Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2011-01-28 00:50:10 +0000
committereutarass2011-01-28 00:50:10 +0000
commitd15f56d8dbc8dca49b29be38ba11df89435060da (patch)
tree7c8488137b23b53be8e9b7afcfd738bd0802464b
parent6e852da01959d36d39d56512e5e238d73d7a670c (diff)
downloadorg.eclipse.tcf.agent-d15f56d8dbc8dca49b29be38ba11df89435060da.tar.gz
org.eclipse.tcf.agent-d15f56d8dbc8dca49b29be38ba11df89435060da.tar.xz
org.eclipse.tcf.agent-d15f56d8dbc8dca49b29be38ba11df89435060da.zip
TCF Agent: DWARF reader: extended support for relocatable ELF files
-rw-r--r--machine/i386/elf-mdep.h37
-rw-r--r--services/dwarfio.h6
-rw-r--r--services/dwarfreloc.c94
-rw-r--r--services/runctrl.c2
-rw-r--r--services/symbols_proxy.c4
-rw-r--r--services/tcf_elf.c13
-rw-r--r--services/tcf_elf.h18
7 files changed, 128 insertions, 46 deletions
diff --git a/machine/i386/elf-mdep.h b/machine/i386/elf-mdep.h
index 23e2ce77..6086ba6b 100644
--- a/machine/i386/elf-mdep.h
+++ b/machine/i386/elf-mdep.h
@@ -21,37 +21,6 @@
#define R_386_PC32 2
static void elf_relocate(void) {
- U4_T value = 0;
- if (sym_index != STN_UNDEF) {
- Elf32_Sym bf = ((Elf32_Sym *)symbols->data)[sym_index];
- if (symbols->file->byte_swap) {
- SWAP(bf.st_name);
- SWAP(bf.st_value);
- SWAP(bf.st_size);
- SWAP(bf.st_info);
- SWAP(bf.st_other);
- SWAP(bf.st_shndx);
- }
- if (symbols->file->type != ET_EXEC) {
- switch (bf.st_shndx) {
- case SHN_ABS:
- value = bf.st_value;
- break;
- case SHN_COMMON:
- case SHN_UNDEF:
- str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- break;
- default:
- if (bf.st_shndx >= symbols->file->section_cnt) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- value = (U4_T)(symbols->file->sections + bf.st_shndx)->addr + bf.st_value;
- *destination = symbols->file->sections + bf.st_shndx;
- break;
- }
- }
- else {
- value = bf.st_value;
- }
- }
if (relocs->type == SHT_REL) {
U4_T x = *(U4_T *)((char *)section->data + reloc_offset);
if (section->file->type != ET_REL) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
@@ -61,16 +30,16 @@ static void elf_relocate(void) {
}
switch (reloc_type) {
case R_386_NONE:
- *destination = NULL;
+ *destination_section = NULL;
break;
case R_386_32:
if (data_size < 4) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- *(U4_T *)data_buf = value + reloc_addend;
+ *(U4_T *)data_buf = (U4_T)(sym_value + reloc_addend);
if (section->file->byte_swap) SWAP(*(U4_T *)data_buf);
break;
case R_386_PC32:
if (data_size < 4) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- *(U4_T *)data_buf = (U4_T)(section->addr + reloc_offset) + value + reloc_addend;
+ *(U4_T *)data_buf = (U4_T)(section->addr + reloc_offset + sym_value + reloc_addend);
if (section->file->byte_swap) SWAP(*(U4_T *)data_buf);
break;
default:
diff --git a/services/dwarfio.h b/services/dwarfio.h
index 6ad062f8..5a1c7a50 100644
--- a/services/dwarfio.h
+++ b/services/dwarfio.h
@@ -65,6 +65,12 @@ extern U8_T dio_ReadU8LEB128(void);
extern I8_T dio_ReadS8LEB128(void);
extern U8_T dio_ReadUX(int Size);
+
+/*
+ * Read link-time address value.
+ * Relocation tables are used if necessary to compute the address value.
+ * For a file that can be relotated at run-time, 's' is assigned a section that the address points to.
+ */
extern U8_T dio_ReadAddressX(ELF_Section ** s, int Size);
extern U8_T dio_ReadAddress(ELF_Section ** s);
diff --git a/services/dwarfreloc.c b/services/dwarfreloc.c
index 23089c09..c8d33dbf 100644
--- a/services/dwarfreloc.c
+++ b/services/dwarfreloc.c
@@ -29,12 +29,13 @@
static ELF_Section * section = NULL;
static ELF_Section * relocs = NULL;
static ELF_Section * symbols = NULL;
-static ELF_Section ** destination = NULL;
+static ELF_Section ** destination_section = NULL;
static U8_T reloc_offset = 0;
static U4_T reloc_type = 0;
-static U4_T reloc_addend = 0;
+static U8_T reloc_addend = 0;
static U4_T sym_index = 0;
+static U8_T sym_value = 0;
static void * data_buf = NULL;
static size_t data_size = 0;
@@ -77,10 +78,95 @@ static void relocate(void * r) {
reloc_type = ELF32_R_TYPE(bf.r_info);
reloc_addend = bf.r_addend;
}
+ if (sym_index != STN_UNDEF) {
+ Elf32_Sym bf = ((Elf32_Sym *)symbols->data)[sym_index];
+ if (symbols->file->byte_swap) {
+ SWAP(bf.st_name);
+ SWAP(bf.st_value);
+ SWAP(bf.st_size);
+ SWAP(bf.st_info);
+ SWAP(bf.st_other);
+ SWAP(bf.st_shndx);
+ }
+ if (symbols->file->type != ET_EXEC) {
+ switch (bf.st_shndx) {
+ case SHN_ABS:
+ sym_value = bf.st_value;
+ break;
+ case SHN_COMMON:
+ case SHN_UNDEF:
+ str_exception(ERR_INV_FORMAT, "Invalid relocation record");
+ break;
+ default:
+ if (bf.st_shndx >= symbols->file->section_cnt) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
+ sym_value = (symbols->file->sections + bf.st_shndx)->addr + bf.st_value;
+ *destination_section = symbols->file->sections + bf.st_shndx;
+ break;
+ }
+ }
+ else {
+ sym_value = bf.st_value;
+ }
+ }
}
else {
- str_exception(ERR_INV_FORMAT, "Unsupported ELF relocation type");
+ if (relocs->type == SHT_REL) {
+ Elf64_Rel bf = *(Elf64_Rel *)r;
+ if (relocs->file->byte_swap) {
+ SWAP(bf.r_offset);
+ SWAP(bf.r_info);
+ }
+ sym_index = ELF64_R_SYM(bf.r_info);
+ reloc_type = ELF64_R_TYPE(bf.r_info);
+ reloc_addend = 0;
+ }
+ else {
+ Elf64_Rela bf = *(Elf64_Rela *)r;
+ if (relocs->file->byte_swap) {
+ SWAP(bf.r_offset);
+ SWAP(bf.r_info);
+ SWAP(bf.r_addend);
+ }
+ sym_index = ELF64_R_SYM(bf.r_info);
+ reloc_type = ELF64_R_TYPE(bf.r_info);
+ reloc_addend = bf.r_addend;
+ }
+ if (sym_index != STN_UNDEF) {
+ Elf64_Sym bf = ((Elf64_Sym *)symbols->data)[sym_index];
+ if (symbols->file->byte_swap) {
+ SWAP(bf.st_name);
+ SWAP(bf.st_value);
+ SWAP(bf.st_size);
+ SWAP(bf.st_info);
+ SWAP(bf.st_other);
+ SWAP(bf.st_shndx);
+ }
+ if (symbols->file->type != ET_EXEC) {
+ switch (bf.st_shndx) {
+ case SHN_ABS:
+ sym_value = bf.st_value;
+ break;
+ case SHN_COMMON:
+ case SHN_UNDEF:
+ str_exception(ERR_INV_FORMAT, "Invalid relocation record");
+ break;
+ default:
+ if (bf.st_shndx >= symbols->file->section_cnt) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
+ sym_value = (symbols->file->sections + bf.st_shndx)->addr + bf.st_value;
+ *destination_section = symbols->file->sections + bf.st_shndx;
+ break;
+ }
+ }
+ else {
+ sym_value = bf.st_value;
+ }
+ }
}
+
+ /* For executable file we don't need to apply the relocation,
+ * all we need is destination_section */
+ if (section->file->type != ET_REL) return;
+
func = elf_relocate_funcs;
while (func->machine != section->file->machine) {
if (func->func == NULL) str_exception(ERR_INV_FORMAT, "Unsupported ELF machine code");
@@ -98,7 +184,7 @@ void drl_relocate(ELF_Section * s, U8_T offset, void * buf, size_t size, ELF_Sec
if (!s->relocate) return;
section = s;
- destination = dst;
+ destination_section = dst;
reloc_offset = offset;
data_buf = buf;
data_size = size;
diff --git a/services/runctrl.c b/services/runctrl.c
index 814451fc..e3735ada 100644
--- a/services/runctrl.c
+++ b/services/runctrl.c
@@ -1039,7 +1039,7 @@ static int update_step_machine_state(Context * ctx) {
if (n < 0) return -1;
if (ext->step_cnt == 0) {
if (n == 0) {
- set_errno(ERR_INV_COMMAND, "No parent stack frame");
+ set_errno(ERR_OTHER, "Cannot step out: no parent stack frame");
return -1;
}
if (get_frame_info(ctx, n - 1, &info) < 0) return -1;
diff --git a/services/symbols_proxy.c b/services/symbols_proxy.c
index 9e3331e2..98f9e967 100644
--- a/services/symbols_proxy.c
+++ b/services/symbols_proxy.c
@@ -136,7 +136,7 @@ typedef struct StackFrameCache {
ReplyHandlerInfo * pending;
ErrorReport * error;
Context * ctx;
- ContextAddress ip;
+ uint64_t ip;
uint64_t address;
uint64_t size;
@@ -1022,7 +1022,7 @@ static void validate_frame(Channel * c, void * args, int error) {
size = json_read_uint64(&c->inp);
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
if (error || size == 0) {
- f->address = f->ip & ~(ContextAddress)3;
+ f->address = f->ip & ~(uint64_t)3;
f->size = 4;
}
else {
diff --git a/services/tcf_elf.c b/services/tcf_elf.c
index d4c5111f..70013b8c 100644
--- a/services/tcf_elf.c
+++ b/services/tcf_elf.c
@@ -916,9 +916,16 @@ ContextAddress elf_map_to_run_time_address(Context * ctx, ELF_File * file, ELF_S
if (get_map(ctx, 0, ~(ContextAddress)0, &elf_map) < 0) return 0;
for (i = 0; i < elf_map.region_cnt; i++) {
MemoryRegion * r = elf_map.regions + i;
- ino_t ino = r->ino;
- if (ino == 0 && (ino = elf_ino(r->file_name)) == 0) continue;
- if (file->dev != r->dev || file->ino != ino) {
+ int same_file = 0;
+ if (r->dev == 0) {
+ same_file = strcmp(file->name, r->file_name) == 0;
+ }
+ else {
+ ino_t ino = r->ino;
+ if (ino == 0) ino = elf_ino(r->file_name);
+ same_file = file->ino == ino && file->dev == r->dev;
+ }
+ if (!same_file) {
/* Check if the memory map entry has a separate debug info file */
int error = 0;
ELF_File * exec = NULL;
diff --git a/services/tcf_elf.h b/services/tcf_elf.h
index 7aef1251..521b95de 100644
--- a/services/tcf_elf.h
+++ b/services/tcf_elf.h
@@ -232,8 +232,8 @@ typedef struct {
Elf32_Sword r_addend;
} Elf32_Rela;
-#define ELF32_R_SYM(i) ((i)>>8)
-#define ELF32_R_TYPE(i) ((unsigned char)(i))
+#define ELF32_R_SYM(i) ((i) >> 8)
+#define ELF32_R_TYPE(i) ((uint8_t)(i))
typedef struct {
Elf32_Sword d_tag;
@@ -301,6 +301,20 @@ typedef struct {
#define ELF64_ST_TYPE(info) ((info) & 0xf)
typedef struct {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+} Elf64_Rel;
+
+typedef struct {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+ Elf64_Sxword r_addend;
+} Elf64_Rela;
+
+#define ELF64_R_SYM(i) ((uint32_t)((i) >> 32))
+#define ELF64_R_TYPE(i) ((uint32_t)(i))
+
+typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;

Back to the top