Index: chrome/nacl/nacl_helper_bootstrap_linux.c |
diff --git a/chrome/nacl/nacl_helper_bootstrap_linux.c b/chrome/nacl/nacl_helper_bootstrap_linux.c |
index 68d004c33596c28e01a480b6e69a7f7265479959..b207a8b7406aae3e733101635be30191b0a021a4 100644 |
--- a/chrome/nacl/nacl_helper_bootstrap_linux.c |
+++ b/chrome/nacl/nacl_helper_bootstrap_linux.c |
@@ -27,6 +27,15 @@ |
#define MAX_PHNUM 12 |
+/* |
+ * This exact magic argument string is recognized in check_r_debug_arg, below. |
+ */ |
+#define R_DEBUG_TEMPLATE_PREFIX "--r_debug=0x" |
+#define R_DEBUG_TEMPLATE_DIGITS "XXXXXXXXXXXXXXXX" |
+static const char kRDebugTemplate[] = |
+ R_DEBUG_TEMPLATE_PREFIX R_DEBUG_TEMPLATE_DIGITS; |
+static const size_t kRDebugPrefixLen = sizeof R_DEBUG_TEMPLATE_PREFIX - 1; |
Mark Seaborn
2011/11/14 20:15:41
consistency: elsewhere you use sizeof() (i.e. with
|
+ |
/* |
* We're not using <string.h> functions here, to avoid dependencies. |
@@ -48,6 +57,16 @@ static size_t my_strlen(const char *s) { |
return n; |
} |
+static int my_strcmp(const char *a, const char *b) { |
+ while (*a == *b) { |
+ if (*a == '\0') |
+ return 0; |
+ ++a; |
+ ++b; |
+ } |
+ return (int) (unsigned char) *a - (int) (unsigned char) *b; |
+} |
+ |
/* |
* Get inline functions for system calls. |
@@ -347,6 +366,35 @@ static ElfW(Addr) load_elf_file(const char *filename, |
return ehdr.e_entry + load_bias; |
} |
+ |
+/* |
+ * GDB looks for this symbol name when it cannot find PT_DYNAMIC->DT_DEBUG. |
+ * We don't have a PT_DYNAMIC, so it will find this. Now all we have to do |
+ * is arrange for this space to be filled in with the dynamic linker's |
+ * _r_debug contents after they're initialized. That way, attaching GDB to |
+ * this process or examining its core file will find the PIE we loaded, the |
+ * dynamic linker, and all the shared libraries, making debugging pleasant. |
+ */ |
+struct r_debug _r_debug __attribute__((nocommon, section(".r_debug"))); |
+ |
+/* |
+ * If the argument matches the kRDebugTemplate string, then replace |
+ * the 16 Xs with the hexadecimal address of our _r_debug variable. |
+ */ |
+static int check_r_debug_arg(char *arg) { |
+ if (!my_strcmp(arg, kRDebugTemplate)) { |
Mark Seaborn
2011/11/14 20:15:41
prefer "strcmp(x,y) == 0" since strcmp()'s result
|
+ uintptr_t addr = (uintptr_t) &_r_debug; |
+ size_t i = 16; |
+ while (i-- > 0) { |
+ arg[kRDebugPrefixLen + i] = "0123456789abcdef"[addr & 0xf]; |
+ addr >>= 4; |
+ } |
+ return 1; |
+ } |
+ return 0; |
+} |
+ |
+ |
/* |
* This is the main loading code. It's called with the starting stack pointer. |
* This points to a sequence of pointer-size words: |
@@ -402,6 +450,16 @@ ElfW(Addr) do_load(uintptr_t *stack) { |
stack[i] = stack[i + 1]; |
/* |
+ * If one of our arguments is the kRDebugTemplate string, then |
+ * we'll modify that argument string in place to specify the |
+ * address of our _r_debug structure. |
+ */ |
+ for (i = 1; i < argc; ++i) { |
+ if (check_r_debug_arg(argv[i])) |
+ break; |
+ } |
+ |
+ /* |
* Record the auxv entries that are specific to the file loaded. |
* The incoming entries point to our own static executable. |
*/ |