mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-05-04 23:16:14 +00:00
nm: use pdp10_elf36 library, use error:format/1 to format error reasons
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
{application, nm,
|
{application, nm,
|
||||||
[{description, "'nm' clone for PDP10 Elf36 files"},
|
[{description, "'nm' clone for pdp10-elf"},
|
||||||
{vsn, "0.1.0"},
|
{vsn, "0.1.0"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications, [kernel, stdlib, lib]},
|
{applications, [kernel, stdlib, lib]},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
%%% -*- erlang-indent-level: 2 -*-
|
%%% -*- erlang-indent-level: 2 -*-
|
||||||
%%%
|
%%%
|
||||||
%%% 'nm' clone for PDP10 Elf36 files
|
%%% 'nm' clone for pdp10-elf
|
||||||
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
%%% Copyright (C) 2013-2019 Mikael Pettersson
|
||||||
%%%
|
%%%
|
||||||
%%% This file is part of pdp10-tools.
|
%%% This file is part of pdp10-tools.
|
||||||
@@ -170,152 +170,30 @@ nm1(Opts, PrintFile, File, FP) ->
|
|||||||
print_symtab(Opts, PrintFile, File, ShTab, SymTab, StrTab).
|
print_symtab(Opts, PrintFile, File, ShTab, SymTab, StrTab).
|
||||||
|
|
||||||
read_ehdr(File, FP) ->
|
read_ehdr(File, FP) ->
|
||||||
case pdp10_elf36_read_ehdr(FP) of
|
case pdp10_elf36:read_Ehdr(FP) of
|
||||||
{ok, Ehdr} ->
|
{ok, Ehdr} ->
|
||||||
Ehdr;
|
Ehdr;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
escript_runtime:fatal("invalid PDP10 ELF36 file ~s: ~p\n",
|
escript_runtime:fatal("invalid PDP10 ELF36 file ~s: ~s\n",
|
||||||
[File, Reason])
|
[File, error:format(Reason)])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
read_shtab(File, FP, Ehdr) ->
|
read_shtab(File, FP, Ehdr) ->
|
||||||
case read_shtab(FP, Ehdr) of
|
case pdp10_elf36:read_ShTab(FP, Ehdr) of
|
||||||
{ok, ShTab, ShStrTab} -> {ShTab, ShStrTab};
|
{ok, {ShTab, ShStrTab}} -> {ShTab, ShStrTab};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
escript_runtime:fatal("failed to read section header table in ~s: ~p\n",
|
escript_runtime:fatal("failed to read section header table in ~s: ~s\n",
|
||||||
[File, Reason])
|
[File, error:format(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])}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
read_symtab(File, FP, ShTab) ->
|
read_symtab(File, FP, ShTab) ->
|
||||||
case read_symtab(FP, ShTab) of
|
case pdp10_elf36:read_SymTab(FP, ShTab) of
|
||||||
{ok, SymTab, StrTab} -> {SymTab, StrTab};
|
{ok, {SymTab, StrTab}} -> {SymTab, StrTab};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
escript_runtime:fatal("failed to read symbol table table in ~s: ~p\n",
|
escript_runtime:fatal("failed to read symbol table table in ~s: ~s\n",
|
||||||
[File, Reason])
|
[File, error:format(Reason)])
|
||||||
end.
|
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) ->
|
print_symtab(Opts, PrintFile, File, ShTab, SymTab, StrTab) ->
|
||||||
case PrintFile of
|
case PrintFile of
|
||||||
true -> io:format("\n~s:\n", [File]);
|
true -> io:format("\n~s:\n", [File]);
|
||||||
@@ -471,279 +349,3 @@ sym_value(ShTab, #elf36_Sym{st_shndx = ShNdx, st_value = Value}) ->
|
|||||||
false -> 0
|
false -> 0
|
||||||
end,
|
end,
|
||||||
Base + Value.
|
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).
|
|
||||||
|
|||||||
Reference in New Issue
Block a user