Chromium Code Reviews| 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. |
| */ |