Skip to content

Commit 9551d29

Browse files
committed
tmp fix for p_align issue
1 parent 8e037fc commit 9551d29

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

src/patcherex2/components/allocation_managers/allocation_manager.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _find_in_mapped_blocks(
154154
def _create_new_mapped_block(
155155
self, size: int, flag=MemoryFlag.RWX, align=0x1
156156
) -> bool:
157-
# map 0x1000 bytes # TODO: currently we won't use available file/mem blocks, instead we create new one at the end of the file
157+
# TODO: currently we won't use available file/mem blocks, instead we create new one at the end of the file
158158
file_addr = None
159159
mem_addr = None
160160
for block in self.blocks[FileBlock]:
@@ -163,8 +163,19 @@ def _create_new_mapped_block(
163163
block.addr += 0x2000
164164
for block in self.blocks[MemoryBlock]:
165165
if block.size == -1:
166-
# mem_addr % 0x1000 should equal to file_addr % 0x1000 TODO
167-
mem_addr = block.addr + (file_addr % 0x1000)
166+
# NOTE: mem_addr % p_align should equal to file_addr % p_align
167+
# Check `man elf` and search for `p_align` for more information
168+
# FIXME: shouldn't do any assumption on component type, reimpl in a better way
169+
# FIXME: even worse, importing ELF will cause circular import
170+
# TODO: consider merge allocation_manager and binfmt_tool into one component
171+
if self.p.binfmt_tool.__class__.__name__ == "ELF":
172+
max_seg_align = max(
173+
[segment["p_align"] for segment in self.p.binfmt_tool._segments]
174+
+ [0]
175+
)
176+
mem_addr = block.addr + (file_addr % max_seg_align)
177+
else:
178+
mem_addr = block.addr + (file_addr % 0x1000)
168179
block.addr = mem_addr + 0x2000
169180
if file_addr and mem_addr:
170181
self.add_block(

src/patcherex2/components/binfmt_tools/elf.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ def _add_end_of_file_block(self) -> None:
185185
self.p.allocation_manager.add_block(block)
186186

187187
addr = load_segments[-1]["p_vaddr"] + load_segments[-1]["p_memsz"]
188-
addr = (addr + 0xFFF) & ~0xFFF # round up to 0x1000
188+
# TODO: should we use the max_align of the segments?
189+
max_align = max([segment["p_align"] for segment in self._segments] + [0])
190+
addr = (addr + (max_align - 1)) & ~(max_align - 1) # round up to max_align
189191
block = MemoryBlock(addr, -1)
190192
self.p.allocation_manager.add_block(block)
191193

@@ -342,6 +344,7 @@ def finalize(self) -> None:
342344
self._segments.append(phdr_load_segment)
343345

344346
# magic
347+
# TODO: should we use the max_align of the segments?
345348
load_segments_rounded = []
346349
first_load_segment = None
347350
for segment in self._segments:
@@ -350,24 +353,24 @@ def finalize(self) -> None:
350353
first_load_segment = segment
351354
load_segments_rounded.append(
352355
(
353-
# start of the segment, round down to multiple of 0x1000
356+
# start of the segment, round down to multiple of max_align
354357
(segment["p_vaddr"] - first_load_segment["p_vaddr"])
355358
- (
356359
(segment["p_vaddr"] - first_load_segment["p_vaddr"])
357-
% 0x1000
360+
% max_align
358361
),
359-
# end of the segment, round up to multiple of 0x1000
362+
# end of the segment, round up to multiple of max_align
360363
int(
361364
(
362365
segment["p_vaddr"]
363366
+ segment["p_memsz"]
364367
- first_load_segment["p_vaddr"]
365-
+ 0x1000
368+
+ max_align
366369
- 1
367370
)
368-
/ 0x1000
371+
/ max_align
369372
)
370-
* 0x1000,
373+
* max_align,
371374
)
372375
)
373376
load_segments_rounded = sorted(load_segments_rounded, key=lambda x: x[0])
@@ -402,9 +405,10 @@ def finalize(self) -> None:
402405
for prev_seg, next_seg in zip(
403406
load_segments_rounded[:-1], load_segments_rounded[1:]
404407
):
408+
# TODO: should we use the max_align of the segments?
405409
potential_base = (
406-
max(prev_seg[1], self.p.binfmt_tool.file_size) + 0xFFF
407-
) & ~0xFFF # round up to 0x1000
410+
max(prev_seg[1], self.p.binfmt_tool.file_size) + (max_align - 1)
411+
) & ~(max_align - 1) # round up to max_align
408412
if next_seg[0] - potential_base > self._elf.header["e_phentsize"] * len(
409413
self._segments
410414
): # if there is space between segments, put phdr here
@@ -417,10 +421,11 @@ def finalize(self) -> None:
417421
# this is to workaround a weird issue in the dynamic linker of glibc
418422
# we want to make sure p_vaddr (phdr_start) == p_offset (len(ncontent))
419423
if phdr_start <= self.p.binfmt_tool.file_size:
424+
# TODO: should we use the max_align of the segments?
420425
# p_vaddr <= p_offset: pad the file (p_offset) to page size, and let p_vaddr = p_offset
421426
self.p.binfmt_tool.file_size = (
422-
self.p.binfmt_tool.file_size + 0xFFF
423-
) & ~0xFFF # round up to 0x1000
427+
self.p.binfmt_tool.file_size + (max_align - 1)
428+
) & ~(max_align - 1) # round up to max_align
424429
phdr_start = self.p.binfmt_tool.file_size
425430

426431
# update phdr segment and its corresponding load segment

0 commit comments

Comments
 (0)