/* dyngen-elf.c -- Elf parser for dyngen
|
/* dyngen-elf.c -- Elf parser for dyngen
|
Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
|
Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdint.h>
|
#include <stdint.h>
|
#include <assert.h>
|
#include <assert.h>
|
|
|
#include <elf.h>
|
#include <elf.h>
|
|
|
#include "dyngen.h"
|
#include "dyngen.h"
|
|
|
struct elf_obj {
|
struct elf_obj {
|
Elf32_Ehdr e_hdr;
|
Elf32_Ehdr e_hdr;
|
Elf32_Shdr *e_shdrs;
|
Elf32_Shdr *e_shdrs;
|
void **e_sections;
|
void **e_sections;
|
Elf32_Sym *e_syms; /* The symbol table in the elf file */
|
Elf32_Sym *e_syms; /* The symbol table in the elf file */
|
unsigned int e_sym_num; /* The number of symbols */
|
unsigned int e_sym_num; /* The number of symbols */
|
unsigned int e_sym_str_tab; /* The string-table associated with symbols */
|
unsigned int e_sym_str_tab; /* The string-table associated with symbols */
|
Elf32_Rel *e_rels;
|
Elf32_Rel *e_rels;
|
unsigned int e_rel_num; /* The number of relocations (in e_rel) */
|
unsigned int e_rel_num; /* The number of relocations (in e_rel) */
|
unsigned int e_rel_sym;
|
unsigned int e_rel_sym;
|
unsigned int e_rel_sec; /* The section to modify */
|
unsigned int e_rel_sec; /* The section to modify */
|
Elf32_Rela *e_relas;
|
Elf32_Rela *e_relas;
|
unsigned int e_rela_num; /* The number of relocations (in e_rela) */
|
unsigned int e_rela_num; /* The number of relocations (in e_rela) */
|
unsigned int e_rela_sym;
|
unsigned int e_rela_sym;
|
unsigned int e_rela_sec; /* The section to modify */
|
unsigned int e_rela_sec; /* The section to modify */
|
};
|
};
|
|
|
void *elf_open_obj(const char *file)
|
void *elf_open_obj(const char *file)
|
{
|
{
|
struct elf_obj *obj;
|
struct elf_obj *obj;
|
FILE *f;
|
FILE *f;
|
int i;
|
int i;
|
|
|
if(!(obj = malloc(sizeof(struct elf_obj)))) {
|
if(!(obj = malloc(sizeof(struct elf_obj)))) {
|
fprintf(stderr, "OOM\n");
|
fprintf(stderr, "OOM\n");
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
if(!(f = fopen(file, "r"))) {
|
if(!(f = fopen(file, "r"))) {
|
free(obj);
|
free(obj);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f);
|
fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f);
|
|
|
/* Do some sanity checks */
|
/* Do some sanity checks */
|
if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) ||
|
if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) ||
|
(obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) ||
|
(obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) ||
|
(obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) ||
|
(obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) ||
|
(obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) {
|
(obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) {
|
fprintf(stderr, "%s is not an elf file!\n", file);
|
fprintf(stderr, "%s is not an elf file!\n", file);
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) {
|
if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) {
|
fprintf(stderr, "Invalid class in ELF header\n");
|
fprintf(stderr, "Invalid class in ELF header\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) {
|
if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) {
|
fprintf(stderr, "Invalid data format in ELF header\n");
|
fprintf(stderr, "Invalid data format in ELF header\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
/* FIXME: Swap data as necessary */
|
/* FIXME: Swap data as necessary */
|
|
|
if((obj->e_hdr.e_ident[EI_VERSION] != 1) ||
|
if((obj->e_hdr.e_ident[EI_VERSION] != 1) ||
|
(obj->e_hdr.e_version != 1)) {
|
(obj->e_hdr.e_version != 1)) {
|
fprintf(stderr, "Unexpected elf version found: %i (%li)\n",
|
fprintf(stderr, "Unexpected elf version found: %i (%li)\n",
|
obj->e_hdr.e_ident[EI_VERSION], (long int)obj->e_hdr.e_version);
|
obj->e_hdr.e_ident[EI_VERSION], (long int)obj->e_hdr.e_version);
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_type != ET_REL) {
|
if(obj->e_hdr.e_type != ET_REL) {
|
fprintf(stderr, "Appears that we did not receive a object file\n");
|
fprintf(stderr, "Appears that we did not receive a object file\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_phoff) {
|
if(obj->e_hdr.e_phoff) {
|
fprintf(stderr, "What am I supposed to do with a program header??\n");
|
fprintf(stderr, "What am I supposed to do with a program header??\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) {
|
if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) {
|
fprintf(stderr, "Unknown size of elf header\n");
|
fprintf(stderr, "Unknown size of elf header\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) {
|
if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) {
|
fprintf(stderr, "The elf file contains no sections!\n");
|
fprintf(stderr, "The elf file contains no sections!\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) {
|
if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) {
|
fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize);
|
fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize);
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
/* Load the section headers */
|
/* Load the section headers */
|
if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){
|
if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){
|
fprintf(stderr, "OOM\n");
|
fprintf(stderr, "OOM\n");
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
fseek(f, obj->e_hdr.e_shoff, SEEK_SET);
|
fseek(f, obj->e_hdr.e_shoff, SEEK_SET);
|
fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f);
|
fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f);
|
|
|
/* FIXME: swap data */
|
/* FIXME: swap data */
|
|
|
/* Load the sections */
|
/* Load the sections */
|
if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) {
|
if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) {
|
fprintf(stderr, "OOM\n");
|
fprintf(stderr, "OOM\n");
|
free(obj->e_shdrs);
|
free(obj->e_shdrs);
|
goto error_load;
|
goto error_load;
|
}
|
}
|
|
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
if(obj->e_shdrs[i].sh_type == SHT_NOBITS)
|
if(obj->e_shdrs[i].sh_type == SHT_NOBITS)
|
continue;
|
continue;
|
if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) {
|
if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) {
|
fprintf(stderr, "OOM\n");
|
fprintf(stderr, "OOM\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET);
|
fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET);
|
fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f);
|
fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f);
|
}
|
}
|
|
|
obj->e_rels = NULL;
|
obj->e_rels = NULL;
|
obj->e_syms = NULL;
|
obj->e_syms = NULL;
|
obj->e_relas = NULL;
|
obj->e_relas = NULL;
|
|
|
/* Find the symbol table and relocation table(s) */
|
/* Find the symbol table and relocation table(s) */
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
switch(obj->e_shdrs[i].sh_type) {
|
switch(obj->e_shdrs[i].sh_type) {
|
case SHT_SYMTAB:
|
case SHT_SYMTAB:
|
if(obj->e_syms) {
|
if(obj->e_syms) {
|
fprintf(stderr, "ELF file has more than one symbol table\n");
|
fprintf(stderr, "ELF file has more than one symbol table\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) {
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) {
|
fprintf(stderr, "ELF symbol table entry size is unknown\n");
|
fprintf(stderr, "ELF symbol table entry size is unknown\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n");
|
fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
obj->e_syms = obj->e_sections[i];
|
obj->e_syms = obj->e_sections[i];
|
obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
obj->e_sym_str_tab = obj->e_shdrs[i].sh_link;
|
obj->e_sym_str_tab = obj->e_shdrs[i].sh_link;
|
break;
|
break;
|
case SHT_REL:
|
case SHT_REL:
|
if(obj->e_rels) {
|
if(obj->e_rels) {
|
fprintf(stderr, "ELF file has more than one relocation table\n");
|
fprintf(stderr, "ELF file has more than one relocation table\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) {
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) {
|
fprintf(stderr, "ELF relocation table entry size is unknown\n");
|
fprintf(stderr, "ELF relocation table entry size is unknown\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n");
|
fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
obj->e_rels = obj->e_sections[i];
|
obj->e_rels = obj->e_sections[i];
|
obj->e_rel_sec = obj->e_shdrs[i].sh_info;
|
obj->e_rel_sec = obj->e_shdrs[i].sh_info;
|
obj->e_rel_sym = obj->e_shdrs[i].sh_link;
|
obj->e_rel_sym = obj->e_shdrs[i].sh_link;
|
obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
break;
|
break;
|
case SHT_RELA:
|
case SHT_RELA:
|
if(obj->e_relas) {
|
if(obj->e_relas) {
|
fprintf(stderr, "ELF file has more than one a-relocation table\n");
|
fprintf(stderr, "ELF file has more than one a-relocation table\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) {
|
if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) {
|
fprintf(stderr, "ELF a-relocation table entry size is unknown\n");
|
fprintf(stderr, "ELF a-relocation table entry size is unknown\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
|
fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n");
|
fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n");
|
goto post_sec_error_load;
|
goto post_sec_error_load;
|
}
|
}
|
obj->e_relas = obj->e_sections[i];
|
obj->e_relas = obj->e_sections[i];
|
obj->e_rela_sec = obj->e_shdrs[i].sh_info;
|
obj->e_rela_sec = obj->e_shdrs[i].sh_info;
|
obj->e_rela_sym = obj->e_shdrs[i].sh_link;
|
obj->e_rela_sym = obj->e_shdrs[i].sh_link;
|
obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
fclose(f);
|
fclose(f);
|
return obj;
|
return obj;
|
|
|
post_sec_error_load:
|
post_sec_error_load:
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
if(obj->e_sections[i])
|
if(obj->e_sections[i])
|
free(obj->e_sections[i]);
|
free(obj->e_sections[i]);
|
}
|
}
|
free(obj->e_sections);
|
free(obj->e_sections);
|
free(obj->e_shdrs);
|
free(obj->e_shdrs);
|
error_load:
|
error_load:
|
free(obj);
|
free(obj);
|
fclose(f);
|
fclose(f);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
void elf_close_obj(void *e_obj)
|
void elf_close_obj(void *e_obj)
|
{
|
{
|
struct elf_obj *obj = e_obj;
|
struct elf_obj *obj = e_obj;
|
int i;
|
int i;
|
|
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
for(i = 0; i < obj->e_hdr.e_shnum; i++) {
|
if(obj->e_sections[i])
|
if(obj->e_sections[i])
|
free(obj->e_sections[i]);
|
free(obj->e_sections[i]);
|
}
|
}
|
free(obj->e_sections);
|
free(obj->e_sections);
|
free(obj->e_shdrs);
|
free(obj->e_shdrs);
|
free(obj);
|
free(obj);
|
}
|
}
|
|
|
static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func)
|
static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func)
|
{
|
{
|
int i, j;
|
int i, j;
|
Elf32_Sym *cur;
|
Elf32_Sym *cur;
|
|
|
for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) {
|
for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) {
|
if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL)
|
if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL)
|
continue;
|
continue;
|
if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC)
|
if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC)
|
continue;
|
continue;
|
if(j == func)
|
if(j == func)
|
return cur;
|
return cur;
|
j++;
|
j++;
|
}
|
}
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
char *elf_get_func_name(void *e_obj, unsigned int func)
|
char *elf_get_func_name(void *e_obj, unsigned int func)
|
{
|
{
|
struct elf_obj *obj = e_obj;
|
struct elf_obj *obj = e_obj;
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
|
|
if(func_sym)
|
if(func_sym)
|
return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name;
|
return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name;
|
|
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
unsigned int elf_get_func_len(void *e_obj, unsigned int func)
|
unsigned int elf_get_func_len(void *e_obj, unsigned int func)
|
{
|
{
|
struct elf_obj *obj = e_obj;
|
struct elf_obj *obj = e_obj;
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
|
|
if(func_sym)
|
if(func_sym)
|
return func_sym->st_size;
|
return func_sym->st_size;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void *elf_get_func_start(void *e_obj, unsigned int func)
|
void *elf_get_func_start(void *e_obj, unsigned int func)
|
{
|
{
|
struct elf_obj *obj = e_obj;
|
struct elf_obj *obj = e_obj;
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
|
|
if(!func_sym)
|
if(!func_sym)
|
return NULL;
|
return NULL;
|
|
|
if(func_sym->st_shndx == SHN_COMMON) {
|
if(func_sym->st_shndx == SHN_COMMON) {
|
fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n");
|
fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n");
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
return obj->e_sections[func_sym->st_shndx] + func_sym->st_value;
|
return obj->e_sections[func_sym->st_shndx] + func_sym->st_value;
|
}
|
}
|
|
|
static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym)
|
static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym)
|
{
|
{
|
char *name;
|
char *name;
|
|
|
name = obj->e_sections[obj->e_sym_str_tab];
|
name = obj->e_sections[obj->e_sym_str_tab];
|
name += obj->e_syms[sym].st_name;
|
name += obj->e_syms[sym].st_name;
|
|
|
return name;
|
return name;
|
}
|
}
|
|
|
int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn,
|
int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn,
|
struct reloc *reloc)
|
struct reloc *reloc)
|
{
|
{
|
struct elf_obj *obj = e_obj;
|
struct elf_obj *obj = e_obj;
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
Elf32_Sym *func_sym = elf_find_func(obj, func);
|
Elf32_Rel *cur;
|
Elf32_Rel *cur;
|
Elf32_Rela *cura;
|
Elf32_Rela *cura;
|
int i, j;
|
int i, j;
|
|
|
/*
|
/*
|
if(obj->e_rel_sec != func_sym->st_shndx) {
|
if(obj->e_rel_sec != func_sym->st_shndx) {
|
fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n");
|
fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n");
|
return 0;
|
return 0;
|
}
|
}
|
*/
|
*/
|
|
|
for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) {
|
for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) {
|
if((cur->r_offset - func_sym->st_value) > func_sym->st_size)
|
if((cur->r_offset - func_sym->st_value) > func_sym->st_size)
|
continue;
|
continue;
|
if(relocn == j) {
|
if(relocn == j) {
|
reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
|
reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
|
reloc->func_offset = cur->r_offset - func_sym->st_value;
|
reloc->func_offset = cur->r_offset - func_sym->st_value;
|
reloc->type = ELF32_R_TYPE(cur->r_info);
|
reloc->type = ELF32_R_TYPE(cur->r_info);
|
/* FIXME: Byte-swap */
|
/* FIXME: Byte-swap */
|
reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset);
|
reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset);
|
return 1;
|
return 1;
|
}
|
}
|
j++;
|
j++;
|
}
|
}
|
|
|
if(!obj->e_relas)
|
if(!obj->e_relas)
|
return 0;
|
return 0;
|
|
|
for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) {
|
for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) {
|
if((cura->r_offset - func_sym->st_value) > func_sym->st_size)
|
if((cura->r_offset - func_sym->st_value) > func_sym->st_size)
|
continue;
|
continue;
|
if(relocn == j) {
|
if(relocn == j) {
|
reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
|
reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
|
reloc->func_offset = cura->r_offset - func_sym->st_value;
|
reloc->func_offset = cura->r_offset - func_sym->st_value;
|
reloc->type = ELF32_R_TYPE(cur->r_info);
|
reloc->type = ELF32_R_TYPE(cur->r_info);
|
reloc->addend = cura->r_addend;
|
reloc->addend = cura->r_addend;
|
return 1;
|
return 1;
|
}
|
}
|
j++;
|
j++;
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
const struct bff bffs = {
|
const struct bff bffs = {
|
elf_open_obj,
|
elf_open_obj,
|
elf_close_obj,
|
elf_close_obj,
|
elf_get_func_name,
|
elf_get_func_name,
|
elf_get_func_start,
|
elf_get_func_start,
|
elf_get_func_len,
|
elf_get_func_len,
|
elf_get_func_reloc };
|
elf_get_func_reloc };
|
|
|