mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-02-28 17:29:24 +00:00
ld_input: add support for archives
This commit is contained in:
@@ -17,6 +17,19 @@
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License
|
||||
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||
%%%
|
||||
%%%=============================================================================
|
||||
%%%
|
||||
%%% - 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 ===================================================
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user