mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-24 03:18:22 +00:00
as: handle .section directive
This commit is contained in:
parent
72df4dc2b3
commit
14184eb4cd
@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% input processing phase for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@ -93,6 +93,7 @@ pass1_stmt(Location, Ctx, Stmt) ->
|
||||
#s_dot_popsection{} -> dot_popsection(Location, Ctx, Stmt);
|
||||
#s_dot_previous{} -> dot_previous(Location, Ctx, Stmt);
|
||||
#s_dot_pushsection{} -> dot_pushsection(Location, Ctx, Stmt);
|
||||
#s_dot_section{} -> dot_section(Location, Ctx, Stmt);
|
||||
#s_dot_subsection{} -> dot_subsection(Location, Ctx, Stmt);
|
||||
#s_dot_text{} -> dot_text(Location, Ctx, Stmt);
|
||||
_ -> {ok, ctx_append(Ctx, Location, Stmt)}
|
||||
@ -117,6 +118,16 @@ dot_pushsection(Location, Ctx,
|
||||
#s_dot_pushsection{name = SectionName, nr = SubsectionNr}) ->
|
||||
ctx_pushsection(Ctx, Location, SectionName, SubsectionNr).
|
||||
|
||||
dot_section(Location, Ctx, Stmt) ->
|
||||
#s_dot_section{ name = SectionName
|
||||
, nr = SubsectionNrOpt
|
||||
, sh_flags = ShFlags
|
||||
, sh_type = ShType
|
||||
, sh_entsize = ShEntSize
|
||||
} = Stmt,
|
||||
ctx_section(Ctx, Location, SectionName, SubsectionNrOpt,
|
||||
ShFlags, ShType, ShEntSize).
|
||||
|
||||
dot_subsection(_Location, Ctx, #s_dot_subsection{nr = SubsectionNr}) ->
|
||||
{ok, ctx_subsection(Ctx, SubsectionNr)}.
|
||||
|
||||
@ -201,6 +212,36 @@ ctx_pushsection(Ctx0, Location, SectionName, SubsectionNr) -> % implements .push
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
ctx_section(Ctx0, Location, SectionName, SubsectionNrOpt,
|
||||
ShFlags, ShType, ShEntSize) ->
|
||||
{IsPushsection, SubsectionNr} =
|
||||
case SubsectionNrOpt of
|
||||
false -> {false, 0};
|
||||
_ -> {true, SubsectionNrOpt}
|
||||
end,
|
||||
Ctx = ctx_flush(Ctx0),
|
||||
#ctx{ sections_map = SectionsMap0
|
||||
, stack = Stack
|
||||
, current = Current
|
||||
, previous = Previous
|
||||
} = Ctx,
|
||||
case enter_section(Location, SectionName, SubsectionNr, SectionsMap0,
|
||||
ShFlags, ShType, ShEntSize) of
|
||||
{ok, {Stmts, SectionsMap}} ->
|
||||
NewStack =
|
||||
case IsPushsection of
|
||||
true -> [{Current, Previous} | Stack];
|
||||
false -> Stack
|
||||
end,
|
||||
{ok, Ctx#ctx{ sections_map = SectionsMap
|
||||
, stack = NewStack
|
||||
, current = {SectionName, SubsectionNr}
|
||||
, previous = Current
|
||||
, stmts = Stmts
|
||||
}};
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
ctx_subsection(Ctx0, SubsectionNr) -> % implements .subsection <nr>
|
||||
Ctx = ctx_flush(Ctx0),
|
||||
#ctx{ sections_map = SectionsMap
|
||||
@ -236,21 +277,118 @@ ctx_append(Ctx, Location, Stmt) ->
|
||||
#ctx{stmts = Stmts} = Ctx,
|
||||
Ctx#ctx{stmts = [{Location, Stmt} | Stmts]}.
|
||||
|
||||
enter_section(Location, SectionName, SubsectionNr, SectionsMap0) ->
|
||||
case maps:get(SectionName, SectionsMap0, false) of
|
||||
enter_section(Location, SectionName, SubsectionNr, SectionsMap) ->
|
||||
enter_section(Location, SectionName, SubsectionNr, SectionsMap,
|
||||
_ShFlags = 0, _ShType = 0, _ShEntSize = 0).
|
||||
|
||||
enter_section(Location, SectionName, SubsectionNr, SectionsMap0,
|
||||
ShFlags, ShType, ShEntSize) ->
|
||||
{Section0, SubsectionsMap} = get_section(SectionName, SectionsMap0),
|
||||
case update_section(Location, Section0, ShFlags, ShType, ShEntSize) of
|
||||
{ok, Section} ->
|
||||
SectionsMap = maps:put(SectionName, {Section, SubsectionsMap}, SectionsMap0),
|
||||
Stmts = maps:get(SubsectionNr, SubsectionsMap, []),
|
||||
{ok, {Stmts, SectionsMap}};
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
get_section(SectionName, SectionsMap) ->
|
||||
case maps:get(SectionName, SectionsMap, false) of
|
||||
{_Section, _SubsectionsMap} = Result -> Result;
|
||||
false ->
|
||||
case section_from_name(SectionName) of
|
||||
false ->
|
||||
fmterr(Location, "unknown section ~s", [SectionName]);
|
||||
Section = #section{} ->
|
||||
#section{} = Section ->
|
||||
SubsectionsMap = #{},
|
||||
SectionsMap = maps:put(SectionName, {Section, SubsectionsMap}, SectionsMap0),
|
||||
Stmts = [],
|
||||
{ok, {Stmts, SectionsMap}}
|
||||
{Section, SubsectionsMap};
|
||||
false ->
|
||||
Section = make_section(SectionName),
|
||||
SubsectionsMap = #{},
|
||||
{Section, SubsectionsMap}
|
||||
end
|
||||
end.
|
||||
|
||||
make_section(SectionName) ->
|
||||
%% update_section/5 will set sh_flags, sh_type, and sh_entsize
|
||||
#section{ name = SectionName
|
||||
, data = {stmts, []}
|
||||
, dot = 0
|
||||
, shndx = 0
|
||||
, sh_name = 0
|
||||
, sh_type = 0
|
||||
, sh_offset = 0
|
||||
, sh_flags = 0
|
||||
, sh_link = ?SHN_UNDEF
|
||||
, sh_addralign = 0
|
||||
, sh_entsize = 0
|
||||
}.
|
||||
|
||||
update_section(Location, Section0, ShFlags, ShType, ShEntSize) ->
|
||||
case update_sh_flags(Location, Section0, ShFlags) of
|
||||
{ok, Section1} ->
|
||||
case update_sh_type(Location, Section1, ShType) of
|
||||
{ok, Section2} ->
|
||||
update_sh_entsize(Location, Section2, ShEntSize);
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{_Section, SubsectionsMap} ->
|
||||
Stmts = maps:get(SubsectionNr, SubsectionsMap, []),
|
||||
{ok, {Stmts, SectionsMap0}}
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
update_sh_flags(Location, Section, ShFlags) ->
|
||||
case ShFlags of
|
||||
0 -> {ok, Section};
|
||||
_ ->
|
||||
case Section#section.sh_flags of
|
||||
0 -> {ok, Section#section{sh_flags = ShFlags}};
|
||||
ShFlags -> {ok, Section};
|
||||
ShFlags0 ->
|
||||
case may_update_sh_flags(Section, ShFlags) of
|
||||
true -> {ok, Section#section{sh_flags = ShFlags0 bor ShFlags}};
|
||||
false -> fmterr(Location, "cannot change section flags", [])
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
may_update_sh_flags(Section, ShFlags) ->
|
||||
%% Processor and application-specific flags may be added to an existing
|
||||
%% section. The range of application-specific flags isn't defined in the
|
||||
%% ELF spec: we interpret that as any flag outside of the reserved ranges.
|
||||
ReservedMask = (?SHF_COMPRESSED * 2 - 1) bor ?SHF_MASKOS,
|
||||
case (ShFlags band ReservedMask) =:= 0 of
|
||||
true -> true;
|
||||
false ->
|
||||
case ShFlags of
|
||||
?SHF_ALLOC ->
|
||||
case Section#section.name of
|
||||
".interp" -> true;
|
||||
".strtab" -> true;
|
||||
".symtab" -> true;
|
||||
_ -> false
|
||||
end;
|
||||
?SHF_EXECINSTR -> Section#section.name =:= ".note.GNU-stack";
|
||||
_ -> false
|
||||
end
|
||||
end.
|
||||
|
||||
update_sh_type(Location, Section, ShType) ->
|
||||
case ShType of
|
||||
0 -> {ok, Section};
|
||||
_ ->
|
||||
case Section#section.sh_type of
|
||||
0 -> {ok, Section#section{sh_type = ShType}};
|
||||
ShType -> {ok, Section};
|
||||
_ -> fmterr(Location, "cannot change section type", [])
|
||||
end
|
||||
end.
|
||||
|
||||
update_sh_entsize(Location, Section, ShEntSize) ->
|
||||
case ShEntSize of
|
||||
0 -> {ok, Section};
|
||||
_ ->
|
||||
case Section#section.sh_entsize of
|
||||
0 -> {ok, Section#section{sh_entsize = ShEntSize}};
|
||||
ShEntSize -> {ok, Section};
|
||||
_ -> fmterr(Location, "cannot change section element size", [])
|
||||
end
|
||||
end.
|
||||
|
||||
enter_subsection(SectionName, SubsectionNr, SectionsMap) ->
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% parser for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@ -27,6 +27,7 @@
|
||||
-include("token.hrl").
|
||||
-include("tunit.hrl").
|
||||
-include_lib("lib/include/pdp10_opcodes.hrl").
|
||||
-include_lib("lib/include/pdp10_elf36.hrl").
|
||||
|
||||
-type location() :: scan:location().
|
||||
|
||||
@ -46,6 +47,7 @@ stmt(ScanState) ->
|
||||
{ok, {Location, ?T_DOT_POPSECTION}} -> dot_popsection(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_PREVIOUS}} -> dot_previous(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_PUSHSECTION}} -> dot_pushsection(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_SECTION}} -> dot_section(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_SHORT}} -> dot_short(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_SIZE}} -> dot_size(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_SUBSECTION}} -> dot_subsection(ScanState, Location);
|
||||
@ -478,6 +480,177 @@ dot_type(ScanState, Location) ->
|
||||
dot_word(ScanState, Location) ->
|
||||
dot_long(ScanState, Location, ".word").
|
||||
|
||||
%% .section/.pushsection directives --------------------------------------------
|
||||
%%
|
||||
%% .section <name> <sectionspec>
|
||||
%% .pushsection <name> [, <nr>] <sectionspec>
|
||||
%%
|
||||
%% <sectionspec> ::= [, <flags> [, <type>]]
|
||||
%% | , <flags>, <type>, <entsize> (if <flags> contain M)
|
||||
%%
|
||||
%% <flags> ::= '"' <flagschar>* '"'
|
||||
%% <flagschar> ::= [adexwMST0-9]
|
||||
%%
|
||||
%% <type> ::= "@progbits" | "@nobits" | "@note" | "@init_array" | "@fini_array"
|
||||
%% | "@preinit_array"
|
||||
%%
|
||||
%% TODO: add support for "G" and "?" flags, and <groupname> and <linkage> specs:
|
||||
%%
|
||||
%% <sectionspec> ::= , <flags>, <type>, <groupname> [, <linkage>] (if <flags> contain G)
|
||||
%% | , <flags>, <type>, <entsize>, <groupname> [, <linkage>] (if <flags> contain both M and G)
|
||||
%%
|
||||
%% <linkage> ::= "comdat" | ".gnu.linkonce"
|
||||
|
||||
dot_section(ScanState, Location) ->
|
||||
dot_section_name(ScanState, Location, _IsPushsection = false).
|
||||
|
||||
dot_section_name(ScanState, Location, IsPushsection) ->
|
||||
case section_name(ScanState) of
|
||||
{ok, Name} -> dot_section_subsection(ScanState, Location, Name, IsPushsection);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
dot_section_subsection(ScanState, Location, Name, IsPushsection) ->
|
||||
case IsPushsection of
|
||||
true ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location1, ?T_NEWLINE}} ->
|
||||
dot_section_finish(Location, Name, _Nr = 0, _ShFlags = 0, _ShType = 0, _ShEntSize = 0);
|
||||
{ok, {_Location1, ?T_COMMA}} ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location2, {?T_UINTEGER, Nr}}} ->
|
||||
dot_section_flags(ScanState, Location, Name, Nr);
|
||||
ScanRes ->
|
||||
dot_section_flags(ScanState, Location, Name, _Nr = 0, ScanRes)
|
||||
end;
|
||||
ScanRes -> badtok("expected comma or newline", ScanRes)
|
||||
end;
|
||||
false -> dot_section_flags(ScanState, Location, Name, _Nr = false)
|
||||
end.
|
||||
|
||||
dot_section_flags(ScanState, Location, Name, Nr) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, ?T_NEWLINE}} ->
|
||||
dot_section_finish(Location, Name, Nr, _ShFlags = 0, _ShType = 0, _ShEntSize = 0);
|
||||
{ok, {_Location, ?T_COMMA}} ->
|
||||
dot_section_flags(ScanState, Location, Name, Nr, scan:token(ScanState));
|
||||
ScanRes -> badtok("expected comma or newline", ScanRes)
|
||||
end.
|
||||
|
||||
dot_section_flags(ScanState, Location, Name, Nr, ScanRes) ->
|
||||
case ScanRes of
|
||||
{ok, {_Location, {?T_STRING, String}}} ->
|
||||
case sh_flags(String) of
|
||||
{ok, ShFlags} -> dot_section_type(ScanState, Location, Name, Nr, ShFlags);
|
||||
false -> badtok("invalid <flags>", ScanRes)
|
||||
end;
|
||||
_ -> badtok("expected <string>", ScanRes)
|
||||
end.
|
||||
|
||||
sh_flags(String) -> sh_flags(String, 0).
|
||||
|
||||
sh_flags([], ShFlags) -> {ok, ShFlags};
|
||||
sh_flags([C | Cs] = String, ShFlags) ->
|
||||
case sh_flag(C) of
|
||||
false ->
|
||||
case strtol:parse(String, _Base = 10) of
|
||||
{ok, {Mask, Rest}} -> sh_flags(Rest, ShFlags bor Mask);
|
||||
{error, _Reason} -> false
|
||||
end;
|
||||
Flag -> sh_flags(Cs, ShFlags bor Flag)
|
||||
end.
|
||||
|
||||
sh_flag(C) ->
|
||||
case C of
|
||||
$a -> ?SHF_ALLOC;
|
||||
$d -> ?SHF_GNU_MBIND;
|
||||
$e -> ?SHF_EXCLUDE;
|
||||
$w -> ?SHF_WRITE;
|
||||
$x -> ?SHF_EXECINSTR;
|
||||
$M -> ?SHF_MERGE;
|
||||
$S -> ?SHF_STRINGS;
|
||||
$T -> ?SHF_TLS;
|
||||
%% TODO: permit $G and $?
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
dot_section_type(ScanState, Location, Name, Nr, ShFlags) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location1, ?T_NEWLINE}} = ScanRes ->
|
||||
case (ShFlags band (?SHF_MERGE bor ?SHF_GROUP)) =/= 0 of
|
||||
true -> badtok("expected ,@type", ScanRes);
|
||||
false ->
|
||||
dot_section_finish(Location, Name, Nr, ShFlags, _ShType = 0, _ShEntSize = 0)
|
||||
end;
|
||||
{ok, {_Location1, ?T_COMMA}} ->
|
||||
case sh_type(ScanState) of
|
||||
{ok, ShType} -> dot_section_entsize(ScanState, Location, Name, Nr, ShFlags, ShType);
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
ScanRes -> badtok("expected comma or newline", ScanRes)
|
||||
end.
|
||||
|
||||
sh_type(ScanState) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location1, ?T_AT}} ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location2, {?T_SYMBOL, Name}}} = ScanRes ->
|
||||
case Name of
|
||||
"progbits" -> {ok, ?SHT_PROGBITS};
|
||||
"nobits" -> {ok, ?SHT_NOBITS};
|
||||
"note" -> {ok, ?SHT_NOTE};
|
||||
"init_array" -> {ok, ?SHT_INIT_ARRAY};
|
||||
"fini_array" -> {ok, ?SHT_FINI_ARRAY};
|
||||
"preinit_array" -> {ok, ?SHT_PREINIT_ARRAY};
|
||||
_ -> badtok("invalid @type", ScanRes)
|
||||
end;
|
||||
{ok, {_Location2, {?T_UINTEGER, ShType}}} -> {ok, ShType};
|
||||
ScanRes -> badtok("expected <symbol> or <uinteger>", ScanRes)
|
||||
end;
|
||||
ScanRes -> badtok("expected @type", ScanRes)
|
||||
end.
|
||||
|
||||
dot_section_entsize(ScanState, Location, Name, Nr, ShFlags, ShType) ->
|
||||
case (ShFlags band ?SHF_MERGE) =/= 0 of
|
||||
true ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location1, ?T_COMMA}} ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location2, {?T_UINTEGER, ShEntSize}}} ->
|
||||
dot_section_newline(ScanState, Location, Name, Nr, ShFlags, ShType, ShEntSize);
|
||||
ScanRes -> badtok("expected <uinteger>", ScanRes)
|
||||
end;
|
||||
ScanRes -> badtok("expected ,<entsize>", ScanRes)
|
||||
end;
|
||||
false ->
|
||||
dot_section_newline(ScanState, Location, Name, Nr, ShFlags, ShType, _ShEntSize = 0)
|
||||
end.
|
||||
|
||||
dot_section_newline(ScanState, Location, Name, Nr, ShFlags, ShType, ShEntSize) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, ?T_NEWLINE}} ->
|
||||
dot_section_finish(Location, Name, Nr, ShFlags, ShType, ShEntSize);
|
||||
ScanRes -> badtok("expected <newline>", ScanRes)
|
||||
end.
|
||||
|
||||
dot_section_finish(Location, Name, Nr, ShFlags, ShType, ShEntSize) ->
|
||||
{ok, {Location, #s_dot_section{ name = Name
|
||||
, nr = Nr
|
||||
, sh_type = ShType
|
||||
, sh_flags = ShFlags
|
||||
, sh_entsize = ShEntSize
|
||||
}}}.
|
||||
|
||||
section_name(ScanState) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, {?T_STRING, Name}}} -> {ok, Name};
|
||||
{ok, {_Location, {?T_SYMBOL, Name}}} -> {ok, Name};
|
||||
%% TODO: do we need a general mapping from reserved to plain symbols?
|
||||
{ok, {_Location, ?T_DOT_DATA}} -> {ok, ".data"};
|
||||
{ok, {_Location, ?T_DOT_TEXT}} -> {ok, ".text"};
|
||||
ScanRes -> badtok("invalid section name", ScanRes)
|
||||
end.
|
||||
|
||||
%% Expressions -----------------------------------------------------------------
|
||||
|
||||
%% <expr_list> ::= (<expr> ("," <expr>)*)?
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% token handling for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@ -41,6 +41,7 @@ from_symbol(Name) ->
|
||||
".popsection" -> ?T_DOT_POPSECTION;
|
||||
".previous" -> ?T_DOT_PREVIOUS;
|
||||
".pushsection" -> ?T_DOT_PUSHSECTION;
|
||||
".section" -> ?T_DOT_SECTION;
|
||||
".short" -> ?T_DOT_SHORT;
|
||||
".size" -> ?T_DOT_SIZE;
|
||||
".subsection" -> ?T_DOT_SUBSECTION;
|
||||
@ -65,6 +66,7 @@ format(Token) ->
|
||||
?T_DOT_POPSECTION -> ".popsection";
|
||||
?T_DOT_PREVIOUS -> ".previous";
|
||||
?T_DOT_PUSHSECTION -> ".pushsection";
|
||||
?T_DOT_SECTION -> ".section";
|
||||
?T_DOT_SHORT -> ".short";
|
||||
?T_DOT_SIZE -> ".size";
|
||||
?T_DOT_SUBSECTION -> ".subsection";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% token definitions for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@ -38,6 +38,7 @@
|
||||
-define(T_DOT_POPSECTION, 'T_DOT_POPSECTION'). % .popsection
|
||||
-define(T_DOT_PREVIOUS, 'T_DOT_PREVIOUS'). % .previous
|
||||
-define(T_DOT_PUSHSECTION, 'T_DOT_PUSHSECTION'). % .pushsection
|
||||
-define(T_DOT_SECTION, 'T_DOT_SECTION'). % .section
|
||||
-define(T_DOT_SHORT, 'T_DOT_SHORT'). % .short
|
||||
-define(T_DOT_SIZE, 'T_DOT_SIZE'). % .size
|
||||
-define(T_DOT_SUBSECTION, 'T_DOT_SUBSECTION'). % .subsection
|
||||
@ -78,6 +79,7 @@
|
||||
| ?T_DOT_POPSECTION
|
||||
| ?T_DOT_PREVIOUS
|
||||
| ?T_DOT_PUSHSECTION
|
||||
| ?T_DOT_SECTION
|
||||
| ?T_DOT_SHORT
|
||||
| ?T_DOT_SIZE
|
||||
| ?T_DOT_SUBSECTION
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% translation unit declarations for pdp10-elf as.
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@ -66,6 +66,19 @@
|
||||
%% .pushsection name [, nr] (TODO: extend)
|
||||
-record(s_dot_pushsection, {name :: string(), nr :: non_neg_integer()}).
|
||||
|
||||
%% .section name, "flags", @type, ...
|
||||
%% .pushsection name, [, nr], "flags", @type, ...
|
||||
%% TODO: add support for G and ? flags and ,<group>,<linkage>
|
||||
-record(s_dot_section,
|
||||
{ name :: string()
|
||||
%% nr is false for .section and a subsection number for .pushsection
|
||||
, nr :: false | non_neg_integer()
|
||||
%% the following are as per the Elf36 Shdr spec
|
||||
, sh_type :: non_neg_integer()
|
||||
, sh_flags :: non_neg_integer()
|
||||
, sh_entsize :: non_neg_integer()
|
||||
}).
|
||||
|
||||
%% .short [expr (, expr)*]
|
||||
-record(s_dot_short, {exprs :: [expr()]}).
|
||||
|
||||
@ -102,6 +115,7 @@
|
||||
| #s_dot_popsection{}
|
||||
| #s_dot_previous{}
|
||||
| #s_dot_pushsection{}
|
||||
| #s_dot_section{}
|
||||
| #s_dot_size{}
|
||||
| #s_dot_subsection{}
|
||||
| #s_dot_text{}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user