* For portability reasons change cle_addr from pointer type.

* Use loader/sym.h.

* cle_upd_reloc() makes updates in memory copy.
This commit is contained in:
bg- 2007-04-25 15:41:02 +00:00
parent ffb90bfe40
commit da798a535b

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)$Id: cle.c,v 1.3 2007/01/12 13:36:27 bg- Exp $ * @(#)$Id: cle.c,v 1.4 2007/04/25 15:41:02 bg- Exp $
*/ */
/* /*
@ -40,9 +40,9 @@
#include "loader/cle.h" #include "loader/cle.h"
#include "loader/elf32.h" #include "loader/elf32.h"
#include "loader/symtab.h" #include "loader/sym.h"
#define NDEBUG //#define NDEBUG
#include "lib/assert.h" #include "lib/assert.h"
#ifdef NDEBUG #ifdef NDEBUG
@ -51,6 +51,8 @@
#define PRINTF(...) printf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__)
#endif #endif
#define NOLL 0
/* /*
* Parse object file located at offset hdr reading data using function * Parse object file located at offset hdr reading data using function
* pread. Save what is useful in info. * pread. Save what is useful in info.
@ -179,12 +181,18 @@ cle_read_info(struct cle_info *info,
* Writing relocs is machine dependent and this function is MSP430 * Writing relocs is machine dependent and this function is MSP430
* specific! * specific!
*/ */
#ifdef __MSP430__
static inline int static inline int
cle_upd_reloc(cle_addr segmem, struct elf32_rela *rela, cle_addr addr) cle_upd_reloc(void *segmem, struct elf32_rela *rela, cle_addr addr)
{ {
memcpy(segmem + rela->r_offset, &addr, 2); /* Write reloc */ memcpy((char *)segmem + rela->r_offset, &addr, 2); /* Write reloc */
return 0; return 0;
} }
#else
static int
cle_upd_reloc(void *segmem, struct elf32_rela *rela, cle_addr addr);
#endif
/* /*
* Relocate one segment that has been copied to the location pointed * Relocate one segment that has been copied to the location pointed
@ -198,7 +206,7 @@ int
cle_relocate(struct cle_info *info, cle_relocate(struct cle_info *info,
int (*pread)(void *, int, off_t), int (*pread)(void *, int, off_t),
off_t hdr, /* Offset to start of file. */ off_t hdr, /* Offset to start of file. */
cle_addr segmem, /* Where segment is stored in memory. */ void *segmem, /* Where segment is stored in memory. */
cle_off reloff, /* .rela.<segment> start */ cle_off reloff, /* .rela.<segment> start */
cle_word relsize) /* .rela.<segment> size */ cle_word relsize) /* .rela.<segment> size */
{ {
@ -219,34 +227,34 @@ cle_relocate(struct cle_info *info,
assert(ret > 0); assert(ret > 0);
if(s.st_shndx == info->bss_shndx) { if(s.st_shndx == info->bss_shndx) {
addr = info->bss; addr = (cle_addr)info->bss;
} else if(s.st_shndx == info->data_shndx) { } else if(s.st_shndx == info->data_shndx) {
addr = info->data; addr = (cle_addr)info->data;
} else if(s.st_shndx == info->text_shndx) { } else if(s.st_shndx == info->text_shndx) {
addr = info->text; addr = info->text;
} else { } else {
addr = NULL; addr = NOLL;
} }
if(s.st_name == 0) { /* No name, local symbol? */ if(s.st_name == 0) { /* No name, local symbol? */
if(addr == NULL) { if(addr == NOLL) {
return CLE_UNKNOWN_SEGMENT; return CLE_UNKNOWN_SEGMENT;
} }
} else { } else {
ret = pread(info->name, sizeof(info->name), ret = pread(info->name, sizeof(info->name),
hdr + info->strtaboff + s.st_name); hdr + info->strtaboff + s.st_name);
assert(ret > 0); assert(ret > 0);
cle_addr sym = symtab_lookup(info->name); cle_addr sym = (cle_addr)sym_object(info->name);
if(addr == NULL && sym != NULL) { /* Imported symbol. */ if(addr == NOLL && sym != NOLL) { /* Imported symbol. */
addr = sym; addr = sym;
} else if(addr != NULL && sym == NULL) { /* Exported symbol. */ } else if(addr != NOLL && sym == NOLL) { /* Exported symbol. */
addr = addr + s.st_value; addr = addr + s.st_value;
} else if(addr == NULL && sym == NULL) { } else if(addr == NOLL && sym == NOLL) {
PRINTF("cle: undefined reference to %.32s (%d)\n", PRINTF("cle: undefined reference to %.32s (%d)\n",
info->name, s.st_info); info->name, s.st_info);
return CLE_UNDEFINED; /* Or COMMON symbol. */ return CLE_UNDEFINED; /* Or COMMON symbol. */
} else if(addr != NULL && sym != NULL) { } else if(addr != NOLL && sym != NOLL) {
PRINTF("cle: multiple definitions of %.32s (%d)\n", PRINTF("cle: multiple definitions of %.32s (%d)\n",
info->name, s.st_info); info->name, s.st_info);
return CLE_MULTIPLY_DEFINED; return CLE_MULTIPLY_DEFINED;
@ -255,7 +263,10 @@ cle_relocate(struct cle_info *info,
addr += rela.r_addend; addr += rela.r_addend;
cle_upd_reloc(segmem, &rela, addr); ret = cle_upd_reloc(segmem, &rela, addr);
if(ret < 0) {
return CLE_UNKNOWN_SEGMENT;
}
} }
return CLE_OK; return CLE_OK;
} }
@ -290,9 +301,9 @@ cle_lookup(struct cle_info *info,
if(strcmp(info->name, symbol) == 0) { /* Exported symbol found. */ if(strcmp(info->name, symbol) == 0) { /* Exported symbol found. */
if(s.st_shndx == info->bss_shndx) { if(s.st_shndx == info->bss_shndx) {
addr = info->bss; addr = (cle_addr)info->bss;
} else if(s.st_shndx == info->data_shndx) { } else if(s.st_shndx == info->data_shndx) {
addr = info->data; addr = (cle_addr)info->data;
} else if(s.st_shndx == info->text_shndx) { } else if(s.st_shndx == info->text_shndx) {
addr = info->text; addr = info->text;
} else { } else {