Closed X547 closed 3 years ago
I attached Albert.odc
that contains report of my ElfDecoder.
Albert.zip
Disassembly utilities such as IDA Pro Free fails to recognize exit
function because it is located outside of segment.
Well, this is by design, actually, but I'm open for criticism and suggestions.
The idea is that for every external function (imported from a library) the compiler expects a proxy in the special proxy table. So, when an external function is called, the actual address is loaded from the proxy table into a register, and a CALL [reg] is executed. The indexes into the proxy table are hard-coded by the compiler. It is the loader's responsibility to fill out the proxy table to provide for proper linking to external funcitons (be it the host OS or the BlackBox linker).
And it only seemed reasonable to me that the proxy table does not need to be present in the ELF file (and neither in the OCF file). Memory space is allocated for it (at the end of meta, segment 0 in your awesome decoder output), and then the OS's dynamic loader fills that out based on information provided in the DYNAMIC segment.
The problem is there are extra zero first entry in proxy table that is not included in segment size. Increasing segment that contains proxy table by 8 bytes will fix the issue. I am not sure what exact code should be adjusted in HrElf to properly fix issue. I added 1 to m.imps.
I see what you're saying. I think the line is in HrElf.DoAddOcf, and it's this one:
AllocSeg(m.meta, AdAligned(m.ms) + (m.imps + m.exts) * addrSize[version], pageAligned);
shoud be
AllocSeg(m.meta, AdAligned(m.ms) + (1 + m.imps + m.exts) * addrSize[version], pageAligned);
If you confirm this fixes the issue, I'll put it into my modules.
AllocSeg(m.meta, AdAligned(m.ms) + (1 + m.imps + m.exts) * addrSize[version], pageAligned);
This will cause trap in size mismatch.
Place that I changed:
PROCEDURE DoAddOcf (ocf: Files.File; VAR res: INTEGER);
VAR s: OcfScanner; _, i: INTEGER; n: Name; meta, desc, code, imps: POINTER TO ARRAY OF BYTE;
prev, m: MModule;
c: ARRAY 3 OF LONGINT;
BEGIN
s.ConnectTo(ocf, 0); (* header and descriptor are in, module can be scanned *)
IF ~s.ok THEN HALT(20)
ELSE
NEW(m);
m.ms := s.ms; m.ds := s.ds; m.cs:= s.cs; m.vs := s.vs; m.imps := s.imps + 1; (* zero entry in proxy table *) m.exts := s.exts; m.name := s.name$;
Hm... I tried my location of +1, and can't get a trap. Can you reproduce and send the trap you receive?
Hm... I tried my location of +1, and can't get a trap.
Sorry, trap was caused when inserting "+1" in one line above. Your change don't cause trap but it don't solve issue:
Reloc (Addend)
Address Old Kind Value Addend
004050B0 00000000 abs64 Do6 0
004050A8 00000000 abs64 Do5 0
004050A0 00000000 abs64 Do4 0
00405098 00000000 abs64 Do3 0
00405090 00000000 abs64 Do2 0
00405088 00000000 abs64 Do1 0
00405080 00000000 abs64 exit 0
00405078 00000000 abs64 puts 0
Segment 0 (00405000, 000000B0, data)
00405000 17 FD 07 FC 99 01 24 24 00 FD 10 80 70 40 00 00 ......$$....p@..
00405010 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............
00405020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00405030 00 62 75 74 20 6E 6F 74 20 73 69 6D 70 6C 65 72 .but not simpler
00405040 00 41 6C 62 65 72 74 20 61 73 6B 65 64 20 74 6F .Albert asked to
00405050 20 6D 61 6B 65 20 69 74 20 61 73 20 73 69 6D 70 make it as simp
00405060 6C 65 20 61 73 20 70 6F 73 73 69 62 6C 65 2C 00 le as possible,.
00405070 00 00 00 00 00 00 00 00 ........
__imp_puts
00405070 00 00 00 00 00 00 00 00 ........
__imp_exit
00405080 00 00 00 00 00 00 00 00 ........
__imp_Do1
00405080 00 00 00 00 00 00 00 00 ........
__imp_Do2
00405090 00 00 00 00 00 00 00 00 ........
__imp_Do3
00405090 00 00 00 00 00 00 00 00 ........
__imp_Do4
004050A0 00 00 00 00 00 00 00 00 ........
__imp_Do5
004050A0 00 00 00 00 00 00 00 00 ........
Note that "__imp_Do6" is missing. My position fixes issue:
Reloc (Addend)
Address Old Kind Value Addend
004050B0 00000000 abs64 Do6 0
004050A8 00000000 abs64 Do5 0
004050A0 00000000 abs64 Do4 0
00405098 00000000 abs64 Do3 0
00405090 00000000 abs64 Do2 0
00405088 00000000 abs64 Do1 0
00405080 00000000 abs64 exit 0
00405078 00000000 abs64 puts 0
Segment 0 (00405000, 000000B8, data)
00405000 17 FD 07 FC 99 01 24 24 00 FD 10 80 70 40 00 00 ......$$....p@..
00405010 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............
00405020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00405030 00 62 75 74 20 6E 6F 74 20 73 69 6D 70 6C 65 72 .but not simpler
00405040 00 41 6C 62 65 72 74 20 61 73 6B 65 64 20 74 6F .Albert asked to
00405050 20 6D 61 6B 65 20 69 74 20 61 73 20 73 69 6D 70 make it as simp
00405060 6C 65 20 61 73 20 70 6F 73 73 69 62 6C 65 2C 00 le as possible,.
00405070 00 00 00 00 00 00 00 00 ........
__imp_puts
00405070 00 00 00 00 00 00 00 00 ........
__imp_exit
00405080 00 00 00 00 00 00 00 00 ........
__imp_Do1
00405080 00 00 00 00 00 00 00 00 ........
__imp_Do2
00405090 00 00 00 00 00 00 00 00 ........
__imp_Do3
00405090 00 00 00 00 00 00 00 00 ........
__imp_Do4
004050A0 00 00 00 00 00 00 00 00 ........
__imp_Do5
004050A0 00 00 00 00 00 00 00 00 ........
__imp_Do6
004050B0 00 00 00 00 00 00 00 00 ........
In this code segment size is defined by LEN(meta) + LEN(imps):
IF m.imps > 0 THEN NEW(imps, m.imps * addrSize[version]) END;
...
OutSeg(m.meta, meta, imps);
PROCEDURE OutSeg (IN s: SSegment; a: ARRAY OF BYTE; b: POINTER TO ARRAY OF BYTE);
(** Output data in a and b (if any) into segment s *)
BEGIN
SkipTo(s.pos); ASSERT(s.pos = out.Pos());
out.WriteBytes(a, 0, LEN(a)); IF b # NIL THEN out.WriteBytes(b^, 0, LEN(b)) END;
ASSERT(out.Pos() = s.pos + s.len)
END OutSeg;
Fixed In HrBinder.
This is https://github.com/adimetrius/Herschel/commit/cc4bead0534a6824bca446a8d906e7952b0d8ffd.
ELF segments of
Albert
sample:Relocations:
Note that address
00405080
do not point to any existing segment.