diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-22 22:12:19 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-22 22:12:19 +0000 |
commit | f759cd068190d9a8820c1c4d57fbe03b85daa000 (patch) | |
tree | f903dad1ef84a9a7d25046c47e52943068be1218 /nuttx/binfmt | |
parent | ee9f379c2f10c3c471bc421366fd1a0ed3147bb6 (diff) | |
download | px4-nuttx-f759cd068190d9a8820c1c4d57fbe03b85daa000.tar.gz px4-nuttx-f759cd068190d9a8820c1c4d57fbe03b85daa000.tar.bz2 px4-nuttx-f759cd068190d9a8820c1c4d57fbe03b85daa000.zip |
New relocation types
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1925 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/binfmt')
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_bind.c | 301 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_init.c | 9 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_load.c | 152 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_read.c | 8 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_uninit.c | 9 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_unload.c | 4 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_verify.c | 9 |
7 files changed, 353 insertions, 139 deletions
diff --git a/nuttx/binfmt/libnxflat/libnxflat_bind.c b/nuttx/binfmt/libnxflat/libnxflat_bind.c index 887fcfe58..6d96ab6e3 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_bind.c +++ b/nuttx/binfmt/libnxflat/libnxflat_bind.c @@ -40,6 +40,7 @@ #include <nuttx/config.h> #include <sys/types.h> +#include <string.h> #include <nxflat.h> #include <errno.h> #include <assert.h> @@ -66,11 +67,243 @@ ****************************************************************************/ /**************************************************************************** - * Public Functions + * Name: nxflat_bindrel32i + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32I binding: + * + * Meaning: Object file contains a 32-bit offset into I-Space at the the offset. + * Fixup: Add mapped I-Space address to the offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ -/*********************************************************************** - * Name: nxflat_bind +static inline int nxflat_bindrel32i(FAR struct nxflat_loadinfo_s *loadinfo, + uint32 offset) +{ + uint32 *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32I Offset: %08x I-Space: %p\n", + offset, loadinfo->ispace); + + if (offset < loadinfo->dsize) + { + addr = (uint32*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += (uint32)(loadinfo->ispace); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} + +/**************************************************************************** + * Name: nxflat_bindrel32d + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32D binding: + * + * Meaning: Object file contains a 32-bit offset into D-Space at the the offset. + * Fixup: Add allocated D-Space address to the offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_bindrel32d(FAR struct nxflat_loadinfo_s *loadinfo, + uint32 offset) +{ + uint32 *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32D Offset: %08x D-Space: %p\n", + offset, loadinfo->dspace->region); + + if (offset < loadinfo->dsize) + { + addr = (uint32*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += (uint32)(loadinfo->dspace->region); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} + +/**************************************************************************** + * Name: nxflat_bindrel32id + * + * Description: + * Perform the NXFLAT_RELOC_TYPE_REL32ID binding: + * + * Meaning: Object file contains a 32-bit offsetinto I-Space at the the + * offset, but will be referenced as data + * Fixup: Add mapped I-Space address - allocated D-Space address to the + * offset. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_bindrel32id(FAR struct nxflat_loadinfo_s *loadinfo, + uint32 offset) +{ + uint32 *addr; + + bvdbg("NXFLAT_RELOC_TYPE_REL32I Offset: %08x I-Space: %p D-Space: %p\n", + offset, loadinfo->ispace, loadinfo->dspace->region); + + if (offset < loadinfo->dsize) + { + addr = (uint32*)(offset + loadinfo->dspace->region); + bvdbg(" Before: %08x\n", *addr); + *addr += ((uint32)(loadinfo->ispace) - (uint32)(loadinfo->dspace->region)); + bvdbg(" After: %08x\n", *addr); + return OK; + } + else + { + bdbg("Offset: %08 does not lie in D-Space size: %08x\n", + offset, loadinfo->dsize); + return -EINVAL; + } +} + +/**************************************************************************** + * Name: nxflat_gotrelocs + * + * Description: + * Bind all of the GOT relocations in the loaded module described by + * 'loadinfo' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo) +{ + FAR struct nxflat_reloc_s *relocs; + FAR struct nxflat_reloc_s reloc; + FAR struct nxflat_hdr_s *hdr; + uint32 offset; + uint16 nrelocs; + int ret; + int result; + int i; + + /* The NXFLAT header is the first thing at the beginning of the ISpace. */ + + hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace; + + /* From this, we can get the offset to the list of relocation entries */ + + offset = ntohl(hdr->h_relocstart); + nrelocs = ntohs(hdr->h_reloccount); + + /* The value of the relocation list that we get from the header is a + * file offset. We will have to convert this to an offset into the + * DSpace segment to get the pointer to the beginning of the relocation + * list. + */ + + DEBUGASSERT(offset >= loadinfo->isize && offset < (loadinfo->isize + loadinfo->dsize)); + relocs = (FAR struct nxflat_reloc_s*)(offset - loadinfo->isize + loadinfo->dspace->region); + + /* Now, traverse the relocation list of imported symbols and attempt to bind + * each GOT relocation (imported symbols will be handled elsewhere). + */ + + ret = OK; /* Assume success */ + for (i = 0; i < nrelocs; i++) + { + /* Handle the relocation by the relocation type */ + + reloc = *relocs++; + result = OK; + switch (NXFLAT_RELOC_TYPE(reloc.r_info)) + { + + /* NXFLAT_RELOC_TYPE_REL32I Meaning: Object file contains a 32-bit offset + * into I-Space at the the offset. + * Fixup: Add mapped I-Space address to the offset. + */ + + case NXFLAT_RELOC_TYPE_REL32I: + { + result = nxflat_bindrel32i(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; + + /* NXFLAT_RELOC_TYPE_REL32D Meaning: Object file contains a 32-bit offset + * into D-Space at the the offset. + * Fixup: Add allocated D-Space address to the + * offset. + */ + + case NXFLAT_RELOC_TYPE_REL32D: + { + result = nxflat_bindrel32d(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; + + /* NXFLAT_RELOC_TYPE_REL32ID Meaning: Object file contains a 32-bit offset + * into I-Space at the the offset, but will + * be referenced as data + * Fixup: Add mapped I-Space address - allocated + * D-Space address to the offset. + */ + + case NXFLAT_RELOC_TYPE_REL32ID: + { + result = nxflat_bindrel32id(loadinfo, NXFLAT_RELOC_OFFSET(reloc.r_info)); + } + break; + + /* NXFLAT_RELOC_TYPE_ABS32 Meaning: Offset refers to a struct nxflat_import_s + * describing a function pointer to be + * imported. + * Fixup: Provide the absolute function address + * in the struct nxflat_import_s instance. + */ + + case NXFLAT_RELOC_TYPE_ABS32: + { + /* These will be handled together in nxflat_bindimports */ + } + break; + } + + /* Check for failures */ + + if (result < 0 && ret == OK) + { + ret = result; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nxflat_bindimports * * Description: * Bind the imported symbol names in the loaded module described by @@ -80,10 +313,11 @@ * 0 (OK) is returned on success and a negated errno is returned on * failure. * - ***********************************************************************/ + ****************************************************************************/ -int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, - FAR const struct symtab_s *exports, int nexports) +static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, + int nexports) { FAR struct nxflat_import_s *imports; FAR struct nxflat_hdr_s *hdr; @@ -94,9 +328,7 @@ int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, uint16 nimports; int i; - /* Get the ISpace load address of the module. The NXFLAT header is the - * first thing at the beginning of the ISpace. - */ + /* The NXFLAT header is the first thing at the beginning of the ISpace. */ hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace; @@ -125,9 +357,9 @@ int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, offset < loadinfo->isize + loadinfo->dsize); imports = (struct nxflat_import_s*) - (offset - loadinfo->isize + loadinfo->dspace); + (offset - loadinfo->isize + loadinfo->dspace->region); - /* Now, search the list of imported symbols and attempt to bind + /* Now, traverse the list of imported symbols and attempt to bind * each symbol to the value exported by from the exported symbol * table. */ @@ -170,3 +402,50 @@ int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, return OK; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_bind + * + * Description: + * Bind the imported symbol names in the loaded module described by + * 'loadinfo' using the exported symbol values provided by 'symtab'. + * After binding the module, clear the BSS region (which held the relocation + * data) in preparation for execution. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, int nexports) +{ + /* First bind all GOT relocations (omitting absolute symbol relocations) */ + + int ret = nxflat_gotrelocs(loadinfo); + if (ret == OK) + { + /* Then bind the imported symbol, absolute relocations separately. + * There is no particular reason to do these separately over than + * traversing the import list directly is simpler than traversing + * it indirectly through the relocation list. + */ + + ret = nxflat_bindimports(loadinfo, exports, nexports); + if (ret == OK) + { + /* Zero the BSS area, trashing the relocations that lived in space + * in the file. + */ + + memset((void*)(loadinfo->dspace->region + loadinfo->datasize), + 0, loadinfo->bsssize); + } + } + return ret; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_init.c b/nuttx/binfmt/libnxflat/libnxflat_init.c index c14ba1c22..8be811342 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_init.c +++ b/nuttx/binfmt/libnxflat/libnxflat_init.c @@ -68,6 +68,15 @@ /**************************************************************************** * Name: nxflat_init + * + * Description: + * This function is called to configure the library to process an NXFLAT + * program binary. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_init(const char *filename, struct nxflat_hdr_s *header, diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c index c3654f772..54b87992c 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_load.c +++ b/nuttx/binfmt/libnxflat/libnxflat_load.c @@ -42,7 +42,6 @@ #include <sys/mman.h> #include <stdlib.h> -#include <string.h> #include <nxflat.h> #include <debug.h> #include <errno.h> @@ -63,22 +62,21 @@ ****************************************************************************/ #if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BINFMT) -static const char g_textsegment[] = "TEXT"; -static const char g_datasegment[] = "DATA"; -static const char g_bsssegment[] = "BSS"; -static const char g_unksegment[] = "UNKNOWN"; +static const char g_relocrel32i[] = "RELOC_REL32I"; +static const char g_relocrel32d[] = "RELOC_REL32D"; +static const char g_relocrel32id[] = "RELOC_REL32ID"; +static const char g_relocabs32[] = "RELOC_AB32"; -static const char *g_segment[] = +static const char *g_reloctype[] = { - g_textsegment, - g_datasegment, - g_bsssegment, - g_unksegment + g_relocrel32i, + g_relocrel32d, + g_relocrel32id, + g_relocabs32 }; - -# define SEGNAME(rl) g_segment[NXFLAT_RELOC_TYPE(rl)] +# define RELONAME(rl) g_reloctype[NXFLAT_RELOC_TYPE(rl)] #else -# define SEGNAME(rl) "(no name)" +# define RELONAME(rl) "(no name)" #endif /**************************************************************************** @@ -86,108 +84,30 @@ static const char *g_segment[] = ****************************************************************************/ /**************************************************************************** - * Name: nxflat_reloc - ****************************************************************************/ - -static void nxflat_reloc(struct nxflat_loadinfo_s *loadinfo, uint32 rl) -{ - uint32 *ptr; - ubyte *datastart; - - /* We only support relocations in the data sections. Verify that the - * relocation address lies in the data section of the file image. - */ - - if (NXFLAT_RELOC_OFFSET(rl) > loadinfo->datasize) - { - bdbg("ERROR: Relocation at %08x invalid -- " - "does not lie in the data segment, size: %08x\n", - NXFLAT_RELOC_OFFSET(rl), loadinfo->datasize); - bdbg(" Relocation not performed!\n"); - } - else if ((NXFLAT_RELOC_OFFSET(rl) & 0x00000003) != 0) - { - bdbg("ERROR: Relocation at %08x invalid -- " - "Improperly aligned\n", - NXFLAT_RELOC_OFFSET(rl)); - } - else - { - /* Get a reference to the "real" start of data. It is - * offset slightly from the beginning of the allocated - * DSpace to hold information needed by ld.so at run time. - */ - - datastart = loadinfo->dspace->region; - - /* Get a pointer to the value that needs relocation in - * DSpace. - */ - - ptr = (uint32*)(datastart + NXFLAT_RELOC_OFFSET(rl)); - - bvdbg("Relocation of variable at DATASEG+%08x " - "(address %p, currently %08x) into segment %s\n", - NXFLAT_RELOC_OFFSET(rl), ptr, *ptr, SEGNAME(rl)); - - switch (NXFLAT_RELOC_TYPE(rl)) - { - /* TEXT is located at an offset of sizeof(struct nxflat_hdr_s) from - * the allocated/mapped ISpace region. - */ - - case NXFLAT_RELOC_TYPE_TEXT: - *ptr += loadinfo->ispace + sizeof(struct nxflat_hdr_s); - break; - - /* DATA and BSS are always contiguous regions. DATA - * begins at the beginning of the allocated data segment. - * BSS is positioned after DATA, unrelocated references - * to BSS include the data offset. - * - * In other contexts, is it necessary to add the datasize - * to get the BSS offset like: - * - * *ptr += datastart + loadinfo->datasize; - */ - - case NXFLAT_RELOC_TYPE_DATA: - case NXFLAT_RELOC_TYPE_BSS: - *ptr += (uint32)datastart; - break; - - /* This case happens normally if the symbol is a weak - * undefined symbol. We permit these. - */ - - case NXFLAT_RELOC_TYPE_NONE: - bdbg("NULL relocation!\n"); - break; - - default: - bdbg("ERROR: Unknown relocation type: %d\n", NXFLAT_RELOC_TYPE(rl)); - break; - } - - bvdbg("Relocation became %08x\n", *ptr); - } -} - -/**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxflat_load + * + * Description: + * Loads the binary specified by nxflat_init into memory, mapping + * the I-space executable regions, allocating the D-Space region, + * and inializing the data segment (relocation information is + * temporarily loaded into the BSS region. BSS will be cleared + * by nxflat_bind() after the relocation data has been processed). + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) { off_t doffset; /* Offset to .data in the NXFLAT file */ - uint32 *reloctab; /* Address of the relocation table */ uint32 dreadsize; /* Total number of bytes of .data to be read */ int ret = OK; - int i; /* Calculate the extra space we need to allocate. This extra space will be * the size of the BSS section. This extra space will also be used @@ -266,7 +186,7 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) } loadinfo->dspace->crefs = 1; - bvdbg("Allocated DSpace (%d bytes) at %p\n", loadinfo->dsize, loadinfo->dspace); + bvdbg("Allocated DSpace (%d bytes) at %p\n", loadinfo->dsize, loadinfo->dspace->region); /* Now, read the data into allocated DSpace at doffset into the * allocated DSpace memory. @@ -282,30 +202,6 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo) bvdbg("TEXT: %08x Entry point offset: %08x Data offset: %08x\n", loadinfo->ispace, loadinfo->entryoffs, doffset); - /* Resolve the address of the relocation table. In the file, the - * relocations should lie at the same offset as BSS. The current - * value of relocstart is the offset from the beginning of the file. - * The following adjustment will convert it to an address in dspace-> - */ - - reloctab = (uint32*)(loadinfo->relocstart + (uint32)loadinfo->dspace->region - loadinfo->isize); - - bvdbg("Relocation table at %p, reloccount: %d\n", - reloctab, loadinfo->reloccount); - - /* Now run through the relocation entries. */ - - for (i=0; i < loadinfo->reloccount; i++) - { - nxflat_reloc(loadinfo, htonl(reloctab[i])); - } - - /* Zero the BSS area, trashing the relocations that lived in space - * in the file. - */ - - memset((void*)(loadinfo->dspace->region + loadinfo->datasize), - 0, loadinfo->bsssize); return OK; errout: diff --git a/nuttx/binfmt/libnxflat/libnxflat_read.c b/nuttx/binfmt/libnxflat/libnxflat_read.c index ff5200140..cf1ba5b37 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_read.c +++ b/nuttx/binfmt/libnxflat/libnxflat_read.c @@ -67,6 +67,14 @@ /**************************************************************************** * Name: nxflat_read + * + * Description: + * Read 'readsize' bytes from the object file at 'offset' + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer, int readsize, int offset) diff --git a/nuttx/binfmt/libnxflat/libnxflat_uninit.c b/nuttx/binfmt/libnxflat/libnxflat_uninit.c index 47d1a90a2..22d9e3ac5 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_uninit.c +++ b/nuttx/binfmt/libnxflat/libnxflat_uninit.c @@ -66,6 +66,15 @@ /**************************************************************************** * Name: nxflat_uninit + * + * Description: + * Releases any resources committed by nxflat_init(). This essentially + * undoes the actions of nxflat_init. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_uninit(struct nxflat_loadinfo_s *loadinfo) diff --git a/nuttx/binfmt/libnxflat/libnxflat_unload.c b/nuttx/binfmt/libnxflat/libnxflat_unload.c index e095315a2..1f8d1163d 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_unload.c +++ b/nuttx/binfmt/libnxflat/libnxflat_unload.c @@ -69,6 +69,10 @@ * This function unloads the object from memory. This essentially * undoes the actions of nxflat_load. * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_unload(struct nxflat_loadinfo_s *loadinfo) diff --git a/nuttx/binfmt/libnxflat/libnxflat_verify.c b/nuttx/binfmt/libnxflat/libnxflat_verify.c index c153a1128..7e6cc548e 100644 --- a/nuttx/binfmt/libnxflat/libnxflat_verify.c +++ b/nuttx/binfmt/libnxflat/libnxflat_verify.c @@ -63,6 +63,15 @@ /**************************************************************************** * Name: nxflat_verifyheader + * + * Description: + * Given the header from a possible NXFLAT executable, verify that it + * is an NXFLAT executable. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * ****************************************************************************/ int nxflat_verifyheader(const struct nxflat_hdr_s *header) |