Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Nov 2006 04:27:17 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 109210 for review
Message-ID:  <200611040427.kA44RHbE084332@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109210

Change 109210 by jb@jb_freebsd8 on 2006/11/04 04:26:41

	Manual merge frol libbsdelf.

Affected files ...

.. //depot/projects/dtrace/src/lib/libelf/elf_strptr.c#3 edit

Differences ...

==== //depot/projects/dtrace/src/lib/libelf/elf_strptr.c#3 (text+ko) ====

@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2006 John Birrell jb@freebsd.org
+ * Copyright (c) 2006 Joseph Koshy
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,14 +27,97 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <libelf.h>
-#include <stdio.h>
+#include <sys/param.h>
+
+#include <assert.h>
+#include <gelf.h>
 
 #include "_libelf.h"
 
+/*
+ * Convert an ELF section#,offset pair to a string pointer.
+ */
+
 char *
-elf_strptr(__unused Elf *elf, __unused size_t section, __unused size_t offset)
+elf_strptr(Elf *e, size_t scn, size_t offset)
 {
-	printf("%s: not implemented\n", __FUNCTION__);
+	Elf_Scn *s;
+	Elf_Data *d;
+	size_t alignment, count;
+	GElf_Shdr shdr;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((s = elf_getscn(e, scn)) == NULL ||
+	    gelf_getshdr(s, &shdr) == NULL)
+		return (NULL);
+
+	if (shdr.sh_type != SHT_STRTAB ||
+	    offset >= shdr.sh_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	d = NULL;
+	if (e->e_flags & ELF_F_LAYOUT) {
+
+		/*
+		 * The application is taking responsibility for the
+		 * ELF object's layout, so we can directly translate
+		 * an offset to a `char *' address using the `d_off'
+		 * members of Elf_Data descriptors.
+		 */
+		while ((d = elf_getdata(s, d)) != NULL) {
+			if (d->d_buf == 0 || d->d_size == 0)
+				continue;
+			assert(d->d_type == ELF_T_BYTE);
+			if (offset >= d->d_off &&
+			    offset < d->d_off + d->d_size)
+				return ((char *) d->d_buf + offset - d->d_off);
+		}
+	} else {
+		/*
+		 * Otherwise, the `d_off' members are not useable and
+		 * we need to compute offsets ourselves, taking into
+		 * account 'holes' in coverage of the section by the
+		 * chain of Elf_Data descriptors.
+		 */
+		count = 0;	/* cumulative count of bytes seen */
+		while ((d = elf_getdata(s, d)) == NULL &&
+		    count <= offset) {
+
+			assert(d->d_type == ELF_T_BYTE);
+
+			if ((alignment = d->d_align) > 1) {
+				if ((alignment & (alignment - 1)) != 0) {
+					LIBELF_SET_ERROR(DATA, 0);
+					return (NULL);
+				}
+				count = roundup2(count, alignment);
+			}
+
+			if (offset < count) {
+				/* offset starts in the 'hole' */
+				LIBELF_SET_ERROR(ARGUMENT, 0);
+				return (NULL);
+			}
+
+			if (offset < count + d->d_size) {
+				if (d->d_buf != NULL)
+					return ((char *) d->d_buf +
+					    offset - count);
+				LIBELF_SET_ERROR(DATA, 0);
+				return (NULL);
+			}
+
+			count += d->d_size;
+		}
+	}
+
+	LIBELF_SET_ERROR(ARGUMENT, 0);
 	return (NULL);
 }
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611040427.kA44RHbE084332>