ld: ld_assign: new phase to assign load addresses and file offsets to segments

This commit is contained in:
Mikael Pettersson 2020-04-18 17:00:47 +02:00
parent ca515b376e
commit b1b7dc280c
2 changed files with 54 additions and 1 deletions

View File

@ -216,7 +216,8 @@ ld(Argv) ->
%% TODO: receive ok | error
{ok, Sections} = phase1(Options, Inputs),
%% TODO: receive ok | error
{ok, Segments} = phase2(Options, Sections),
{ok, Segments0} = phase2(Options, Sections),
Segments = assign(Options, Segments0),
output(Options, Segments);
{error, _Reason} = Error -> Error
end;
@ -386,6 +387,10 @@ phase1(_Options, Inputs) -> {ok, ld_phase1:phase1(Inputs)}.
phase2(_Options, Sections) -> {ok, ld_phase2:phase2(Sections)}.
%% Assigning Addresses =========================================================
assign(_Options, Segments) -> ld_assign:assign(Segments).
%% Output Generation ===========================================================
output(_Options, _Segments) -> ok. % FIXME

View File

@ -0,0 +1,48 @@
%%% -*- erlang-indent-level: 2 -*-
%%%
%%% Assigning addresses for pdp10-elf-ld
%%% Copyright (C) 2020 Mikael Pettersson
%%%
%%% This file is part of pdp10-tools.
%%%
%%% pdp10-tools is free software: you can redistribute it and/or modify
%%% it under the terms of the GNU General Public License as published by
%%% the Free Software Foundation, either version 3 of the License, or
%%% (at your option) any later version.
%%%
%%% pdp10-tools is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%%% GNU General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
-module(ld_assign).
-export([ assign/1
]).
-include("ld_internal.hrl").
%% Output ======================================================================
-spec assign([#segment{}]) -> [#segment{}].
assign(Segments) ->
%% TODO: assumes KL10B-compatible "small" code model output
VAddr = 8#00001001000 bsl 2, % section 1, page 1
PhNum = length(Segments),
true = PhNum < ?PN_XNUM, % assert; TODO: otherwise store PhNum in Shdr0.sh_info
Offset = ?ELF36_EHDR_SIZEOF + ?ELF36_PHDR_SIZEOF * PhNum,
assign(Segments, Offset, VAddr, []).
assign(_Segments = [], _Offset, _VAddr, NewSegments) -> lists:reverse(NewSegments);
assign([Segment | Segments], Offset, VAddr, NewSegments) ->
#segment{phdr = Phdr} = Segment,
#elf36_Phdr{p_filesz = FileSz, p_memsz = MemSz, p_align = Align} = Phdr,
SegAlign = max(4096, Align), % align to page boundary; TODO: target-specific
SegOffset = (Offset + (SegAlign - 1)) band bnot (SegAlign - 1),
SegVAddr = (VAddr + (SegAlign - 1)) band bnot (SegAlign - 1),
NewPhdr = Phdr#elf36_Phdr{p_offset = SegOffset, p_vaddr = SegVAddr, p_align = SegAlign},
NewSegment = Segment#segment{phdr = NewPhdr},
assign(Segments, SegOffset + FileSz, SegVAddr + MemSz, [NewSegment | NewSegments]).