* [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
@ 2026-06-13 15:21 valium007
2026-06-15 16:06 ` Helge Deller
0 siblings, 1 reply; 6+ messages in thread
From: valium007 @ 2026-06-13 15:21 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, deller, pierrick.bouvier, valium007
When a binary is patched or relocated such that the program header table is
moved into a separate PT_LOAD segment (rather than sitting at the start of the
first loadable segment), QEMU's AT_PHDR auxv entry becomes incorrect. The
loader was computing AT_PHDR as load_addr + e_phoff, which assumes the headers
are mapped 1:1 from file offset 0. This breaks when the headers are elsewhere.
The Linux kernel instead locates the PT_LOAD segment that contains e_phoff,
then computes the in-memory address as p_vaddr + (e_phoff - p_offset). This
correctly handles relocated headers.
Fix by:
1. Add phdr_addr field to image_info to cache the resolved address.
2. Initialize to load_addr + e_phoff (fallback for headers outside any PT_LOAD).
3. In the PT_LOAD mapping loop, detect if the segment contains e_phoff and
override with the segment-relative address.
4. Use info->phdr_addr for AT_PHDR instead of the incorrect formula.
Signed-off-by: valium007 <valium7171@gmail.com>
---
linux-user/elfload.c | 21 ++++++++++++++++++++-
linux-user/qemu.h | 1 +
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index b05b8b0..8049c8a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
/* There must be exactly DLINFO_ITEMS entries here, or the assert
* on info->auxv_len will trigger.
*/
- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
@@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
info->data_offset = load_bias;
info->load_addr = load_addr;
info->entry = ehdr->e_entry + load_bias;
+ /*
+ * Fallback for AT_PHDR if the program headers do not fall within
+ * any PT_LOAD segment (see the loop below, which overrides this with
+ * the correct in-memory address when a containing segment is found).
+ */
+ info->phdr_addr = load_addr + ehdr->e_phoff;
info->start_code = -1;
info->end_code = 0;
info->start_data = -1;
@@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
vaddr_ef = vaddr + eppnt->p_filesz;
vaddr_em = vaddr + eppnt->p_memsz;
+ /*
+ * If this segment contains the program headers, record their
+ * in-memory address for AT_PHDR. This matches the kernel, which
+ * locates the headers via the containing PT_LOAD rather than
+ * assuming load_addr + e_phoff (false when the phdrs are not
+ * mapped 1:1 from file offset 0, e.g. relocated into their own
+ * segment by a binary patcher).
+ */
+ if (eppnt->p_offset <= ehdr->e_phoff &&
+ ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
+ info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
+ }
+
/*
* Some segments may be completely empty, with a non-zero p_memsz
* but no backing file segment.
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 07fe801..2268493 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -26,6 +26,7 @@
struct image_info {
abi_ulong load_bias;
abi_ulong load_addr;
+ abi_ulong phdr_addr;
abi_ulong start_code;
abi_ulong end_code;
abi_ulong start_data;
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-13 15:21 [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment valium007
@ 2026-06-15 16:06 ` Helge Deller
2026-06-15 17:33 ` Pierrick Bouvier
2026-06-17 12:41 ` valium
0 siblings, 2 replies; 6+ messages in thread
From: Helge Deller @ 2026-06-15 16:06 UTC (permalink / raw)
To: valium007, qemu-devel; +Cc: laurent, pierrick.bouvier
On 6/13/26 17:21, valium007 wrote:
> When a binary is patched or relocated such that the program header table is
> moved into a separate PT_LOAD segment
How relevant is this? How/why does it happen?
> (rather than sitting at the start of the
> first loadable segment), QEMU's AT_PHDR auxv entry becomes incorrect. The
> loader was computing AT_PHDR as load_addr + e_phoff, which assumes the headers
> are mapped 1:1 from file offset 0. This breaks when the headers are elsewhere.
>
> The Linux kernel instead locates the PT_LOAD segment that contains e_phoff,
> then computes the in-memory address as p_vaddr + (e_phoff - p_offset). This
> correctly handles relocated headers.
Ok, I need to check on this.
> Fix by:
> 1. Add phdr_addr field to image_info to cache the resolved address.
> 2. Initialize to load_addr + e_phoff (fallback for headers outside any PT_LOAD).
> 3. In the PT_LOAD mapping loop, detect if the segment contains e_phoff and
> override with the segment-relative address.
> 4. Use info->phdr_addr for AT_PHDR instead of the incorrect formula.
>
> Signed-off-by: valium007 <valium7171@gmail.com>
Can you sign with a real name?
Helge
> ---
> linux-user/elfload.c | 21 ++++++++++++++++++++-
> linux-user/qemu.h | 1 +
> 2 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index b05b8b0..8049c8a 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
> /* There must be exactly DLINFO_ITEMS entries here, or the assert
> * on info->auxv_len will trigger.
> */
> - NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
> + NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
> NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
> NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
> NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
> @@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
> info->data_offset = load_bias;
> info->load_addr = load_addr;
> info->entry = ehdr->e_entry + load_bias;
> + /*
> + * Fallback for AT_PHDR if the program headers do not fall within
> + * any PT_LOAD segment (see the loop below, which overrides this with
> + * the correct in-memory address when a containing segment is found).
> + */
> + info->phdr_addr = load_addr + ehdr->e_phoff;
> info->start_code = -1;
> info->end_code = 0;
> info->start_data = -1;
> @@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
> vaddr_ef = vaddr + eppnt->p_filesz;
> vaddr_em = vaddr + eppnt->p_memsz;
>
> + /*
> + * If this segment contains the program headers, record their
> + * in-memory address for AT_PHDR. This matches the kernel, which
> + * locates the headers via the containing PT_LOAD rather than
> + * assuming load_addr + e_phoff (false when the phdrs are not
> + * mapped 1:1 from file offset 0, e.g. relocated into their own
> + * segment by a binary patcher).
> + */
> + if (eppnt->p_offset <= ehdr->e_phoff &&
> + ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
> + info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
> + }
> +
> /*
> * Some segments may be completely empty, with a non-zero p_memsz
> * but no backing file segment.
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 07fe801..2268493 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -26,6 +26,7 @@
> struct image_info {
> abi_ulong load_bias;
> abi_ulong load_addr;
> + abi_ulong phdr_addr;
> abi_ulong start_code;
> abi_ulong end_code;
> abi_ulong start_data;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-15 16:06 ` Helge Deller
@ 2026-06-15 17:33 ` Pierrick Bouvier
2026-06-17 12:41 ` valium
1 sibling, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2026-06-15 17:33 UTC (permalink / raw)
To: Helge Deller, valium007, qemu-devel; +Cc: laurent
On 6/15/2026 9:06 AM, Helge Deller wrote:
> On 6/13/26 17:21, valium007 wrote:
>> When a binary is patched or relocated such that the program header
>> table is
>> moved into a separate PT_LOAD segment
>
> How relevant is this? How/why does it happen?
>
Maybe a tcg test could be provided to show how it can be reproduced, and
check this patch fixes the problem.
>> (rather than sitting at the start of the
>> first loadable segment), QEMU's AT_PHDR auxv entry becomes incorrect. The
>> loader was computing AT_PHDR as load_addr + e_phoff, which assumes the
>> headers
>> are mapped 1:1 from file offset 0. This breaks when the headers are
>> elsewhere.
>>
>> The Linux kernel instead locates the PT_LOAD segment that contains
>> e_phoff,
>> then computes the in-memory address as p_vaddr + (e_phoff - p_offset).
>> This
>> correctly handles relocated headers.
>
> Ok, I need to check on this.
>
>> Fix by:
>> 1. Add phdr_addr field to image_info to cache the resolved address.
>> 2. Initialize to load_addr + e_phoff (fallback for headers outside any
>> PT_LOAD).
>> 3. In the PT_LOAD mapping loop, detect if the segment contains e_phoff
>> and
>> override with the segment-relative address.
>> 4. Use info->phdr_addr for AT_PHDR instead of the incorrect formula.
>>
>> Signed-off-by: valium007 <valium7171@gmail.com>
>
> Can you sign with a real name?
>
> Helge
>
>> ---
>> linux-user/elfload.c | 21 ++++++++++++++++++++-
>> linux-user/qemu.h | 1 +
>> 2 files changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>> index b05b8b0..8049c8a 100644
>> --- a/linux-user/elfload.c
>> +++ b/linux-user/elfload.c
>> @@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p,
>> int argc, int envc,
>> /* There must be exactly DLINFO_ITEMS entries here, or the assert
>> * on info->auxv_len will trigger.
>> */
>> - NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
>> + NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
>> NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
>> NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
>> NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
>> @@ -1469,6 +1469,12 @@ static void load_elf_image(const char
>> *image_name, const ImageSource *src,
>> info->data_offset = load_bias;
>> info->load_addr = load_addr;
>> info->entry = ehdr->e_entry + load_bias;
>> + /*
>> + * Fallback for AT_PHDR if the program headers do not fall within
>> + * any PT_LOAD segment (see the loop below, which overrides this
>> with
>> + * the correct in-memory address when a containing segment is
>> found).
>> + */
>> + info->phdr_addr = load_addr + ehdr->e_phoff;
>> info->start_code = -1;
>> info->end_code = 0;
>> info->start_data = -1;
>> @@ -1523,6 +1529,19 @@ static void load_elf_image(const char
>> *image_name, const ImageSource *src,
>> vaddr_ef = vaddr + eppnt->p_filesz;
>> vaddr_em = vaddr + eppnt->p_memsz;
>> + /*
>> + * If this segment contains the program headers, record
>> their
>> + * in-memory address for AT_PHDR. This matches the
>> kernel, which
>> + * locates the headers via the containing PT_LOAD rather
>> than
>> + * assuming load_addr + e_phoff (false when the phdrs are
>> not
>> + * mapped 1:1 from file offset 0, e.g. relocated into
>> their own
>> + * segment by a binary patcher).
>> + */
>> + if (eppnt->p_offset <= ehdr->e_phoff &&
>> + ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
>> + info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt-
>> >p_offset);
>> + }
>> +
>> /*
>> * Some segments may be completely empty, with a non-
>> zero p_memsz
>> * but no backing file segment.
>> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
>> index 07fe801..2268493 100644
>> --- a/linux-user/qemu.h
>> +++ b/linux-user/qemu.h
>> @@ -26,6 +26,7 @@
>> struct image_info {
>> abi_ulong load_bias;
>> abi_ulong load_addr;
>> + abi_ulong phdr_addr;
>> abi_ulong start_code;
>> abi_ulong end_code;
>> abi_ulong start_data;
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-15 16:06 ` Helge Deller
2026-06-15 17:33 ` Pierrick Bouvier
@ 2026-06-17 12:41 ` valium
2026-06-17 16:48 ` Helge Deller
1 sibling, 1 reply; 6+ messages in thread
From: valium @ 2026-06-17 12:41 UTC (permalink / raw)
To: Helge Deller, valium007, qemu-devel; +Cc: laurent, pierrick.bouvier
On Mon Jun 15, 2026 at 9:36 PM IST, Helge Deller wrote:
> On 6/13/26 17:21, valium007 wrote:
>> When a binary is patched or relocated such that the program header table is
>> moved into a separate PT_LOAD segment
>
> How relevant is this? How/why does it happen?
This is very much relevant with the issue. This can happen when certain
packers/protectors move the phdrs into a separate PT_LOAD for the
purpose of anti-tamper/protection mechanisms. The patched binary will
run on real environment but not on QEMU (in most cases the binary will
segfault).
> Can you sign with a real name?
Sure, this is my very first patch on qemu, to continue with this I think
I need to send the patch again with my real name signed off?
>> ---
>> linux-user/elfload.c | 21 ++++++++++++++++++++-
>> linux-user/qemu.h | 1 +
>> 2 files changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>> index b05b8b0..8049c8a 100644
>> --- a/linux-user/elfload.c
>> +++ b/linux-user/elfload.c
>> @@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>> /* There must be exactly DLINFO_ITEMS entries here, or the assert
>> * on info->auxv_len will trigger.
>> */
>> - NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
>> + NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
>> NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
>> NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
>> NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
>> @@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>> info->data_offset = load_bias;
>> info->load_addr = load_addr;
>> info->entry = ehdr->e_entry + load_bias;
>> + /*
>> + * Fallback for AT_PHDR if the program headers do not fall within
>> + * any PT_LOAD segment (see the loop below, which overrides this with
>> + * the correct in-memory address when a containing segment is found).
>> + */
>> + info->phdr_addr = load_addr + ehdr->e_phoff;
>> info->start_code = -1;
>> info->end_code = 0;
>> info->start_data = -1;
>> @@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>> vaddr_ef = vaddr + eppnt->p_filesz;
>> vaddr_em = vaddr + eppnt->p_memsz;
>>
>> + /*
>> + * If this segment contains the program headers, record their
>> + * in-memory address for AT_PHDR. This matches the kernel, which
>> + * locates the headers via the containing PT_LOAD rather than
>> + * assuming load_addr + e_phoff (false when the phdrs are not
>> + * mapped 1:1 from file offset 0, e.g. relocated into their own
>> + * segment by a binary patcher).
>> + */
>> + if (eppnt->p_offset <= ehdr->e_phoff &&
>> + ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
>> + info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
>> + }
>> +
>> /*
>> * Some segments may be completely empty, with a non-zero p_memsz
>> * but no backing file segment.
>> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
>> index 07fe801..2268493 100644
>> --- a/linux-user/qemu.h
>> +++ b/linux-user/qemu.h
>> @@ -26,6 +26,7 @@
>> struct image_info {
>> abi_ulong load_bias;
>> abi_ulong load_addr;
>> + abi_ulong phdr_addr;
>> abi_ulong start_code;
>> abi_ulong end_code;
>> abi_ulong start_data;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-17 12:41 ` valium
@ 2026-06-17 16:48 ` Helge Deller
2026-06-17 17:48 ` valium
0 siblings, 1 reply; 6+ messages in thread
From: Helge Deller @ 2026-06-17 16:48 UTC (permalink / raw)
To: valium, qemu-devel; +Cc: laurent, pierrick.bouvier
On 6/17/26 14:41, valium wrote:
> On Mon Jun 15, 2026 at 9:36 PM IST, Helge Deller wrote:
>> On 6/13/26 17:21, valium007 wrote:
>>> When a binary is patched or relocated such that the program header table is
>>> moved into a separate PT_LOAD segment
>>
>> How relevant is this? How/why does it happen?
>
> This is very much relevant with the issue. This can happen when certain
> packers/protectors move the phdrs into a separate PT_LOAD for the
> purpose of anti-tamper/protection mechanisms. The patched binary will
> run on real environment but not on QEMU (in most cases the binary will
> segfault).
Ok. (Still seems like a niche issue).
>> Can you sign with a real name?
>
> Sure, this is my very first patch on qemu, to continue with this I think
> I need to send the patch again with my real name signed off?
It's sufficient if you let us know what it should be.
Helge
>
>>> ---
>>> linux-user/elfload.c | 21 ++++++++++++++++++++-
>>> linux-user/qemu.h | 1 +
>>> 2 files changed, 21 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>>> index b05b8b0..8049c8a 100644
>>> --- a/linux-user/elfload.c
>>> +++ b/linux-user/elfload.c
>>> @@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>>> /* There must be exactly DLINFO_ITEMS entries here, or the assert
>>> * on info->auxv_len will trigger.
>>> */
>>> - NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
>>> + NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
>>> NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
>>> NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
>>> NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
>>> @@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>>> info->data_offset = load_bias;
>>> info->load_addr = load_addr;
>>> info->entry = ehdr->e_entry + load_bias;
>>> + /*
>>> + * Fallback for AT_PHDR if the program headers do not fall within
>>> + * any PT_LOAD segment (see the loop below, which overrides this with
>>> + * the correct in-memory address when a containing segment is found).
>>> + */
>>> + info->phdr_addr = load_addr + ehdr->e_phoff;
>>> info->start_code = -1;
>>> info->end_code = 0;
>>> info->start_data = -1;
>>> @@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>>> vaddr_ef = vaddr + eppnt->p_filesz;
>>> vaddr_em = vaddr + eppnt->p_memsz;
>>>
>>> + /*
>>> + * If this segment contains the program headers, record their
>>> + * in-memory address for AT_PHDR. This matches the kernel, which
>>> + * locates the headers via the containing PT_LOAD rather than
>>> + * assuming load_addr + e_phoff (false when the phdrs are not
>>> + * mapped 1:1 from file offset 0, e.g. relocated into their own
>>> + * segment by a binary patcher).
>>> + */
>>> + if (eppnt->p_offset <= ehdr->e_phoff &&
>>> + ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
>>> + info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
>>> + }
>>> +
>>> /*
>>> * Some segments may be completely empty, with a non-zero p_memsz
>>> * but no backing file segment.
>>> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
>>> index 07fe801..2268493 100644
>>> --- a/linux-user/qemu.h
>>> +++ b/linux-user/qemu.h
>>> @@ -26,6 +26,7 @@
>>> struct image_info {
>>> abi_ulong load_bias;
>>> abi_ulong load_addr;
>>> + abi_ulong phdr_addr;
>>> abi_ulong start_code;
>>> abi_ulong end_code;
>>> abi_ulong start_data;
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-17 16:48 ` Helge Deller
@ 2026-06-17 17:48 ` valium
0 siblings, 0 replies; 6+ messages in thread
From: valium @ 2026-06-17 17:48 UTC (permalink / raw)
To: Helge Deller, valium, qemu-devel; +Cc: laurent, pierrick.bouvier
On Wed Jun 17, 2026 at 10:18 PM IST, Helge Deller wrote:
> It's sufficient if you let us know what it should be.
My real name is Akshit Yadav.
>>
>>>> ---
>>>> linux-user/elfload.c | 21 ++++++++++++++++++++-
>>>> linux-user/qemu.h | 1 +
>>>> 2 files changed, 21 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>>>> index b05b8b0..8049c8a 100644
>>>> --- a/linux-user/elfload.c
>>>> +++ b/linux-user/elfload.c
>>>> @@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>>>> /* There must be exactly DLINFO_ITEMS entries here, or the assert
>>>> * on info->auxv_len will trigger.
>>>> */
>>>> - NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
>>>> + NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
>>>> NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
>>>> NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
>>>> NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
>>>> @@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>>>> info->data_offset = load_bias;
>>>> info->load_addr = load_addr;
>>>> info->entry = ehdr->e_entry + load_bias;
>>>> + /*
>>>> + * Fallback for AT_PHDR if the program headers do not fall within
>>>> + * any PT_LOAD segment (see the loop below, which overrides this with
>>>> + * the correct in-memory address when a containing segment is found).
>>>> + */
>>>> + info->phdr_addr = load_addr + ehdr->e_phoff;
>>>> info->start_code = -1;
>>>> info->end_code = 0;
>>>> info->start_data = -1;
>>>> @@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
>>>> vaddr_ef = vaddr + eppnt->p_filesz;
>>>> vaddr_em = vaddr + eppnt->p_memsz;
>>>>
>>>> + /*
>>>> + * If this segment contains the program headers, record their
>>>> + * in-memory address for AT_PHDR. This matches the kernel, which
>>>> + * locates the headers via the containing PT_LOAD rather than
>>>> + * assuming load_addr + e_phoff (false when the phdrs are not
>>>> + * mapped 1:1 from file offset 0, e.g. relocated into their own
>>>> + * segment by a binary patcher).
>>>> + */
>>>> + if (eppnt->p_offset <= ehdr->e_phoff &&
>>>> + ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
>>>> + info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
>>>> + }
>>>> +
>>>> /*
>>>> * Some segments may be completely empty, with a non-zero p_memsz
>>>> * but no backing file segment.
>>>> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
>>>> index 07fe801..2268493 100644
>>>> --- a/linux-user/qemu.h
>>>> +++ b/linux-user/qemu.h
>>>> @@ -26,6 +26,7 @@
>>>> struct image_info {
>>>> abi_ulong load_bias;
>>>> abi_ulong load_addr;
>>>> + abi_ulong phdr_addr;
>>>> abi_ulong start_code;
>>>> abi_ulong end_code;
>>>> abi_ulong start_data;
>>
>>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-17 17:49 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-13 15:21 [PATCH] linux-user: Fix AT_PHDR when program headers are relocated into their own segment valium007
2026-06-15 16:06 ` Helge Deller
2026-06-15 17:33 ` Pierrick Bouvier
2026-06-17 12:41 ` valium
2026-06-17 16:48 ` Helge Deller
2026-06-17 17:48 ` valium
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.