2014-01-01 04:54:24 +01:00
|
|
|
/* Copyright 2013-2014 Free Software Foundation, Inc.
|
2013-07-17 11:44:26 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
#include <limits.h>
|
2013-07-17 11:44:26 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
|
|
|
#include "sym-file-loader.h"
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <ansidecl.h>
|
|
|
|
#include <elf/common.h>
|
|
|
|
#include <elf/external.h>
|
|
|
|
|
|
|
|
#ifdef TARGET_LP64
|
|
|
|
|
|
|
|
typedef Elf64_External_Phdr Elf_External_Phdr;
|
|
|
|
typedef Elf64_External_Ehdr Elf_External_Ehdr;
|
|
|
|
typedef Elf64_External_Shdr Elf_External_Shdr;
|
|
|
|
typedef Elf64_External_Sym Elf_External_Sym;
|
|
|
|
typedef uint64_t Elf_Addr;
|
|
|
|
|
|
|
|
#elif defined TARGET_ILP32
|
|
|
|
|
|
|
|
typedef Elf32_External_Phdr Elf_External_Phdr;
|
|
|
|
typedef Elf32_External_Ehdr Elf_External_Ehdr;
|
|
|
|
typedef Elf32_External_Shdr Elf_External_Shdr;
|
|
|
|
typedef Elf32_External_Sym Elf_External_Sym;
|
|
|
|
typedef uint32_t Elf_Addr;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define GET(hdr, field) (\
|
|
|
|
sizeof ((hdr)->field) == 1 ? (uint64_t) (hdr)->field[0] : \
|
|
|
|
sizeof ((hdr)->field) == 2 ? (uint64_t) *(uint16_t *) (hdr)->field : \
|
|
|
|
sizeof ((hdr)->field) == 4 ? (uint64_t) *(uint32_t *) (hdr)->field : \
|
|
|
|
sizeof ((hdr)->field) == 8 ? *(uint64_t *) (hdr)->field : \
|
|
|
|
*(uint64_t *) NULL)
|
|
|
|
|
|
|
|
#define GETADDR(hdr, field) (\
|
|
|
|
sizeof ((hdr)->field) == sizeof (Elf_Addr) ? *(Elf_Addr *) (hdr)->field : \
|
|
|
|
*(Elf_Addr *) NULL)
|
|
|
|
|
|
|
|
struct segment
|
|
|
|
{
|
|
|
|
uint8_t *mapped_addr;
|
|
|
|
Elf_External_Phdr *phdr;
|
|
|
|
struct segment *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct library
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
Elf_External_Ehdr *ehdr;
|
|
|
|
struct segment *segments;
|
|
|
|
};
|
|
|
|
|
|
|
|
static Elf_External_Shdr *find_shdr (Elf_External_Ehdr *ehdr,
|
|
|
|
const char *section);
|
|
|
|
static int translate_offset (uint64_t file_offset, struct segment *seg,
|
|
|
|
void **addr);
|
|
|
|
|
2013-07-17 11:44:26 +02:00
|
|
|
#ifdef TARGET_LP64
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
elf_st_type (uint8_t st_info)
|
|
|
|
{
|
|
|
|
return ELF64_ST_TYPE (st_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined TARGET_ILP32
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
elf_st_type (uint8_t st_info)
|
|
|
|
{
|
|
|
|
return ELF32_ST_TYPE (st_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Load a program segment. */
|
|
|
|
|
|
|
|
static struct segment *
|
|
|
|
load (uint8_t *addr, Elf_External_Phdr *phdr, struct segment *tail_seg)
|
|
|
|
{
|
|
|
|
struct segment *seg = NULL;
|
|
|
|
uint8_t *mapped_addr = NULL;
|
|
|
|
void *from = NULL;
|
|
|
|
void *to = NULL;
|
|
|
|
|
|
|
|
/* For the sake of simplicity all operations are permitted. */
|
|
|
|
unsigned perm = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
|
|
|
|
|
|
mapped_addr = (uint8_t *) mmap ((void *) GETADDR (phdr, p_vaddr),
|
|
|
|
GET (phdr, p_memsz), perm,
|
|
|
|
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
|
|
|
|
|
|
from = (void *) (addr + GET (phdr, p_offset));
|
|
|
|
to = (void *) mapped_addr;
|
|
|
|
|
|
|
|
memcpy (to, from, GET (phdr, p_filesz));
|
|
|
|
|
|
|
|
seg = (struct segment *) malloc (sizeof (struct segment));
|
|
|
|
|
|
|
|
if (seg == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
seg->mapped_addr = mapped_addr;
|
|
|
|
seg->phdr = phdr;
|
|
|
|
seg->next = 0;
|
|
|
|
|
|
|
|
if (tail_seg != 0)
|
|
|
|
tail_seg->next = seg;
|
|
|
|
|
|
|
|
return seg;
|
|
|
|
}
|
|
|
|
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
#ifdef __linux__
|
|
|
|
# define SELF_LINK "/proc/self/exe"
|
|
|
|
#elif defined NETBSD
|
2014-04-15 15:13:08 +02:00
|
|
|
# define SELF_LINK "/proc/curproc/exe"
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
#elif defined __OpenBSD__ || defined __FreeBSD__ || defined __DragonFly__
|
2014-04-15 15:13:08 +02:00
|
|
|
# define SELF_LINK "/proc/curproc/file"
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
#elif defined SunOS
|
2014-04-15 15:13:08 +02:00
|
|
|
# define SELF_LINK "/proc/self/path/a.out"
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Like RPATH=$ORIGIN, return the dirname of the current
|
|
|
|
executable. */
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
get_origin (void)
|
|
|
|
{
|
|
|
|
static char self_path[PATH_MAX];
|
|
|
|
static ssize_t self_path_len;
|
|
|
|
|
|
|
|
if (self_path_len == 0)
|
|
|
|
{
|
|
|
|
#ifdef SELF_LINK
|
|
|
|
self_path_len = readlink (SELF_LINK, self_path, PATH_MAX - 1);
|
|
|
|
if (self_path_len != -1)
|
|
|
|
{
|
|
|
|
char *dirsep;
|
|
|
|
|
|
|
|
self_path[self_path_len] = '\0';
|
|
|
|
dirsep = strrchr (self_path, '/');
|
|
|
|
*dirsep = '\0';
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
self_path_len = -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self_path_len == -1)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return self_path;
|
|
|
|
}
|
|
|
|
|
2013-07-17 11:44:26 +02:00
|
|
|
/* Mini shared library loader. No reallocation
|
|
|
|
is performed for the sake of simplicity. */
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
struct library *
|
|
|
|
load_shlib (const char *file)
|
2013-07-17 11:44:26 +02:00
|
|
|
{
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
struct library *lib;
|
2013-07-17 11:44:26 +02:00
|
|
|
uint64_t i;
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
int fd = -1;
|
2013-07-17 11:44:26 +02:00
|
|
|
off_t fsize;
|
|
|
|
uint8_t *addr;
|
|
|
|
Elf_External_Ehdr *ehdr;
|
|
|
|
Elf_External_Phdr *phdr;
|
|
|
|
struct segment *head_seg = NULL;
|
|
|
|
struct segment *tail_seg = NULL;
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
const char *origin;
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
/* Map the lib in memory for reading.
|
|
|
|
|
|
|
|
If the file name is relative, try looking it up relative to the
|
|
|
|
main executable's path. I.e., emulate RPATH=$ORIGIN. */
|
|
|
|
if (file[0] != '/')
|
|
|
|
{
|
|
|
|
origin = get_origin ();
|
|
|
|
if (origin == NULL)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "get_origin not implemented.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
Make sym-file.exp work with remote targets and hosts.
The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.
Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN. See gdb_compile.
This test doesn't use dlopen, but instead uses its own simple elf
loader. The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.
Tested on x86_64 Fedora 17, native and gdbserver.
I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs. I think I covered all relevant, but if
not, I think it'll be simple enough to add more. (Note the test is
skipped on non-ELF targets.)
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.c: Include <limits.h>.
(SELF_LINK): New define.
(get_origin): New function.
(load_shlib): Use it.
* gdb.base/sym-file.exp: Don't early return if the target is
remote. Use runto_main, and issue fail is that fails. Use
gdb_load_shlibs.
(shlib_name): Delete.
(lib_so, lib_syms, lib_dlopen): New globals. Use them throughout.
2014-04-14 18:23:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
path = alloca (strlen (origin) + 1 + strlen (file) + 1);
|
|
|
|
sprintf (path, "%s/%s", origin, file);
|
|
|
|
fd = open (path, O_RDONLY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
fd = open (file, O_RDONLY);
|
2013-07-17 11:44:26 +02:00
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
{
|
|
|
|
perror ("fopen failed.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fsize = lseek (fd, 0, SEEK_END);
|
|
|
|
|
|
|
|
if (fsize < 0)
|
|
|
|
{
|
|
|
|
perror ("lseek failed.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
addr = (uint8_t *) mmap (NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
|
|
if (addr == (uint8_t *) -1)
|
|
|
|
{
|
|
|
|
perror ("mmap failed.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the lib is an ELF file. */
|
|
|
|
ehdr = (Elf_External_Ehdr *) addr;
|
|
|
|
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|
|
|
|
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
|
|
|
|
|| ehdr->e_ident[EI_MAG2] != ELFMAG2
|
|
|
|
|| ehdr->e_ident[EI_MAG3] != ELFMAG3)
|
|
|
|
{
|
|
|
|
printf ("Not an ELF file: %x\n", ehdr->e_ident[EI_MAG0]);
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
|
|
|
|
{
|
|
|
|
if (sizeof (void *) != 4)
|
|
|
|
{
|
|
|
|
printf ("Architecture mismatch.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
|
|
|
|
{
|
|
|
|
if (sizeof (void *) != 8)
|
|
|
|
{
|
|
|
|
printf ("Architecture mismatch.");
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
return NULL;
|
2013-07-17 11:44:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
lib = malloc (sizeof (struct library));
|
|
|
|
if (lib == NULL)
|
|
|
|
{
|
|
|
|
printf ("malloc failed.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
lib->fd = fd;
|
|
|
|
|
2013-07-17 11:44:26 +02:00
|
|
|
/* Load the program segments. For the sake of simplicity
|
|
|
|
assume that no reallocation is needed. */
|
|
|
|
phdr = (Elf_External_Phdr *) (addr + GET (ehdr, e_phoff));
|
|
|
|
for (i = 0; i < GET (ehdr, e_phnum); i++, phdr++)
|
|
|
|
{
|
|
|
|
if (GET (phdr, p_type) == PT_LOAD)
|
|
|
|
{
|
|
|
|
struct segment *next_seg = load (addr, phdr, tail_seg);
|
|
|
|
if (next_seg == 0)
|
|
|
|
continue;
|
|
|
|
tail_seg = next_seg;
|
|
|
|
if (head_seg == 0)
|
|
|
|
head_seg = next_seg;
|
|
|
|
}
|
|
|
|
}
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
lib->ehdr = ehdr;
|
|
|
|
lib->segments = head_seg;
|
|
|
|
return lib;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
get_text_addr (struct library *lib, void **text_addr)
|
|
|
|
{
|
|
|
|
Elf_External_Shdr *text;
|
|
|
|
|
|
|
|
/* Get the text section. */
|
|
|
|
text = find_shdr (lib->ehdr, ".text");
|
|
|
|
if (text == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (translate_offset (GET (text, sh_offset), lib->segments, text_addr)
|
|
|
|
!= 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-07-17 11:44:26 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the section-header table. */
|
|
|
|
|
|
|
|
Elf_External_Shdr *
|
|
|
|
find_shdrtab (Elf_External_Ehdr *ehdr)
|
|
|
|
{
|
|
|
|
return (Elf_External_Shdr *) (((uint8_t *) ehdr) + GET (ehdr, e_shoff));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the string table of the section headers. */
|
|
|
|
|
|
|
|
const char *
|
|
|
|
find_shstrtab (Elf_External_Ehdr *ehdr, uint64_t *size)
|
|
|
|
{
|
|
|
|
const Elf_External_Shdr *shdr;
|
|
|
|
const Elf_External_Shdr *shstr;
|
|
|
|
|
|
|
|
if (GET (ehdr, e_shnum) <= GET (ehdr, e_shstrndx))
|
|
|
|
{
|
|
|
|
printf ("The index of the string table is corrupt.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
shdr = find_shdrtab (ehdr);
|
|
|
|
|
|
|
|
shstr = &shdr[GET (ehdr, e_shstrndx)];
|
|
|
|
*size = GET (shstr, sh_size);
|
|
|
|
return ((const char *) ehdr) + GET (shstr, sh_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the string table named SECTION. */
|
|
|
|
|
|
|
|
const char *
|
|
|
|
find_strtab (Elf_External_Ehdr *ehdr,
|
|
|
|
const char *section, uint64_t *strtab_size)
|
|
|
|
{
|
|
|
|
uint64_t shstrtab_size = 0;
|
|
|
|
const char *shstrtab;
|
|
|
|
uint64_t i;
|
|
|
|
const Elf_External_Shdr *shdr = find_shdrtab (ehdr);
|
|
|
|
|
|
|
|
/* Get the string table of the section headers. */
|
|
|
|
shstrtab = find_shstrtab (ehdr, &shstrtab_size);
|
|
|
|
if (shstrtab == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < GET (ehdr, e_shnum); i++)
|
|
|
|
{
|
|
|
|
uint64_t name = GET (shdr + i, sh_name);
|
|
|
|
if (GET (shdr + i, sh_type) == SHT_STRTAB && name <= shstrtab_size
|
|
|
|
&& strcmp ((const char *) &shstrtab[name], section) == 0)
|
|
|
|
{
|
|
|
|
*strtab_size = GET (shdr + i, sh_size);
|
|
|
|
return ((const char *) ehdr) + GET (shdr + i, sh_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the section header named SECTION. */
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
static Elf_External_Shdr *
|
2013-07-17 11:44:26 +02:00
|
|
|
find_shdr (Elf_External_Ehdr *ehdr, const char *section)
|
|
|
|
{
|
|
|
|
uint64_t shstrtab_size = 0;
|
|
|
|
const char *shstrtab;
|
|
|
|
uint64_t i;
|
|
|
|
|
|
|
|
/* Get the string table of the section headers. */
|
|
|
|
shstrtab = find_shstrtab (ehdr, &shstrtab_size);
|
|
|
|
if (shstrtab == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Elf_External_Shdr *shdr = find_shdrtab (ehdr);
|
|
|
|
for (i = 0; i < GET (ehdr, e_shnum); i++)
|
|
|
|
{
|
|
|
|
uint64_t name = GET (shdr + i, sh_name);
|
|
|
|
if (name <= shstrtab_size)
|
|
|
|
{
|
|
|
|
if (strcmp ((const char *) &shstrtab[name], section) == 0)
|
|
|
|
return &shdr[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the symbol table. */
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
static Elf_External_Sym *
|
2013-07-17 11:44:26 +02:00
|
|
|
find_symtab (Elf_External_Ehdr *ehdr, uint64_t *symtab_size)
|
|
|
|
{
|
|
|
|
uint64_t i;
|
|
|
|
const Elf_External_Shdr *shdr = find_shdrtab (ehdr);
|
|
|
|
|
|
|
|
for (i = 0; i < GET (ehdr, e_shnum); i++)
|
|
|
|
{
|
|
|
|
if (GET (shdr + i, sh_type) == SHT_SYMTAB)
|
|
|
|
{
|
|
|
|
*symtab_size = GET (shdr + i, sh_size) / sizeof (Elf_External_Sym);
|
|
|
|
return (Elf_External_Sym *) (((const char *) ehdr) +
|
|
|
|
GET (shdr + i, sh_offset));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Translate a file offset to an address in a loaded segment. */
|
|
|
|
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
static int
|
2013-07-17 11:44:26 +02:00
|
|
|
translate_offset (uint64_t file_offset, struct segment *seg, void **addr)
|
|
|
|
{
|
|
|
|
while (seg)
|
|
|
|
{
|
|
|
|
uint64_t p_from, p_to;
|
|
|
|
|
|
|
|
Elf_External_Phdr *phdr = seg->phdr;
|
|
|
|
|
|
|
|
if (phdr == NULL)
|
|
|
|
{
|
|
|
|
seg = seg->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_from = GET (phdr, p_offset);
|
|
|
|
p_to = p_from + GET (phdr, p_filesz);
|
|
|
|
|
|
|
|
if (p_from <= file_offset && file_offset < p_to)
|
|
|
|
{
|
|
|
|
*addr = (void *) (seg->mapped_addr + (file_offset - p_from));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
seg = seg->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lookup the address of FUNC. */
|
|
|
|
|
|
|
|
int
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
lookup_function (struct library *lib, const char *func, void **addr)
|
2013-07-17 11:44:26 +02:00
|
|
|
{
|
|
|
|
const char *strtab;
|
|
|
|
uint64_t strtab_size = 0;
|
|
|
|
Elf_External_Sym *symtab;
|
|
|
|
uint64_t symtab_size = 0;
|
|
|
|
uint64_t i;
|
gdb.base/sym-file.exp, hide guts of the custom loader.
This test uses a simple custom elf loader, implemented in
gdb.base/sym-file-loader.h|c. This loader doesn't have a dlclose-like
function today, but I'll need one. But, I found that the guts of the
loader are exposed too much to the client, making the interface more
complicated than necessary. It's simpler if the loader just exports a
few dlopen/dlsym -style functions. That's what this patch does.
Tested on x86_86 Fedora 17, native and gdbserver.
gdb/testsuite/
2014-04-15 Pedro Alves <palves@redhat.com>
* gdb.base/sym-file-loader.h: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> to
sym-file-loader.c.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
to sym-file-loader.c.
(struct library): Forward declare.
(load_shlib, lookup_function): Change prototypes.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Remove declarations.
(get_text_addr): New declaration.
* gdb.base/sym-file-loader.c: Move inclusion of <inttypes.h>,
<ansidecl.h>, <elf/common.h> and <elf/external.h> here from
sym-file-loader.h.
(Elf_External_Phdr, Elf_External_Ehdr, Elf_External_Shdr)
(Elf_External_Sym, Elf_Addr, GET, GETADDR, struct segment): Move
here from sym-file-loader.h.
(struct library): New structure.
(load_shlib, lookup_function): Change prototypes and adjust to
work with a struct library.
(find_shstrtab, find_strtab, find_shdr, find_symtab)
(translate_offset): Make static.
(get_text_addr): New function.
* gdb.base/sym-file-main.c (main): Adjust to new loader interface.
2014-04-15 15:02:34 +02:00
|
|
|
Elf_External_Ehdr *ehdr = lib->ehdr;
|
|
|
|
struct segment *seg = lib->segments;
|
2013-07-17 11:44:26 +02:00
|
|
|
|
|
|
|
/* Get the string table for the symbols. */
|
|
|
|
strtab = find_strtab (ehdr, ".strtab", &strtab_size);
|
|
|
|
if (strtab == NULL)
|
|
|
|
{
|
|
|
|
printf (".strtab not found.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the symbol table. */
|
|
|
|
symtab = find_symtab (ehdr, &symtab_size);
|
|
|
|
if (symtab == NULL)
|
|
|
|
{
|
|
|
|
printf ("symbol table not found.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < symtab_size; i++)
|
|
|
|
{
|
|
|
|
Elf_External_Sym *sym = &symtab[i];
|
|
|
|
|
|
|
|
if (elf_st_type (GET (sym, st_info)) != STT_FUNC)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (GET (sym, st_name) < strtab_size)
|
|
|
|
{
|
|
|
|
const char *name = &strtab[GET (sym, st_name)];
|
|
|
|
if (strcmp (name, func) == 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
uint64_t offset = GET (sym, st_value);
|
|
|
|
return translate_offset (offset, seg, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|