From 522b7101cae9cbacff2e60399a795297df7d2d5c Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Mon, 14 Aug 2023 15:05:59 +0200 Subject: [PATCH] ld_symtab: cleanups --- erlang/apps/ld/src/ld_symtab.erl | 84 +++++++++++++++++++------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/erlang/apps/ld/src/ld_symtab.erl b/erlang/apps/ld/src/ld_symtab.erl index 242114e..7bb4a62 100644 --- a/erlang/apps/ld/src/ld_symtab.erl +++ b/erlang/apps/ld/src/ld_symtab.erl @@ -1,7 +1,7 @@ %%% -*- erlang-indent-level: 2 -*- %%% -%%% symbol table for pdp10-elf-ld -%%% Copyright (C) 2020 Mikael Pettersson +%%% Build symbol tables for pdp10-elf ld +%%% Copyright (C) 2020-2023 Mikael Pettersson %%% %%% This file is part of pdp10-tools. %%% @@ -17,6 +17,12 @@ %%% %%% You should have received a copy of the GNU General Public License %%% along with pdp10-tools. If not, see . +%%% +%%%============================================================================= +%%% +%%% The segments have now been assigned load addresses. Scan the inputs and: +%%% - build a GlobalMap mapping each global symbol to its value +%%% - build a FileMap mapping each input file to its local symbol table -module(ld_symtab). @@ -25,34 +31,16 @@ -include("ld_internal.hrl"). +-type frag() :: {ifile(), ShNdx :: non_neg_integer()}. +-type fragmap() :: #{frag() => non_neg_integer()}. + %% Build Symbol Tables ========================================================= -spec build([#input{}], [#segment{}]) -> {global(), filemap()}. build(Inputs, Segments) -> - FragMap = scan_segments(Segments), + FragMap = build_fragmap(Segments), scan_inputs(Inputs, FragMap). -%% Scan all segments, which now have load addresses assigned, and record -%% the load address for every included fragment (file and section). -scan_segments(Segments) -> - lists:foldl(fun scan_segment/2, _FragMap = maps:new(), Segments). - -scan_segment(#segment{phdr = Phdr, sections = Sections}, FragMap0) -> - #elf36_Phdr{p_vaddr = SegmentBase} = Phdr, - lists:foldl(fun(Section, FragMap) -> - scan_section(Section, FragMap, SegmentBase) - end, FragMap0, Sections). - -scan_section(#section{shdr = Shdr, frags = Frags}, FragMap0, SegmentBase) -> - #elf36_Shdr{sh_offset = SectionOffset} = Shdr, - SectionBase = SegmentBase + SectionOffset, - lists:foldl(fun(Frag, FragMap) -> - scan_frag(Frag, FragMap, SectionBase) - end, FragMap0, Frags). - -scan_frag(#sectfrag{file = File, shndx = ShNdx, offset = SectionOffset}, FragMap, SectionBase) -> - maps:put({File, ShNdx}, SectionBase + SectionOffset, FragMap). - %% Scan all input files, whose segments now have load addresses in FragMap, %% build a symbol table for each file, and update the global symbol table. scan_inputs(Inputs, FragMap) -> @@ -62,16 +50,19 @@ scan_inputs(Inputs, FragMap) -> scan_input(Input, GlobalMap0, FileMap, FragMap) -> #input{file = File, symtab = Syms} = Input, - {GlobalMap, SymTab} = scan_syms(Syms, _ShNdx = 0, File, FragMap, GlobalMap0, _SymTab = maps:new()), - {GlobalMap, maps:put(File, SymTab, FileMap)}. + {GlobalMap, LocalSymTab} = scan_syms(Syms, File, FragMap, GlobalMap0), + {GlobalMap, maps:put(File, LocalSymTab, FileMap)}. -scan_syms([], _SymNdx, _File, _FragMap, GlobalMap, SymTab) -> - {GlobalMap, SymTab}; -scan_syms([Sym | Syms], SymNdx, File, FragMap, GlobalMap, SymTab) -> - {NewGlobalMap, NewSymTab} = scan_sym(Sym, SymNdx, File, FragMap, GlobalMap, SymTab), - scan_syms(Syms, SymNdx + 1, File, FragMap, NewGlobalMap, NewSymTab). +scan_syms(Syms, File, FragMap, GlobalMap) -> + {_LocalSymNdx, NewGlobalMap, LocalSymTab} = + lists:foldl( + fun(Sym, {SymNdx1, GlobalMap1, SymTab1}) -> + {GlobalMap2, SymTab2} = enter_sym(Sym, SymNdx1, File, FragMap, GlobalMap1, SymTab1), + {SymNdx1 + 1, GlobalMap2, SymTab2} + end, {_SymNdx = 0, GlobalMap, _SymTab = maps:new()}, Syms), + {NewGlobalMap, LocalSymTab}. -scan_sym(Sym, SymNdx, File, FragMap, GlobalMap0, SymTab0) -> +enter_sym(Sym, SymNdx, File, FragMap, GlobalMap0, SymTab0) -> #elf36_Sym{st_name = Name, st_value = Value, st_info = Info, st_shndx = ShNdx} = Sym, true = is_list(Name), % assert in-core name is string() SymVal = @@ -90,8 +81,31 @@ scan_sym(Sym, SymNdx, File, FragMap, GlobalMap0, SymTab0) -> SymTab = maps:put(SymNdx, SymVal, SymTab0), GlobalMap = case ?ELF36_ST_BIND(Info) of - ?STB_GLOBAL when ShNdx =/= ?SHN_UNDEF -> maps:put(Name, SymVal, GlobalMap0); - ?STB_GLOBAL -> GlobalMap0; - ?STB_LOCAL -> GlobalMap0 + ?STB_LOCAL -> GlobalMap0; + ?STB_GLOBAL when ShNdx =:= ?SHN_UNDEF -> GlobalMap0; + ?STB_GLOBAL -> maps:put(Name, SymVal, GlobalMap0) end, {GlobalMap, SymTab}. + +%% Build fragment map ========================================================== +%% +%% Scan all segments, which now have load addresses assigned, and record +%% the load address for every included fragment (file and section). + +-spec build_fragmap([#segment{}]) -> fragmap(). +build_fragmap(Segments) -> + lists:foldl(fun scan_segment/2, _FragMap = maps:new(), Segments). + +scan_segment(#segment{phdr = #elf36_Phdr{p_vaddr = SegmentBase}, sections = Sections}, FragMap0) -> + lists:foldl(fun(Section, FragMap) -> + scan_section(Section, FragMap, SegmentBase) + end, FragMap0, Sections). + +scan_section(#section{shdr = #elf36_Shdr{sh_offset = SectionOffset}, frags = Frags}, FragMap0, SegmentBase) -> + SectionBase = SegmentBase + SectionOffset, + lists:foldl(fun(Frag, FragMap) -> + enter_frag(Frag, FragMap, SectionBase) + end, FragMap0, Frags). + +enter_frag(#sectfrag{file = File, shndx = ShNdx, offset = SectionOffset}, FragMap, SectionBase) -> + maps:put({File, ShNdx}, SectionBase + SectionOffset, FragMap).