mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-24 11:22:52 +00:00
nm: use pdp10_elf36 library, use error:format/1 to format error reasons
This commit is contained in:
parent
c150845358
commit
c53d8167c9
@ -16,7 +16,7 @@
|
||||
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{application, nm,
|
||||
[{description, "'nm' clone for PDP10 Elf36 files"},
|
||||
[{description, "'nm' clone for pdp10-elf"},
|
||||
{vsn, "0.1.0"},
|
||||
{registered, []},
|
||||
{applications, [kernel, stdlib, lib]},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% 'nm' clone for PDP10 Elf36 files
|
||||
%%% 'nm' clone for pdp10-elf
|
||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
@ -170,152 +170,30 @@ nm1(Opts, PrintFile, File, FP) ->
|
||||
print_symtab(Opts, PrintFile, File, ShTab, SymTab, StrTab).
|
||||
|
||||
read_ehdr(File, FP) ->
|
||||
case pdp10_elf36_read_ehdr(FP) of
|
||||
case pdp10_elf36:read_Ehdr(FP) of
|
||||
{ok, Ehdr} ->
|
||||
Ehdr;
|
||||
{error, Reason} ->
|
||||
escript_runtime:fatal("invalid PDP10 ELF36 file ~s: ~p\n",
|
||||
[File, Reason])
|
||||
escript_runtime:fatal("invalid PDP10 ELF36 file ~s: ~s\n",
|
||||
[File, error:format(Reason)])
|
||||
end.
|
||||
|
||||
read_shtab(File, FP, Ehdr) ->
|
||||
case read_shtab(FP, Ehdr) of
|
||||
{ok, ShTab, ShStrTab} -> {ShTab, ShStrTab};
|
||||
case pdp10_elf36:read_ShTab(FP, Ehdr) of
|
||||
{ok, {ShTab, ShStrTab}} -> {ShTab, ShStrTab};
|
||||
{error, Reason} ->
|
||||
escript_runtime:fatal("failed to read section header table in ~s: ~p\n",
|
||||
[File, Reason])
|
||||
end.
|
||||
|
||||
read_shtab(FP, Ehdr) ->
|
||||
#elf36_Ehdr{ e_shoff = ShOff
|
||||
, e_shnum = ShNum0
|
||||
, e_shstrndx = ShStrNdx } = Ehdr,
|
||||
case ShOff of
|
||||
0 -> {ok, {[], []}};
|
||||
_ ->
|
||||
case pdp10_stdio:fseek(FP, {bof, ShOff}) of
|
||||
ok ->
|
||||
case pdp10_elf36_read_shdr(FP) of
|
||||
{ok, Shdr0} ->
|
||||
ShNum = actual_shnum(ShNum0, Shdr0),
|
||||
case do_read_shtab(FP, ShNum - 1, [Shdr0]) of
|
||||
{ok, ShTab} ->
|
||||
case read_shstrtab(FP, ShTab, ShStrNdx, Shdr0) of
|
||||
{ok, ShStrTab} -> {ok, ShTab, ShStrTab};
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end
|
||||
end.
|
||||
|
||||
actual_shnum(0, #elf36_Shdr{sh_size = ShNum} = _Shdr0) -> ShNum;
|
||||
actual_shnum(ShNum, _Shdr0) -> ShNum.
|
||||
|
||||
do_read_shtab(_FP, 0, Shdrs) -> {ok, lists:reverse(Shdrs)};
|
||||
do_read_shtab(FP, ShNum, Shdrs) when ShNum > 0 ->
|
||||
case pdp10_elf36_read_shdr(FP) of
|
||||
{ok, Shdr} -> do_read_shtab(FP, ShNum - 1, [Shdr | Shdrs]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
read_shstrtab(FP, ShTab, ShStrNdx0, Shdr0) ->
|
||||
case ShStrNdx0 of
|
||||
?SHN_UNDEF -> {ok, []};
|
||||
_ ->
|
||||
ShStrNdx =
|
||||
case ShStrNdx0 of
|
||||
?SHN_XINDEX -> Shdr0#elf36_Shdr.sh_link;
|
||||
_ -> ShStrNdx0
|
||||
end,
|
||||
read_strtab(FP, ShTab, ShStrNdx)
|
||||
end.
|
||||
|
||||
read_strtab(FP, ShTab, Index) ->
|
||||
ShNum = length(ShTab),
|
||||
case Index > 0 andalso Index < ShNum of
|
||||
true ->
|
||||
#elf36_Shdr{ sh_type = Type
|
||||
, sh_size = Size
|
||||
, sh_offset = Offset
|
||||
} = lists:nth(Index + 1, ShTab),
|
||||
case Type of
|
||||
?SHT_STRTAB ->
|
||||
case pdp10_stdio:fseek(FP, {bof, Offset}) of
|
||||
ok ->
|
||||
case pdp10_stdio:fread(1, Size, FP) of
|
||||
{ok, _StrTab} = Result -> Result;
|
||||
{error, _Reason} = Error -> Error;
|
||||
eof -> {error, eof}
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
_ ->
|
||||
{error, io_lib:format("invalid type ~p for string table at index ~p",
|
||||
[Type, Index])}
|
||||
end;
|
||||
false ->
|
||||
{error, io_lib:format("invalid string table section index ~p",
|
||||
[Index])}
|
||||
escript_runtime:fatal("failed to read section header table in ~s: ~s\n",
|
||||
[File, error:format(Reason)])
|
||||
end.
|
||||
|
||||
read_symtab(File, FP, ShTab) ->
|
||||
case read_symtab(FP, ShTab) of
|
||||
{ok, SymTab, StrTab} -> {SymTab, StrTab};
|
||||
case pdp10_elf36:read_SymTab(FP, ShTab) of
|
||||
{ok, {SymTab, StrTab}} -> {SymTab, StrTab};
|
||||
{error, Reason} ->
|
||||
escript_runtime:fatal("failed to read symbol table table in ~s: ~p\n",
|
||||
[File, Reason])
|
||||
escript_runtime:fatal("failed to read symbol table table in ~s: ~s\n",
|
||||
[File, error:format(Reason)])
|
||||
end.
|
||||
|
||||
read_symtab(FP, ShTab) ->
|
||||
case find_symtab(ShTab) of
|
||||
false -> {ok, [], []};
|
||||
{ok, Shdr} ->
|
||||
#elf36_Shdr{ sh_link = Link
|
||||
, sh_entsize = EntSize
|
||||
, sh_size = Size
|
||||
, sh_offset = Offset
|
||||
} = Shdr,
|
||||
case [] of
|
||||
_ when EntSize =/= ?ELF36_SYM_SIZEOF ->
|
||||
{error, io_lib:format("wrong sh_entsize ~p in symtab section header", [EntSize])};
|
||||
_ when (Size rem ?ELF36_SYM_SIZEOF) =/= 0 ->
|
||||
{error, io_lib:format("wrong sh_size ~p in symtab section header", [Size])};
|
||||
_ ->
|
||||
case read_strtab(FP, ShTab, Link) of
|
||||
{ok, StrTab} ->
|
||||
SymNum = Size div ?ELF36_SYM_SIZEOF,
|
||||
case SymNum of
|
||||
0 -> {ok, [], StrTab};
|
||||
_ ->
|
||||
case pdp10_stdio:fseek(FP, {bof, Offset}) of
|
||||
ok ->
|
||||
case do_read_symtab(FP, SymNum, []) of
|
||||
{ok, SymTab} -> {ok, SymTab, StrTab};
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
do_read_symtab(_FP, _SymNum = 0, Syms) -> {ok, lists:reverse(Syms)};
|
||||
do_read_symtab(FP, SymNum, Syms) when SymNum > 0 ->
|
||||
case pdp10_elf36_read_sym(FP) of
|
||||
{ok, Sym} -> do_read_symtab(FP, SymNum - 1, [Sym | Syms]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
find_symtab([]) -> false;
|
||||
find_symtab([#elf36_Shdr{sh_type = ?SHT_SYMTAB} = Shdr | _]) -> {ok, Shdr};
|
||||
find_symtab([_Shdr | ShTab]) -> find_symtab(ShTab).
|
||||
|
||||
print_symtab(Opts, PrintFile, File, ShTab, SymTab, StrTab) ->
|
||||
case PrintFile of
|
||||
true -> io:format("\n~s:\n", [File]);
|
||||
@ -471,279 +349,3 @@ sym_value(ShTab, #elf36_Sym{st_shndx = ShNdx, st_value = Value}) ->
|
||||
false -> 0
|
||||
end,
|
||||
Base + Value.
|
||||
|
||||
%% ELF36 =======================================================================
|
||||
%% (these bits should go into the pdp10_elf36 library module)
|
||||
|
||||
pdp10_elf36_read_ehdr(FP) ->
|
||||
case pdp10_elf36_read_record(FP, pdp10_elf36_ehdr_desc()) of
|
||||
{ok, Ehdr} ->
|
||||
case pdp10_elf36_check_ehdr(Ehdr) of
|
||||
ok -> {ok, Ehdr};
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
pdp10_elf36_check_ehdr(Ehdr) ->
|
||||
check(Ehdr,
|
||||
[ fun check_ehdr_ei_mag0/1
|
||||
, fun check_ehdr_ei_mag1/1
|
||||
, fun check_ehdr_ei_mag2/1
|
||||
, fun check_ehdr_ei_mag3/1
|
||||
, fun check_ehdr_ei_class/1
|
||||
, fun check_ehdr_ei_data/1
|
||||
, fun check_ehdr_ei_version/1
|
||||
, fun check_ehdr_ei_osabi/1
|
||||
, fun check_ehdr_ei_abiversion/1
|
||||
, fun check_ehdr_e_type/1
|
||||
, fun check_ehdr_e_machine/1
|
||||
, fun check_ehdr_e_version/1
|
||||
, fun check_ehdr_e_ehsize/1
|
||||
, fun check_ehdr_e_shentsize/1
|
||||
]).
|
||||
|
||||
pdp10_elf36_read_shdr(FP) ->
|
||||
pdp10_elf36_read_record(FP, pdp10_elf36_shdr_desc()).
|
||||
|
||||
pdp10_elf36_read_sym(FP) ->
|
||||
pdp10_elf36_read_record(FP, pdp10_elf36_sym_desc()).
|
||||
|
||||
check(_X, []) -> ok;
|
||||
check(X, [Fun | Funs]) ->
|
||||
case Fun(X) of
|
||||
ok -> check(X, Funs);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
check_ehdr_ei_mag0(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Mag0 = lists:nth(?EI_MAG0 + 1, Ident),
|
||||
case Mag0 of
|
||||
?ELFMAG0 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_mag0 ~p", [Mag0])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_mag1(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Mag1 = lists:nth(?EI_MAG1 + 1, Ident),
|
||||
case Mag1 of
|
||||
?ELFMAG1 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_mag1 ~p", [Mag1])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_mag2(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Mag2 = lists:nth(?EI_MAG2 + 1, Ident),
|
||||
case Mag2 of
|
||||
?ELFMAG2 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_mag2 ~p", [Mag2])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_mag3(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Mag3 = lists:nth(?EI_MAG3 + 1, Ident),
|
||||
case Mag3 of
|
||||
?ELFMAG3 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_mag3 ~p", [Mag3])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_class(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Class = lists:nth(?EI_CLASS + 1, Ident),
|
||||
case Class of
|
||||
?ELFCLASS36 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_class ~p", [Class])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_data(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Data = lists:nth(?EI_DATA + 1, Ident),
|
||||
case Data of
|
||||
?ELFDATA2MSB -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_data ~p", [Data])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_version(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
Version = lists:nth(?EI_VERSION + 1, Ident),
|
||||
case Version of
|
||||
?EV_CURRENT -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_version ~p", [Version])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_osabi(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
OSABI = lists:nth(?EI_OSABI + 1, Ident),
|
||||
case OSABI of
|
||||
?ELFOSABI_NONE -> ok;
|
||||
?ELFOSABI_LINUX -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_osabi ~p", [OSABI])}
|
||||
end.
|
||||
|
||||
check_ehdr_ei_abiversion(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ident = Ident } = Ehdr,
|
||||
ABIVersion = lists:nth(?EI_ABIVERSION + 1, Ident),
|
||||
case ABIVersion of
|
||||
0 -> ok;
|
||||
_ -> {error, io_lib:format("wrong ei_abiversion ~p", [ABIVersion])}
|
||||
end.
|
||||
|
||||
check_ehdr_e_type(Ehdr) ->
|
||||
#elf36_Ehdr{ e_type = Type } = Ehdr,
|
||||
case Type of
|
||||
?ET_REL -> ok;
|
||||
?ET_EXEC -> ok;
|
||||
?ET_DYN -> ok;
|
||||
?ET_CORE -> ok;
|
||||
_ -> {error, io_lib:format("wrong e_type ~p", [Type])}
|
||||
end.
|
||||
|
||||
check_ehdr_e_machine(Ehdr) ->
|
||||
#elf36_Ehdr{ e_machine = Machine } = Ehdr,
|
||||
case Machine of
|
||||
?EM_PDP10 -> ok;
|
||||
_ -> {error, io_lib:format("wrong e_machine ~p", [Machine])}
|
||||
end.
|
||||
|
||||
check_ehdr_e_version(Ehdr) ->
|
||||
#elf36_Ehdr{ e_version = Version } = Ehdr,
|
||||
case Version of
|
||||
?EV_CURRENT -> ok;
|
||||
_ -> {error, io_lib:format("wrong e_version ~p", [Version])}
|
||||
end.
|
||||
|
||||
check_ehdr_e_ehsize(Ehdr) ->
|
||||
#elf36_Ehdr{ e_ehsize = EhSize } = Ehdr,
|
||||
case EhSize of
|
||||
?ELF36_EHDR_SIZEOF -> ok;
|
||||
_ -> {error, io_lib:format("wrong e_ehsize ~p", [EhSize])}
|
||||
end.
|
||||
|
||||
check_ehdr_e_shentsize(Ehdr) ->
|
||||
#elf36_Ehdr{ e_shoff = ShOff
|
||||
, e_shentsize = ShEntSize } = Ehdr,
|
||||
case {ShOff, ShEntSize} of
|
||||
{0, _} -> ok;
|
||||
{_, ?ELF36_SHDR_SIZEOF} -> ok;
|
||||
_ -> {error, io_lib:format("wrong e_shentsize ~p", [ShEntSize])}
|
||||
end.
|
||||
|
||||
%% Input of records ============================================================
|
||||
|
||||
-type reader() :: fun((pdp10_stdio:file()) -> {ok, integer()} | {error, any()}).
|
||||
|
||||
-record(record_desc, {
|
||||
tag :: atom()
|
||||
, fields :: [reader()]
|
||||
}).
|
||||
|
||||
pdp10_elf36_read_record(FP, #record_desc{tag = Tag, fields = FieldReaders}) ->
|
||||
pdp10_elf36_read_record(FP, FieldReaders, [Tag]).
|
||||
|
||||
pdp10_elf36_read_record(_FP, [], Values) ->
|
||||
{ok, list_to_tuple(lists:reverse(Values))};
|
||||
pdp10_elf36_read_record(FP, [FieldReader | FieldReaders], Values) ->
|
||||
case FieldReader(FP) of
|
||||
{ok, Value} ->
|
||||
pdp10_elf36_read_record(FP, FieldReaders, [Value | Values]);
|
||||
{error, _Reason} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
pdp10_elf36_ehdr_desc() ->
|
||||
#record_desc{ tag = elf36_Ehdr
|
||||
, fields =
|
||||
[
|
||||
fun read_e_ident/1 % e_ident
|
||||
, fun read_Half/1 % e_type
|
||||
, fun read_Half/1 % e_machine
|
||||
, fun read_Word/1 % e_version
|
||||
, fun read_Addr/1 % e_entry
|
||||
, fun read_Off/1 % e_phoff
|
||||
, fun read_Off/1 % e_shoff
|
||||
, fun read_Word/1 % e_flags
|
||||
, fun read_Half/1 % e_ehsize
|
||||
, fun read_Half/1 % e_phentsize
|
||||
, fun read_Half/1 % e_phnum
|
||||
, fun read_Half/1 % e_shentsize
|
||||
, fun read_Half/1 % e_shnum
|
||||
, fun read_Half/1 % e_shstrndx
|
||||
]
|
||||
}.
|
||||
|
||||
read_e_ident(FP) ->
|
||||
pdp10_elf36_read(FP, ?EI_NIDENT, fun(L) -> L end).
|
||||
|
||||
pdp10_elf36_shdr_desc() ->
|
||||
#record_desc{ tag = elf36_Shdr
|
||||
, fields =
|
||||
[
|
||||
fun read_Word/1 % sh_name
|
||||
, fun read_Word/1 % sh_type
|
||||
, fun read_Word/1 % sh_flags
|
||||
, fun read_Addr/1 % sh_addr
|
||||
, fun read_Off/1 % sh_offset
|
||||
, fun read_Word/1 % sh_size
|
||||
, fun read_Word/1 % sh_link
|
||||
, fun read_Word/1 % sh_info
|
||||
, fun read_Word/1 % sh_addralign
|
||||
, fun read_Word/1 % sh_entsize
|
||||
]
|
||||
}.
|
||||
|
||||
pdp10_elf36_sym_desc() ->
|
||||
#record_desc{ tag = elf36_Sym
|
||||
, fields =
|
||||
[
|
||||
fun read_Word/1 % st_name
|
||||
, fun read_Addr/1 % st_value
|
||||
, fun read_Word/1 % st_size
|
||||
, fun read_Uchar/1 % st_info
|
||||
, fun read_Uchar/1 % st_other
|
||||
, fun read_Half/1 % st_shndx
|
||||
]
|
||||
}.
|
||||
|
||||
%% Input of scalar items =======================================================
|
||||
|
||||
read_Uchar(FP) -> pdp10_elf36_read_uint9(FP).
|
||||
read_Half(FP) -> pdp10_elf36_read_uint18(FP).
|
||||
read_Word(FP) -> pdp10_elf36_read_uint36(FP).
|
||||
read_Addr(FP) -> pdp10_elf36_read_uint36(FP).
|
||||
read_Off(FP) -> pdp10_elf36_read_uint36(FP).
|
||||
|
||||
pdp10_elf36_read_uint9(FP) ->
|
||||
case pdp10_stdio:fgetc(FP) of
|
||||
{ok, _Nonet} = Res -> Res;
|
||||
{error, _Reason} = Res -> Res;
|
||||
eof -> {error, eof}
|
||||
end.
|
||||
|
||||
pdp10_elf36_read_uint18(FP) ->
|
||||
pdp10_elf36_read(FP, 2, fun make_uint18be/1).
|
||||
|
||||
pdp10_elf36_read_uint36(FP) ->
|
||||
pdp10_elf36_read(FP, 4, fun make_uint36be/1).
|
||||
|
||||
pdp10_elf36_read(FP, N, ConvFun) when N >= 0 ->
|
||||
pdp10_elf36_read(FP, N, ConvFun, []).
|
||||
|
||||
pdp10_elf36_read(_FP, 0, ConvFun, Acc) ->
|
||||
{ok, ConvFun(lists:reverse(Acc))};
|
||||
pdp10_elf36_read(FP, N, ConvFun, Acc) ->
|
||||
case pdp10_elf36_read_uint9(FP) of
|
||||
{ok, Nonet} ->
|
||||
pdp10_elf36_read(FP, N - 1, ConvFun, [Nonet | Acc]);
|
||||
{error, _Reason} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
make_uint18be([B1, B2]) -> % big-endian conversion
|
||||
((B1 band 16#1FF) bsl 9) bor (B2 band 16#1FF).
|
||||
|
||||
make_uint36be([B1, B2, B3, B4]) -> % big-endian conversion
|
||||
((B1 band 16#1FF) bsl 27) bor
|
||||
((B2 band 16#1FF) bsl 19) bor
|
||||
((B3 band 16#1FF) bsl 9) bor
|
||||
(B4 band 16#1FF).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user