From c53d8167c9dce55528af2f0c400a1d5121bbd84f Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Mon, 19 Aug 2019 22:19:39 +0200 Subject: [PATCH] nm: use pdp10_elf36 library, use error:format/1 to format error reasons --- erlang/apps/nm/src/nm.app.src | 2 +- erlang/apps/nm/src/nm.erl | 422 +--------------------------------- 2 files changed, 13 insertions(+), 411 deletions(-) diff --git a/erlang/apps/nm/src/nm.app.src b/erlang/apps/nm/src/nm.app.src index b4167fd..5004851 100644 --- a/erlang/apps/nm/src/nm.app.src +++ b/erlang/apps/nm/src/nm.app.src @@ -16,7 +16,7 @@ %%% along with pdp10-tools. If not, see . {application, nm, - [{description, "'nm' clone for PDP10 Elf36 files"}, + [{description, "'nm' clone for pdp10-elf"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib, lib]}, diff --git a/erlang/apps/nm/src/nm.erl b/erlang/apps/nm/src/nm.erl index 661eb9b..6eea536 100644 --- a/erlang/apps/nm/src/nm.erl +++ b/erlang/apps/nm/src/nm.erl @@ -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).