amd64 kernel modules: mapping sections to addresses

Andriy Gapon avg at freebsd.org
Tue Jun 22 09:21:32 UTC 2010


on 22/06/2010 00:34 Andriy Gapon said the following:
> gdb change - I'd rather do it via kld_current_sos,
> kld_relocate_section_addresses.  I'd like to avoid changing common gdb code for
> a variety of reasons.

I came up with the following patch.
EXEC_P and DYNAMIC flags are bfd library equivalents of ET_EXEC and ET_DYN elf
flags.  Absence of both of these flags means ET_REL, which is a type of our
amd64 kernel modules.
The code all resides in kld.c and acts only kernel modules that are either
auto-loaded via kld_current_sos or explicitly added with add-kld.
I used a static variable in kld_relocate_section_addresses because that function
is called on each section sequentially, so current offset can not be stored on
stack.  The offset is reset to module's load address when see that we are called
with first section.  Alternative is to glimpse at previous section's end address
as you did.  So the code depends on sections being passed in forward sequential
order.

How does this look?
Could you please test it?

diff --git a/gnu/usr.bin/gdb/kgdb/kld.c b/gnu/usr.bin/gdb/kgdb/kld.c
index 716a67c..d5ba20a 100644
--- a/gnu/usr.bin/gdb/kgdb/kld.c
+++ b/gnu/usr.bin/gdb/kgdb/kld.c
@@ -198,12 +198,32 @@ find_kld_address (char *arg, CORE_ADDR *address)
 }

 static void
+adjust_section_address (struct section_table *sec, CORE_ADDR *curr_base)
+{
+	struct bfd_section *asect = sec->the_bfd_section;
+	bfd *abfd = sec->bfd;
+
+	if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) {
+		sec->addr += *curr_base;
+		sec->endaddr += *curr_base;
+		return;
+	}
+
+	*curr_base = align_power(*curr_base,
+	    bfd_get_section_alignment(abfd, asect));
+	sec->addr = *curr_base;
+	sec->endaddr = sec->addr + bfd_section_size(abfd, asect);
+	*curr_base = sec->endaddr;
+}
+
+static void
 load_kld (char *path, CORE_ADDR base_addr, int from_tty)
 {
 	struct section_addr_info *sap;
 	struct section_table *sections = NULL, *sections_end = NULL, *s;
 	struct cleanup *cleanup;
 	bfd *bfd;
+	CORE_ADDR curr_addr;
 	int i;

 	/* Open the kld. */
@@ -224,10 +244,9 @@ load_kld (char *path, CORE_ADDR base_addr, int from_tty)
 	if (build_section_table (bfd, &sections, &sections_end))
 		error("\"%s\": can't find file sections", path);
 	cleanup = make_cleanup(xfree, sections);
-	for (s = sections; s < sections_end; s++) {
-		s->addr += base_addr;
-		s->endaddr += base_addr;
-	}
+	curr_addr = base_addr;
+	for (s = sections; s < sections_end; s++)
+		adjust_section_address(s, &curr_addr);

 	/* Build a section addr info to pass to symbol_file_add(). */
 	sap = build_section_addr_info_from_section_table (sections,
@@ -284,9 +303,12 @@ kgdb_add_kld_cmd (char *arg, int from_tty)
 static void
 kld_relocate_section_addresses (struct so_list *so, struct section_table *sec)
 {
+	static CORE_ADDR curr_addr;
+
+	if (sec == so->sections)
+		curr_addr = so->lm_info->base_address;

-	sec->addr += so->lm_info->base_address;
-	sec->endaddr += so->lm_info->base_address;
+	adjust_section_address(sec, &curr_addr);
 }

 static void


-- 
Andriy Gapon


More information about the freebsd-hackers mailing list