aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/llvm/elf_format.erl
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-05-10 17:22:25 +0200
committerMagnus Lång <[email protected]>2016-05-11 13:19:46 +0200
commit0f489445070cf65d96db7938f80ad118921c1f6a (patch)
treeeb31f67e5d9506ab000c3fd547c8f18aa92fadc4 /lib/hipe/llvm/elf_format.erl
parent3dc060d7b6e0f2ea55e6649b23a47d226874b9d4 (diff)
downloadotp-0f489445070cf65d96db7938f80ad118921c1f6a.tar.gz
otp-0f489445070cf65d96db7938f80ad118921c1f6a.tar.bz2
otp-0f489445070cf65d96db7938f80ad118921c1f6a.zip
hipe: Extract some records into elf_format.hrl
This allows for much more robust interpretation of relocations, symbols and sections in hipe_llvm_main, without the clunkiness of an abstract interface between two internal modules that belong to the same subsystem anyway.
Diffstat (limited to 'lib/hipe/llvm/elf_format.erl')
-rw-r--r--lib/hipe/llvm/elf_format.erl140
1 files changed, 56 insertions, 84 deletions
diff --git a/lib/hipe/llvm/elf_format.erl b/lib/hipe/llvm/elf_format.erl
index e56ccce626..4155dff7c4 100644
--- a/lib/hipe/llvm/elf_format.erl
+++ b/lib/hipe/llvm/elf_format.erl
@@ -13,18 +13,16 @@
-module(elf_format).
--export([get_tab_entries/1,
- %% Relocations
- get_rodata_relocs/1,
- get_text_relocs/1,
+-export([%% Relocations
extract_rela/2,
- get_rela_addends/1,
%% Note
extract_note/2,
%% Executable code
extract_text/1,
%% GCC Exception Table
get_exn_handlers/1,
+ %% Symbols
+ elf_symbols/1,
%% Main interface
read/1
]).
@@ -40,14 +38,7 @@
-type lp() :: non_neg_integer(). % landing pad
-type num() :: non_neg_integer().
-type index() :: non_neg_integer().
--type offset() :: non_neg_integer().
--type size() :: non_neg_integer().
-type start() :: non_neg_integer().
--type reloc_type() :: atom().
-
--type valueoff() :: offset().
-
--type name() :: string().
-type tuple(X) :: {} | {X} | {X, X} | tuple().
@@ -91,38 +82,6 @@
}).
%% -type elf_ehdr_ident() :: #elf_ehdr_ident{}.
-%% Section header entries
--record(elf_shdr, {name :: string(), % Section name
- type, % Section type
- flags, % Section attributes
- addr, % Virtual address in memory
- offset :: offset(), % Offset in file
- size :: size(), % Size of section
- link, % Link to other section
- info, % Miscellaneous information
- addralign, % Address align boundary
- entsize % Size of entries, if section has table
- }).
--type elf_shdr() :: #elf_shdr{}.
-
-%% Symbol table entries
--record(elf_sym, {name :: string(), % Symbol name
- info, % Type and Binding attributes
- other, % Reserved
- section :: undefined | abs | elf_shdr(),
- value :: valueoff(), % Symbol value
- size :: size() % Size of object
- }).
--type elf_sym() :: #elf_sym{}.
-
-%% Relocations
--record(elf_rel, {offset :: offset()
- ,type :: reloc_type()
- ,addend :: offset() | undefined
- ,symbol :: elf_sym()
- }).
--type elf_rel() :: #elf_rel{}.
-
%% %% Program header table
%% -record(elf_phdr, {type, % Type of segment
%% flags, % Segment attributes
@@ -201,13 +160,13 @@ mk_shdr(Name, Type, Flags, Addr, Offset, Size, Link, Info, AddrAlign, EntSize) -
%%%-------------------------
%%% Symbol Table Entries
%%%-------------------------
-mk_sym(Name, Info, Other, Section, Value, Size) ->
- #elf_sym{name = Name, info = Info, other = Other,
+mk_sym(Name, Bind, Type, Section, Value, Size) ->
+ #elf_sym{name = Name, bind = Bind, type = Type,
section = Section, value = Value, size = Size}.
--spec sym_name(elf_sym()) -> string().
-sym_name(#elf_sym{name = Name}) -> Name.
-
+%% -spec sym_name(elf_sym()) -> string().
+%% sym_name(#elf_sym{name = Name}) -> Name.
+%%
%% -spec sym_value(elf_sym()) -> valueoff().
%% sym_value(#elf_sym{value = Value}) -> Value.
%%
@@ -327,10 +286,26 @@ get_shdrtab_entries(ShdrTab, ShStrTab) ->
Entsize:?bits(?SH_ENTSIZE_SIZE)/integer-little,
Rest/binary
>> = ShdrTab,
- Entry = mk_shdr(get_strtab_entry(Name, ShStrTab), Type, Flags, Addr, Offset,
- Size, Link, Info, Addralign, Entsize),
+ Entry = mk_shdr(get_strtab_entry(Name, ShStrTab), decode_shdr_type(Type),
+ Flags, Addr, Offset, Size, Link, Info, Addralign, Entsize),
[Entry | get_shdrtab_entries(Rest, ShStrTab)].
+decode_shdr_type(?SHT_NULL) -> 'null';
+decode_shdr_type(?SHT_PROGBITS) -> 'progbits';
+decode_shdr_type(?SHT_SYMTAB) -> 'symtab';
+decode_shdr_type(?SHT_STRTAB) -> 'strtab';
+decode_shdr_type(?SHT_RELA) -> 'rela';
+decode_shdr_type(?SHT_HASH) -> 'hash'; %unused
+decode_shdr_type(?SHT_DYNAMIC) -> 'dynamic'; %unused
+decode_shdr_type(?SHT_NOTE) -> 'note'; %unused
+decode_shdr_type(?SHT_NOBITS) -> 'nobits';
+decode_shdr_type(?SHT_REL) -> 'rel';
+decode_shdr_type(?SHT_SHLIB) -> 'shlib'; %unused
+decode_shdr_type(?SHT_DYNSYM) -> 'dynsym'; %unused
+decode_shdr_type(OS) when ?SHT_LOOS =< OS, OS =< ?SHT_HIOS -> {os, OS};
+decode_shdr_type(Proc) when ?SHT_LOPROC =< Proc, Proc =< ?SHT_HIPROC ->
+ {proc, Proc}.
+
-spec elf_section(non_neg_integer(), elf()) -> undefined | abs | elf_shdr().
elf_section(0, #elf{}) -> undefined;
elf_section(?SHN_ABS, #elf{}) -> abs;
@@ -338,14 +313,6 @@ elf_section(Index, #elf{sec_idx=SecIdx}) when Index =< tuple_size(SecIdx) ->
element(Index, SecIdx).
%%------------------------------------------------------------------------------
-
--spec get_tab_entries(elf()) -> [{name(), valueoff(), size()}].
-get_tab_entries(#elf{sym_idx=SymIdx}) ->
- [{Name, Value, Size div ?ELF_XWORD_SIZE}
- || #elf_sym{name = Name, value = Value, size = Size}
- <- tuple_to_list(SymIdx), Name =/= ""].
-
-%%------------------------------------------------------------------------------
%% Functions to manipulate Symbol Table
%%------------------------------------------------------------------------------
@@ -360,30 +327,51 @@ parse_sym(<<%% Structural pattern matching on fields.
Value:?bits(?ST_VALUE_SIZE)/integer-little,
Size:?bits(?ST_SIZE_SIZE)/integer-little,
Info:?bits(?ST_INFO_SIZE)/integer-little,
- Other:?bits(?ST_OTHER_SIZE)/integer-little,
+ _Other:?bits(?ST_OTHER_SIZE)/integer-little,
Shndx:?bits(?ST_SHNDX_SIZE)/integer-little>>,
Elf, StrTab) ->
- mk_sym(get_strtab_entry(Name, StrTab), Info, Other, elf_section(Shndx, Elf),
- Value, Size).
+ mk_sym(get_strtab_entry(Name, StrTab), decode_symbol_bind(?ELF_ST_BIND(Info)),
+ decode_symbol_type(?ELF_ST_TYPE(Info)), elf_section(Shndx, Elf), Value,
+ Size).
-else.
parse_sym(<<%% Same fields in different order:
Name:?bits(?ST_NAME_SIZE)/integer-little,
Info:?bits(?ST_INFO_SIZE)/integer-little,
- Other:?bits(?ST_OTHER_SIZE)/integer-little,
+ _Other:?bits(?ST_OTHER_SIZE)/integer-little,
Shndx:?bits(?ST_SHNDX_SIZE)/integer-little,
Value:?bits(?ST_VALUE_SIZE)/integer-little,
Size:?bits(?ST_SIZE_SIZE)/integer-little>>,
Elf, StrTab) ->
- mk_sym(get_strtab_entry(Name, StrTab), Info, Other, elf_section(Shndx, Elf),
- Value, Size).
+ mk_sym(get_strtab_entry(Name, StrTab), decode_symbol_bind(?ELF_ST_BIND(Info)),
+ decode_symbol_type(?ELF_ST_TYPE(Info)), elf_section(Shndx, Elf), Value,
+ Size).
-endif.
+decode_symbol_bind(?STB_LOCAL) -> 'local';
+decode_symbol_bind(?STB_GLOBAL) -> 'global';
+decode_symbol_bind(?STB_WEAK) -> 'weak'; %unused
+decode_symbol_bind(OS) when ?STB_LOOS =< OS, OS =< ?STB_HIOS -> {os, OS};
+decode_symbol_bind(Proc) when ?STB_LOPROC =< Proc, Proc =< ?STB_HIPROC ->
+ {proc, Proc}.
+
+decode_symbol_type(?STT_NOTYPE) -> 'notype';
+decode_symbol_type(?STT_OBJECT) -> 'object';
+decode_symbol_type(?STT_FUNC) -> 'func';
+decode_symbol_type(?STT_SECTION) -> 'section';
+decode_symbol_type(?STT_FILE) -> 'file';
+decode_symbol_type(OS) when ?STT_LOOS =< OS, OS =< ?STT_HIOS -> {os, OS};
+decode_symbol_type(Proc) when ?STT_LOPROC =< Proc, Proc =< ?STT_HIPROC ->
+ {proc, Proc}.
+
%% @doc Extracts a specific entry from the Symbol Table.
-spec elf_symbol(0, elf()) -> undefined;
(pos_integer(), elf()) -> elf_sym().
elf_symbol(0, #elf{}) -> undefined;
elf_symbol(Index, #elf{sym_idx=SymIdx}) -> element(Index, SymIdx).
+-spec elf_symbols(elf()) -> [elf_sym()].
+elf_symbols(#elf{sym_idx=SymIdx}) -> tuple_to_list(SymIdx).
+
%%------------------------------------------------------------------------------
%% Functions to manipulate String Table
%%------------------------------------------------------------------------------
@@ -415,22 +403,6 @@ bin_get_string(<<Char, Rest/binary>>) -> [Char|bin_get_string(Rest)].
%% Functions to manipulate Relocations
%%------------------------------------------------------------------------------
-%% @doc This function gets as argument an ELF binary file and returns a list
-%% with all .rela.rodata labels (i.e. constants and literals in code)
-%% or an empty list if no ".rela.rodata" section exists in code.
--spec get_rodata_relocs(elf()) -> [offset()].
-get_rodata_relocs(Elf) -> get_rela_addends(extract_rela(Elf, ?RODATA)).
-
--spec get_rela_addends([elf_rel()]) -> [offset()].
-get_rela_addends(RelaEntries) -> [A || #elf_rel{addend=A} <- RelaEntries].
-
-%% @doc Extract a list of the form `[{SymbolName, Offset}]' with all relocatable
-%% symbols and their offsets in the code from the ".text" section.
--spec get_text_relocs(elf()) -> [{name(), offset()}].
-get_text_relocs(Elf) ->
- [{sym_name(Symbol), Offset}
- || #elf_rel{offset=Offset, symbol=Symbol} <- extract_rela(Elf, ?TEXT)].
-
%% @doc Extract the Relocations segment for section `Name' (that is passed
%% as second argument) from an ELF formated Object file binary.
-spec extract_rela(elf(), name()) -> [elf_rel()].
@@ -442,7 +414,7 @@ extract_rela(Elf, Name) ->
type=decode_reloc_type(?ELF_R_TYPE(Info)),
addend=read_implicit_addend(Offset, SecData)}
|| <<Offset:?bits(?R_OFFSET_SIZE)/little,
- Info:?bits(?R_INFO_SIZE)/little % ELF-32 uses ".rel"
+ Info:?bits(?R_INFO_SIZE)/little % 386 uses ".rel"
>> <= extract_segment_by_name(Elf, ?REL(Name))].
%% The only types HiPE knows how to patch
@@ -451,7 +423,7 @@ decode_reloc_type(2) -> 'pc32'.
read_implicit_addend(Offset, Section) ->
%% All x86 relocation types uses 'word32' relocation fields; i.e. 32-bit LE.
- <<_:Offset/binary, Addend:32/little, _/binary>> = Section,
+ <<_:Offset/binary, Addend:32/signed-little, _/binary>> = Section,
Addend.
-else. %% BIT32
@@ -460,7 +432,7 @@ extract_rela(Elf, Name) ->
type=decode_reloc_type(?ELF_R_TYPE(Info)), addend=Addend}
|| <<Offset:?bits(?R_OFFSET_SIZE)/little,
Info:?bits(?R_INFO_SIZE)/little,
- Addend:?bits(?R_ADDEND_SIZE)/little % ...while ELF-64 uses ".rela"
+ Addend:?bits(?R_ADDEND_SIZE)/signed-little % X86_64 uses ".rela"
>> <= extract_segment_by_name(Elf, ?RELA(Name))].
decode_reloc_type(1) -> '64';