From f6096ec45c2da3bf87f5669db1175b3d9721a7b2 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 9 Aug 2023 20:49:05 +0200 Subject: [PATCH] ld_input: add support for archives --- erlang/apps/ld/src/ld_input.erl | 67 ++++++++++++++++++++++++++++-- erlang/apps/ld/src/ld_internal.hrl | 11 ++++- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/erlang/apps/ld/src/ld_input.erl b/erlang/apps/ld/src/ld_input.erl index 9549298..7bab34c 100644 --- a/erlang/apps/ld/src/ld_input.erl +++ b/erlang/apps/ld/src/ld_input.erl @@ -17,6 +17,19 @@ %%% %%% You should have received a copy of the GNU General Public License %%% along with pdp10-tools. If not, see . +%%% +%%%============================================================================= +%%% +%%% - Process input files in the order given. +%%% - Maintain sets of currently defined and undefined symbols, initially empty +%%% and the entry symbol, respectiively. +%%% - An input object file is included unconditionally. Its symbol table is read +%%% and the sets of defined and undefined symbols are updated accordingly. +%%% - An input archive has its members processed in the order stored. +%%% - An input archive member is included if any only if the archive's symbol table +%%% indicates that the member defines some currently undefined symbol. +%%% - If an archive member is included it is processed exactly like an explicit +%%% input object file. -module(ld_input). @@ -25,6 +38,8 @@ ]). -include("ld_internal.hrl"). +-include_lib("lib/include/archive.hrl"). +-include_lib("lib/include/pdp10_ar.hrl"). %% error reasons -define(badelf, badelf). @@ -55,14 +70,58 @@ input([], _DefMap, UndefMap, Inputs) -> end. input_file(File, DefMap, UndefMap, Inputs) -> - case pdp10_stdio:fopen(File, [raw, read]) of - {ok, FP} -> + case archive:read(File) of + {ok, {FP, Archive}} -> try - input_elf(File, FP, DefMap, UndefMap, Inputs) + input_archive(File, FP, Archive, DefMap, UndefMap, Inputs) after pdp10_stdio:fclose(FP) end; - {error, Reason} -> mkerror({?badfile, File, Reason}) + {error, _} -> + case pdp10_stdio:fopen(File, [raw, read]) of + {ok, FP} -> + try + input_elf(File, FP, DefMap, UndefMap, Inputs) + after + pdp10_stdio:fclose(FP) + end; + {error, Reason} -> mkerror({?badfile, File, Reason}) + end + end. + +%% Process input archive ======================================================= + +input_archive(File, FP, Archive, DefMap, UndefMap, Inputs) -> + #archive{symtab = SymTab, members = Members} = Archive, + %% Build a mapping from member offset to the set of symbols defined there. + OffsetToDefs = + lists:foldl( + fun({Symbol, Offset}, Map) -> + Symbols = maps:get(Offset, Map, #{}), + maps:put(Offset, maps:put(Symbol, false, Symbols), Map) + end, maps:new(), SymTab), + input_archive(Members, OffsetToDefs, File, FP, DefMap, UndefMap, Inputs). + +input_archive(_Members = [], _OffsetToDefs, _File, _FP, DefMap, UndefMap, Inputs) -> + {ok, {DefMap, UndefMap, Inputs}}; +input_archive([Member | Members], OffsetToDefs, File, FP, DefMap, UndefMap, Inputs) -> + case input_member(Member, OffsetToDefs, File, FP, DefMap, UndefMap) of + false -> + input_archive(Members, OffsetToDefs, File, FP, DefMap, UndefMap, Inputs); + {ok, {NewDefMap, NewUndefMap, Input}} -> + input_archive(Members, OffsetToDefs, File, FP, NewDefMap, NewUndefMap, [Input | Inputs]); + {error, _Reason} = Error -> Error + end. + +input_member(Member, OffsetToDefs, File, FP, DefMap, UndefMap) -> + #member{arhdr = ArHdr, location = HdrOffset} = Member, + MemberDefs = maps:get(HdrOffset, OffsetToDefs, #{}), + case maps:size(maps:intersect(MemberDefs, UndefMap)) of + 0 -> false; + _ -> + Offset = HdrOffset + ?PDP10_ARHDR_SIZEOF, + #arhdr{ar_name = Name, ar_size = Size} = ArHdr, + input_elf({File, Name, Offset, Size}, FP, Offset, Offset + Size, DefMap, UndefMap) end. %% Process input object file =================================================== diff --git a/erlang/apps/ld/src/ld_internal.hrl b/erlang/apps/ld/src/ld_internal.hrl index 8206f40..ba954d9 100644 --- a/erlang/apps/ld/src/ld_internal.hrl +++ b/erlang/apps/ld/src/ld_internal.hrl @@ -1,7 +1,7 @@ %%% -*- erlang-indent-level: 2 -*- %%% %%% internal declarations for pdp10-elf ld. -%%% Copyright (C) 2020 Mikael Pettersson +%%% Copyright (C) 2020-2023 Mikael Pettersson %%% %%% This file is part of pdp10-tools. %%% @@ -23,8 +23,15 @@ -include_lib("lib/include/pdp10_elf36.hrl"). +-type ifile() :: string() % explicit input .o-file + | { Archive :: string() % archive name + , Name :: string() % member name + , Offset :: non_neg_integer() % member data (not header) at this offset + , Size :: non_neg_integer() % member data size + }. + -record(input, - { file :: string() + { file :: ifile() , shtab :: [#elf36_Shdr{}] , symtab :: [#elf36_Sym{}] , stshndx :: non_neg_integer()