From 0f489445070cf65d96db7938f80ad118921c1f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Tue, 10 May 2016 17:22:25 +0200 Subject: 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. --- lib/hipe/llvm/Makefile | 8 +++ lib/hipe/llvm/elf32_format.hrl | 6 ++ lib/hipe/llvm/elf64_format.hrl | 6 ++ lib/hipe/llvm/elf_format.erl | 140 ++++++++++++++++----------------------- lib/hipe/llvm/elf_format.hrl | 52 +++++++++++++++ lib/hipe/llvm/hipe_llvm_main.erl | 131 +++++++++++++++++++----------------- 6 files changed, 197 insertions(+), 146 deletions(-) diff --git a/lib/hipe/llvm/Makefile b/lib/hipe/llvm/Makefile index d2d39fb9e3..d172e37b02 100644 --- a/lib/hipe/llvm/Makefile +++ b/lib/hipe/llvm/Makefile @@ -108,3 +108,11 @@ release_spec: opt $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin release_docs_spec: + +$(EBIN)/elf_format.beam: elf_format.hrl elf32_format.hrl elf64_format.hrl +$(EBIN)/hipe_llvm_main.beam: ../../kernel/src/hipe_ext_format.hrl \ + hipe_llvm_arch.hrl elf_format.hrl elf32_format.hrl elf64_format.hrl +$(EBIN)/hipe_llvm_merge.beam: ../../kernel/src/hipe_ext_format.hrl \ + hipe_llvm_arch.hrl ../rtl/hipe_literals.hrl ../main/hipe.hrl +$(EBIN)/hipe_rtl_to_llvm.beam: ../rtl/hipe_rtl.hrl ../rtl/hipe_literals.hrl \ + hipe_llvm_arch.hrl diff --git a/lib/hipe/llvm/elf32_format.hrl b/lib/hipe/llvm/elf32_format.hrl index af1d95bf5b..1158cb6434 100644 --- a/lib/hipe/llvm/elf32_format.hrl +++ b/lib/hipe/llvm/elf32_format.hrl @@ -57,3 +57,9 @@ -define(P_MEMSZ_OFFSET, (?P_FILESZ_OFFSET + ?P_FILESZ_SIZE) ). -define(P_FLAGS_OFFSET, (?P_TYPE_OFFSET + ?P_TYPE_SIZE) ). -define(P_ALIGN_OFFSET, (?P_MEMSZ_OFFSET + ?P_MEMSZ_SIZE) ). + +%%------------------------------------------------------------------------------ +%% Exported record and type declarations for 'elf_format' module +%%------------------------------------------------------------------------------ + +-type reloc_type() :: '32' | 'pc32'. diff --git a/lib/hipe/llvm/elf64_format.hrl b/lib/hipe/llvm/elf64_format.hrl index 794746ffdc..0136e7f381 100644 --- a/lib/hipe/llvm/elf64_format.hrl +++ b/lib/hipe/llvm/elf64_format.hrl @@ -56,3 +56,9 @@ -define(P_FILESZ_OFFSET, (?P_PVADDR_OFFSET + ?P_PVADDR_SIZE) ). -define(P_MEMSZ_OFFSET, (?P_FILESZ_OFFSET + ?P_FILESZ_SIZE) ). -define(P_ALIGN_OFFSET, (?P_MEMSZ_OFFSET + ?P_MEMSZ_SIZE) ). + +%%------------------------------------------------------------------------------ +%% Exported record and type declarations for 'elf_format' module +%%------------------------------------------------------------------------------ + +-type reloc_type() :: '64' | 'pc32' | '32'. 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,24 +286,32 @@ 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; 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|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)} || <> <= 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} || <> <= extract_segment_by_name(Elf, ?RELA(Name))]. decode_reloc_type(1) -> '64'; diff --git a/lib/hipe/llvm/elf_format.hrl b/lib/hipe/llvm/elf_format.hrl index 7a3cdfead6..5074682ae6 100644 --- a/lib/hipe/llvm/elf_format.hrl +++ b/lib/hipe/llvm/elf_format.hrl @@ -486,3 +486,55 @@ %% Misc. %%------------------------------------------------------------------------------ -define(bits(Bytes), ((Bytes) bsl 3)). + +%%------------------------------------------------------------------------------ +%% Exported record and type declarations for 'elf_format' module +%%------------------------------------------------------------------------------ + +-type offset() :: non_neg_integer(). +-type size() :: non_neg_integer(). +-type addend() :: integer() | undefined. +-type sym_bind() :: 'local' | 'global' | 'weak' | {os, ?STB_LOOS..?STB_HIOS} + | {proc, ?STB_LOPROC..?STB_HIPROC}. +-type sym_type() :: 'notype' | 'object' | 'func' | 'section' | 'file' + | {os, ?STT_LOOS..?STT_HIOS} + | {proc, ?STT_LOPROC..?STT_HIPROC}. +-type shdr_type() :: 'null' | 'progbits' | 'symtab' | 'strtab' | 'rela' + | 'hash' | 'dynamic' | 'note' | 'nobits' | 'rel' | 'shlib' + | 'dynsym' | {os, ?SHT_LOOS..?SHT_HIOS} + | {proc, ?SHT_LOPROC..?SHT_HIPROC}. + +-type valueoff() :: offset(). +-type name() :: string(). + +%% Section header entries +-record(elf_shdr, {name :: name() % Section name + ,type :: shdr_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 :: name() % Symbol name + ,bind :: sym_bind() % Symbol binding + ,type :: sym_type() % Symbol type + ,value :: valueoff() % Symbol value + ,size :: size() % Size of object + ,section :: undefined | abs | elf_shdr() + }). +-type elf_sym() :: #elf_sym{}. + +%% Relocations +-record(elf_rel, {offset :: offset() + ,type :: reloc_type() + ,addend :: addend() + ,symbol :: elf_sym() + }). +-type elf_rel() :: #elf_rel{}. diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 60833d4af9..3ab213f94c 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -26,11 +26,10 @@ rtl_to_native(MFA, RTL, Roots, Options) -> ObjBin = open_object_file(ObjectFile), Obj = elf_format:read(ObjBin), %% Get labels info (for switches and jump tables) - Labels = elf_format:get_rodata_relocs(Obj), - {Switches, Closures} = get_tables(Obj), + Labels = elf_format:extract_rela(Obj, ?RODATA), + Tables = get_tables(Obj), %% Associate Labels with Switches and Closures with stack args - {SwitchInfos, ExposedClosures} = - correlate_labels(Switches ++ Closures, Labels), + {SwitchInfos, ExposedClosures} = correlate_labels(Tables, Labels), %% SwitchInfos: [{"table_50", [Labels]}] %% ExposedClosures: [{"table_closures", [Labels]}] @@ -38,7 +37,7 @@ rtl_to_native(MFA, RTL, Roots, Options) -> %% used for switch's jump tables LabelMap = create_labelmap(MFA, SwitchInfos, RelocsDict), %% Get relocation info - TextRelocs = elf_format:get_text_relocs(Obj), + TextRelocs = elf_format:extract_rela(Obj, ?TEXT), %% AccRefs contains the offsets of all references to relocatable symbols in %% the code: AccRefs = fix_relocations(TextRelocs, RelocsDict, MFA), @@ -158,12 +157,10 @@ trans_optlev_flag(Tool, Options) -> %%------------------------------------------------------------------------------ %% @doc Get switch table and closure table. +-spec get_tables(elf_format:elf()) -> [elf_sym()]. get_tables(Elf) -> - %% Search Symbol Table for an entry with name prefixed with "table_": - Triples = elf_format:get_tab_entries(Elf), - Switches = [T || T={"table_" ++ _, _, _} <- Triples], - Closures = [T || T={"table_closures" ++ _, _, _} <- Switches], - {Switches, Closures}. + %% Search Symbol Table for entries where name is prefixed with "table_": + [S || S=#elf_sym{name="table_" ++ _} <- elf_format:elf_symbols(Elf)]. %% @doc This function associates symbols who point to some table of labels with %% the corresponding offsets of the labels in the code. These tables can @@ -171,14 +168,12 @@ get_tables(Elf) -> %% of blocks that contain closure calls with more than ?NR_ARG_REGS. correlate_labels([], _L) -> {[], []}; correlate_labels(Tables, Labels) -> - %% Sort "Tables" based on "ValueOffsets" - OffsetSortedTb = lists:ukeysort(2, Tables), - %% Unzip offset-sorted list of "Switches" - {Names, _Offsets, TablesSizeList} = lists:unzip3(OffsetSortedTb), - %% Associate switch names with labels - L = split_list(Labels, TablesSizeList), - %% Zip back! (to [{SwitchName, Values}]) - NamesValues = lists:zip(Names, L), + %% Assumes that the relocations are sorted + RelocTree = gb_trees:from_orddict( + [{Rel#elf_rel.offset, Rel#elf_rel.addend} || Rel <- Labels]), + %% Lookup all relocations pertaining to each symbol + NamesValues = [{Name, lookup_range(Value, Value+Size, RelocTree)} + || #elf_sym{name=Name, value=Value, size=Size} <- Tables], case lists:keytake("table_closures", 1, NamesValues) of false -> %% No closures in the code, no closure table {NamesValues, []}; @@ -186,6 +181,17 @@ correlate_labels(Tables, Labels) -> {SwitchesNV, ClosureTableNV} end. +%% Fetches all values with a key in [Low, Hi) +-spec lookup_range(_::K, _::K, gb_trees:tree(K,V)) -> [_::V]. +lookup_range(Low, Hi, Tree) -> + lookup_range_1(Hi, gb_trees:iterator_from(Low, Tree)). + +lookup_range_1(Hi, Iter0) -> + case gb_trees:next(Iter0) of + {Key, Value, Iter} when Key < Hi -> [Value | lookup_range_1(Hi, Iter)]; + _ -> [] + end. + %% @doc Create a gb_tree which contains information about the labels that used %% for switch's jump tables. The keys of the gb_tree are of the form %% {MFA, Label} and the values are the actual Offsets. @@ -216,37 +222,53 @@ insert_to_labelmap([{Key, Value}|Rest], LabelMap) -> %% @doc Correlate object file relocation symbols with info from translation to %% llvm code. fix_relocations(Relocs, RelocsDict, MFA) -> - fix_relocs(Relocs, RelocsDict, MFA, []). - -fix_relocs([], _, _, RelocAcc) -> RelocAcc; -fix_relocs([{Name, Offset}|Rs], RelocsDict, {ModName,_,_}=MFA, RelocAcc) -> + lists:map(fun(Reloc) -> fix_reloc(Reloc, RelocsDict, MFA) end, Relocs). + +%% Relocation types and expected addends for x86 and amd64 +-define(PCREL_T, 'pc32'). +-define(PCREL_A, -4). %% Hard-coded in hipe_x86.c and hipe_amd64.c +-ifdef(BIT32). +-define(ABS_T, '32'). +-define(ABS_A, _). %% We support any addend +-else. +-define(ABS_T, '64'). +-define(ABS_A, 0). +-endif. + +fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype}, + offset=Offset, type=?PCREL_T, addend=?PCREL_A}, + RelocsDict, {ModName,_,_}) when Name =/= "" -> case dict:fetch(Name, RelocsDict) of - {atom, AtomName} -> - fix_relocs(Rs, RelocsDict, MFA, - [{?LOAD_ATOM, Offset, AtomName}|RelocAcc]); - {constant, Label} -> - fix_relocs(Rs, RelocsDict, MFA, - [{?LOAD_ADDRESS, Offset, {constant, Label}}|RelocAcc]); - {switch, _, JTabLab} -> %% Treat switch exactly as constant - fix_relocs(Rs, RelocsDict, MFA, - [{?LOAD_ADDRESS, Offset, {constant, JTabLab}}|RelocAcc]); - {closure, _}=Closure -> - fix_relocs(Rs, RelocsDict, MFA, - [{?LOAD_ADDRESS, Offset, Closure}|RelocAcc]); - {call, {bif, BifName, _}} -> - fix_relocs(Rs, RelocsDict, MFA, - [{?CALL_LOCAL, Offset, BifName}|RelocAcc]); + {call, {bif, BifName, _}} -> {?CALL_LOCAL, Offset, BifName}; %% MFA calls to functions in the same module are of type 3, while all %% other MFA calls are of type 2. - {call, {ModName,_F,_A}=CallMFA} -> - fix_relocs(Rs, RelocsDict, MFA, - [{?CALL_LOCAL, Offset, CallMFA}|RelocAcc]); - {call, CallMFA} -> - fix_relocs(Rs, RelocsDict, MFA, - [{?CALL_REMOTE, Offset, CallMFA}|RelocAcc]); - Other -> - exit({?MODULE, fix_relocs, - {"Relocation not in relocation dictionary", Other}}) + %% XXX: Does this code break hot code loading (by transforming external + %% calls into local calls?) + {call, {ModName,_F,_A}=CallMFA} -> {?CALL_LOCAL, Offset, CallMFA}; + {call, CallMFA} -> {?CALL_REMOTE, Offset, CallMFA} + end; +fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype}, + offset=Offset, type=?ABS_T, addend=?ABS_A}, + RelocsDict, _) when Name =/= "" -> + case dict:fetch(Name, RelocsDict) of + {atom, AtomName} -> {?LOAD_ATOM, Offset, AtomName}; + {constant, Label} -> {?LOAD_ADDRESS, Offset, {constant, Label}}; + {closure, _}=Closure -> {?LOAD_ADDRESS, Offset, Closure} + end; +fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?TEXT}, + type=func}, + offset=Offset, type=?PCREL_T, addend=?PCREL_A}, + RelocsDict, MFA) when Name =/= "" -> + case dict:fetch(Name, RelocsDict) of + {call, MFA} -> {?CALL_LOCAL, Offset, MFA} + end; +fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?RODATA}, + type=object}, + offset=Offset, type=?ABS_T, addend=?ABS_A}, + RelocsDict, _) when Name =/= "" -> + case dict:fetch(Name, RelocsDict) of + {switch, _, JTabLab} -> %% Treat switch exactly as constant + {?LOAD_ADDRESS, Offset, {constant, JTabLab}} end. %%------------------------------------------------------------------------------ @@ -278,7 +300,7 @@ get_sdescs(Elf) -> Roots/binary>> = NoteGC_bin, LiveRoots = get_liveroots(Roots, []), %% Extract the safe point offsets: - SPOffs = elf_format:get_rela_addends(RelaNoteGC), + SPOffs = [A || #elf_rel{addend=A} <- RelaNoteGC], %% Extract Exception Handler labels: ExnHandlers = elf_format:get_exn_handlers(Elf), %% Combine ExnHandlers and Safe point addresses (return addresses): @@ -476,18 +498,3 @@ unique_folder(FunName, Arity, Options) -> dir_exists(Filename) -> {Flag, Info} = file:read_file_info(Filename), (Flag =:= ok) andalso (element(3, Info) =:= directory). - -%% @doc Function that takes as arguments a list of integers and a list with -%% numbers indicating how many items should each tuple have and splits -%% the original list to a list of lists of integers (with the specified -%% number of elements), i.e. [ [...], [...] ]. --spec split_list([integer()], [integer()]) -> [ [integer()] ]. -split_list(List, ElemsPerTuple) -> - split_list(List, ElemsPerTuple, []). - --spec split_list([integer()], [integer()], [ [integer()] ]) -> [ [integer()] ]. -split_list([], [], Acc) -> - lists:reverse(Acc); -split_list(List, [NumOfElems | MoreNums], Acc) -> - {L1, L2} = lists:split(NumOfElems, List), - split_list(L2, MoreNums, [ L1 | Acc]). -- cgit v1.2.3