Hi all,
yesterday I run into the ELF like this :

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000074 0x00008000 0x00000000 0xe1f18 0xe1f18 RWE 0x1
  LOAD           0x0e1f8c 0x0060f028 0x00000000 0x1103f 0x1103f RWE 0x1

As it can be seen from the readelf output, PhysAddress of the segments
is 0x0, and this posed problems for the load_image command of OpenOCD.
However, arm GDB was very happy to load it, loading section by section
at appropriate virtual addresses.

I did some investigation, and I found out (from ELF specification) :
p_vaddr : This member gives the virtual address at which the first
byte of the segment resides in
memory.
p_paddr : On systems for which physical addressing is relevant, this
member is reserved for the
segment’s physical address. Because System V ignores physical
addressing for application
programs, this member has unspecified contents for executable files and shared
objects.

Then I run into these posts :
http://cygwin.com/ml/binutils/2002-09/msg00516.html
http://lists.gnu.org/archive/html/bug-gnu-utils/2002-08/msg00319.html

ARM ELF specification seems to be stating explicitly that p_paddr in
the Program Header Table should be put to zero for all Text, Data and
BSS segments:
p_vaddr - load address of the segment
p_paddr - 0

Further on, in "Scatter-loaded Executables" part of the same document it says :
sh_addr: same as p_vaddr of corresponding Segment

The p_vaddr field of each Segment of a scatter-loaded Executable is
the load address
of the Segment, which need not necessarily be its execution address.
Startup code can
move (part of) a Segment to its execution address using the symbols:
Load$$reg$$Base
Image$$reg$$Base
Image$$reg$$Length
as described in the Software Development Toolkit User Guide.

I am guessing that GDB uses this method and always takes p_vaddr
(OpenOCD is not consistent to GDB in this case).

To conclude, I crafted a trivial patch which will impose taking
p_vaddr as the load destination of the segment whenever p_paddr is
0x0.
I was a bit afraid to go for p_vaddr only_and_always, but left this as
a solution, because I do not know the impact on other architectures,
so I followed this post :
http://www.mail-archive.com/[email protected]/msg00715.html

What do you think ?

Best regards,
Drasko
From f4d2841959946ed156f569314dc82795c880bae9 Mon Sep 17 00:00:00 2001
From: Drasko DRASKOVIC <[email protected]>
Date: Tue, 21 Jun 2011 13:10:35 +0200
Subject: [PATCH] load_image command should use virtual address (p_vaddr) for ELF

So far image_load command tries to load ELF binaries to address
discovered by reading p_paddr member of a Program header of an ELF
segment.

However, ELF specifications says for p_paddr : ...Because System V ignores physical addressing
for application programs, this member has unspecified contents for executable files
and shared objects.

ARM ELF specifiaction goes even further, demanding that this member be
set to zero, using the p_vaddr as a segment load address.

To avoid the cases to wrong addr where p_paddr is zero,
we are now using p_vaddr to as a load destination in case that p_paddr
== 0. If p_addr is !=0, we are using it and not p_vaddr (to keep compatibility
with other platforms, if any).
---
 src/target/image.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/src/target/image.c b/src/target/image.c
index 454fc6c..af12d7c 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -478,7 +478,10 @@ static int image_elf_read_headers(struct image *image)
 		if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
 		{
 			image->sections[j].size = field32(elf,elf->segments[i].p_filesz);
-			image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
+			if (elf->segments[i].p_paddr != 0)
+				image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
+			else
+				image->sections[j].base_address = field32(elf,elf->segments[i].p_vaddr);
 			image->sections[j].private = &elf->segments[i];
 			image->sections[j].flags = field32(elf,elf->segments[i].p_flags);
 			j++;
-- 
1.5.6.5

_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to