gonzui


Format: Advanced Search

t2ex/t2ex_source/t2ex/load/src/ldr_elf.cbare sourcepermlink (0.10 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T2EX Software Package
    4:  *
    5:  *    Copyright 2012 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2012/12/12.
   10:  *    Modified by T-Engine Forum at 2013/03/08.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/04.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: /*
   16:  * This software package is available for use, modification, 
   17:  * and redistribution in accordance with the terms of the attached 
   18:  * T-License 2.x.
   19:  * If you want to redistribute the source code, you need to attach 
   20:  * the T-License 2.x document.
   21:  * There's no obligation to publish the content, and no obligation 
   22:  * to disclose it to the TRON Forum if you have modified the 
   23:  * software package.
   24:  * You can also distribute the modified source code. In this case, 
   25:  * please register the modification to T-Kernel traceability service.
   26:  * People can know the history of modifications by the service, 
   27:  * and can be sure that the version you have inherited some 
   28:  * modification of a particular version or not.
   29:  *
   30:  *    http://trace.tron.org/tk/?lang=en
   31:  *    http://trace.tron.org/tk/?lang=ja
   32:  *
   33:  * As per the provisions of the T-License 2.x, TRON Forum ensures that 
   34:  * the portion of the software that is copyrighted by Ken Sakamura or 
   35:  * the TRON Forum does not infringe the copyrights of a third party.
   36:  * However, it does not make any warranty other than this.
   37:  * DISCLAIMER: TRON Forum and Ken Sakamura shall not be held
   38:  * responsible for any consequences or damages caused directly or
   39:  * indirectly by the use of this software package.
   40:  *
   41:  * The source codes in bsd_source.tar.gz in this software package are 
   42:  * derived from NetBSD or OpenBSD and not covered under T-License 2.x.
   43:  * They need to be changed or redistributed according to the 
   44:  * representation of each source header.
   45:  */
   46: 
   47: /*
   48:  *      ldr_elf.c
   49:  *
   50:  *       T2EX: program load functions
   51:  *       ELF object loader
   52:  */
   53: 
   54: #include <basic.h>
   55: #include <errno.h>
   56: #include <libstr.h>
   57: #include <tk/tkernel.h>
   58: #include <sys/debug.h>
   59: #include <sys/segment.h>
   60: #include <pagedef.h>
   61: #include "pminfo.h"
   62: #include "source.h"
   63: #include "elf.h"
   64: 
   65: 
   66: #if CPU_I386
   67: #define LINK_ADDR       0x00100000            /* link address */
   68: #endif
   69: 
   70: /* architecture check */
   71: #if CPU_I386
   72: #  define CHK_ELFDATA(n)                ( (n) == ELFDATA2LSB )
   73: #  define CHK_ELFMACH(n)                ( (n) == EM_386 )
   74: #  define SHT_RELTYPE                   SHT_REL
   75: #endif
   76: #if CPU_SH3|CPU_SH4
   77: #  define CHK_ELFDATA(n)                ( (n) == ELFDATA2LSB )
   78: #  define CHK_ELFMACH(n)                ( (n) == EM_SH )
   79: #  define SHT_RELTYPE                   SHT_RELA
   80: #endif
   81: #if CPU_ARM
   82: #  define CHK_ELFDATA(n)                ( (n) == ELFDATA2LSB )
   83: #  define CHK_ELFMACH(n)                ( (n) == EM_ARM )
   84: #  define SHT_RELTYPE                   SHT_REL
   85: #endif
   86: #if CPU_MIPS
   87: #  define CHK_ELFDATA(n)                ( (n) == ELFDATA2LSB )
   88: #  define CHK_ELFMACH(n)                ( (n) == EM_MIPS )
   89: #  define SHT_RELTYPE                   SHT_REL
   90: #endif
   91: #if CPU_PPC
   92: #  define CHK_ELFDATA(n)                ( (n) == ELFDATA2MSB )
   93: #  define CHK_ELFMACH(n)                ( (n) == EM_PPC )
   94: #  define SHT_RELTYPE                   SHT_RELA
   95: #endif
   96: 
   97: /*
   98:  * ELF loading information
   99:  */
  100: typedef struct {
  101:         B*     text_ladr;  /* text area load address */
  102:         UW     text_fofs;  /* text area file offset */
  103:         UW     text_size;  /* text area size */
  104:         B*     data_ladr;  /* data area load address */
  105:         UW     data_fofs;  /* data area file offset */
  106:         UW     data_size;  /* data area size */
  107:         B*     bss_ladr;   /* bss  area load address */
  108:         UW     bss_size;   /* bss  area size */
  109: 
  110:         UH     text_shndx; /* text area section number */
  111:         UH     data_shndx; /* data area section number */
  112:         UH     bss_shndx;  /* bss  area section number */
  113:         UW     rel_text_fofs;      /* text area relocation info file offset */
  114:         UW     rel_text_size;      /* text area relocation info size */
  115:         UW     rel_data_fofs;      /* data area relocation info file offset */
  116:         UW     rel_data_size;      /* data area relocation info size */
  117: 
  118:         UW     symtbl_fofs;        /* symbol table file offset */
  119:         UW     symtbl_size;        /* symbol table size */
  120:         BOOL   vir_or_off;       /* relocation information type: 
  121:                                    virtual address (TRUE) or offset inside section (FALSE) */
  122: #if CPU_MIPS
  123:         UW     reginf_fofs;        /* register info file offset */
  124:         UW     reginf_size;        /* register info size */
  125:         W      gp;          /* gp register value */
  126: #endif
  127: #if CPU_PPC
  128:         UW     gp_info_fofs;       /* gp info file offset */
  129:         W      gp;          /* gp register value (_SDA_BASE_) */
  130: #endif
  131: } ELF_LoadInfo;
  132: 
  133: 
  134: /*
  135:  * Get ELF loading information from section header
  136:  */
  137: LOCAL ER GetELFLoadInfoShdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, LoadSource *ldr )
  138: {
  139:         Elf32_Shdr     *shdr_buf, *shdr, *p;
  140:         W              n;
  141:         B              *adr;
  142:         W              symsect = -1;
  143:         ER             er;
  144: 
  145:         if ( hdr->e_shentsize < sizeof(Elf32_Shdr) || hdr->e_shnum == 0 )
  146:                                 { er = EX_INVAL; goto err_ret1; }
  147: 
  148:         /* Allocate buffer for reading ELF section header */
  149:         n = hdr->e_shentsize * hdr->e_shnum;
  150:         shdr_buf = Vmalloc(n);
  151:         if ( shdr_buf == NULL ) { er = EX_NOEXEC; goto err_ret1; }
  152: 
  153:         /* Read section header*/
  154:         er = ldr->read(ldr, hdr->e_shoff, shdr_buf, n);
  155:         if ( er < E_OK ) goto err_ret2;
  156:         if ( er < n ) { er = EX_NOEXEC; goto err_ret2; }
  157: 
  158:         for ( n = hdr->e_shnum, shdr = shdr_buf; --n >= 0;
  159:                         shdr = (Elf32_Shdr*)((B*)shdr + hdr->e_shentsize) ) {
  160: 
  161:                 switch ( shdr->sh_type ) {
  162:                   case SHT_PROGBITS:
  163:                         switch ( shdr->sh_flags ) {
  164:                           case SHF_ALLOC|SHF_EXECINSTR:      /* text area */
  165:                                 if ( eli->text_size != 0 )
  166:                                         { er = EX_NOEXEC; goto err_ret2; }
  167:                                 eli->text_ladr = shdr->sh_addr;
  168:                                 eli->text_fofs = shdr->sh_offset;
  169:                                 eli->text_size = shdr->sh_size;
  170:                                 eli->text_shndx = shdr - shdr_buf;
  171:                                 break;
  172:                           case SHF_ALLOC|SHF_WRITE:  /* data area */
  173:                                 if ( eli->data_ladr != NULL )
  174:                                         { er = EX_NOEXEC; goto err_ret2; }
  175:                                 eli->data_ladr = shdr->sh_addr;
  176:                                 eli->data_fofs = shdr->sh_offset;
  177:                                 eli->data_size = shdr->sh_size;
  178:                                 eli->data_shndx = shdr - shdr_buf;
  179:                                 break;
  180: #if CPU_PPC
  181:                           case SHF_WRITE:            /* gp_info */
  182:                                 if ( shdr->sh_size != 4 ) break;
  183:                                 if ( eli->gp_info_fofs != 0 )
  184:                                         { er = EX_NOEXEC; goto err_ret2; }
  185:                                 eli->gp_info_fofs = shdr->sh_offset;
  186:                                 break;
  187: #endif
  188:                           default:
  189:                                 if ( (shdr->sh_flags & SHF_ALLOC) == 0 )
  190:                                                         continue; /* ignore */
  191:                                 er = EX_NOEXEC; goto err_ret2;
  192:                         }
  193:                         break;
  194: 
  195:                   case SHT_NOBITS:
  196:                         switch ( shdr->sh_flags ) {
  197:                           case SHF_ALLOC|SHF_WRITE:  /* bss area */
  198:                                 if ( eli->bss_ladr != NULL )
  199:                                         { er = EX_NOEXEC; goto err_ret2; }
  200:                                 eli->bss_ladr = shdr->sh_addr;
  201:                                 eli->bss_size = shdr->sh_size;
  202:                                 eli->bss_shndx = shdr - shdr_buf;
  203:                                 break;
  204:                           case 0:
  205:                                 continue; /* ignore */
  206:                           default:
  207:                                 er = EX_NOEXEC; goto err_ret2;
  208:                         }
  209:                         break;
  210: 
  211:                   case SHT_RELTYPE:
  212:                         if ( shdr->sh_info >= hdr->e_shnum
  213:                           || shdr->sh_link >= hdr->e_shnum )
  214:                                         { er = EX_NOEXEC; goto err_ret2; }
  215: 
  216:                         /* relocation target */
  217:                         p = &shdr_buf[shdr->sh_info];
  218:                         if ( p->sh_type != SHT_PROGBITS )
  219:                                 continue;
  220: 
  221:                         switch ( p->sh_flags ) {
  222:                           case SHF_ALLOC|SHF_EXECINSTR:      /* text area */
  223:                                 if ( eli->rel_text_size != 0 )
  224:                                         { er = EX_NOEXEC; goto err_ret2; }
  225:                                 eli->rel_text_fofs = shdr->sh_offset;
  226:                                 eli->rel_text_size = shdr->sh_size;
  227:                                 break;
  228:                           case SHF_ALLOC|SHF_WRITE:  /* data area */
  229:                                 if ( eli->rel_data_size != 0 )
  230:                                         { er = EX_NOEXEC; goto err_ret2; }
  231:                                 eli->rel_data_fofs = shdr->sh_offset;
  232:                                 eli->rel_data_size = shdr->sh_size;
  233:                                 break;
  234:                           case 0:
  235:                                 continue; /* ignore */
  236:                           default:
  237:                                 er = EX_NOEXEC; goto err_ret2;
  238:                         }
  239: 
  240:                         if ( symsect >= 0 && shdr->sh_link != (UW)symsect )
  241:                                         { er = EX_NOEXEC; goto err_ret2; }
  242:                         symsect = shdr->sh_link;
  243:                         break;
  244: #if CPU_MIPS
  245:                   case SHT_MIPS_REGINFO:
  246:                        if( eli->reginf_size != 0 )
  247:                                { er = EX_NOEXEC; goto err_ret2; }
  248:                         eli->reginf_fofs = shdr->sh_offset;
  249:                         eli->reginf_size = shdr->sh_size;
  250:                       break;
  251: #endif
  252:                   default:
  253:                         continue; /* ignore */
  254:                 }
  255:         }
  256: 
  257:         /* Check for loading information validity */
  258:         if ( eli->text_size == 0 ) { er = EX_NOEXEC; goto err_ret2; }
  259:         adr = PageAlignU(eli->text_ladr + eli->text_size);
  260:         if ( eli->data_ladr != adr ) { er = EX_NOEXEC; goto err_ret2; }
  261:         adr += eli->data_size;
  262:         if ( eli->bss_ladr < adr ) { er = EX_NOEXEC; goto err_ret2; }
  263: 
  264:         if ( symsect >= 0 ) {
  265:                 /* symbol table for relocation */
  266:                 if ( shdr_buf[symsect].sh_type != SHT_SYMTAB )
  267:                                         { er = EX_NOEXEC; goto err_ret2; }
  268:                 eli->symtbl_fofs = shdr_buf[symsect].sh_offset;
  269:                 eli->symtbl_size = shdr_buf[symsect].sh_size;
  270:         }
  271: 
  272:         Vfree(shdr_buf);
  273: 
  274:         return E_OK;
  275: 
  276: err_ret2:
  277:         Vfree(shdr_buf);
  278: err_ret1:
  279:         TM_DEBUG_PRINT(("GetELFLoadInfoShdr ercd = %d\n", er));
  280:         return er;
  281: }
  282: 
  283: /*
  284:  * Check if segments with dynamic information exist
  285:  */
  286: LOCAL BOOL HasDynSeg( Elf32_Ehdr *hdr, LoadSource *ldr )
  287: {
  288:         Elf32_Phdr     *phdr_buf, *phdr;
  289:         W              n;
  290:         ER             er;
  291: 
  292:         if ( hdr->e_phentsize < sizeof(Elf32_Phdr) || hdr->e_phnum < 1 )
  293:                                 { er = EX_NOEXEC; goto err_ret1; }
  294: 
  295:         /* Allocate buffer for reading program header */
  296:         n = hdr->e_phentsize * hdr->e_phnum;
  297:         phdr_buf = Vmalloc(n);
  298:         if ( phdr_buf == NULL ) { er = EX_NOMEM; goto err_ret1; }
  299: 
  300:         /* Read program header */
  301:         er = ldr->read(ldr, hdr->e_phoff, phdr_buf, n);
  302:         if ( er < E_OK ) goto err_ret2;
  303:         if ( er < n ) { er = EX_NOEXEC; goto err_ret2; }
  304: 
  305:         for ( n = hdr->e_phnum, phdr = phdr_buf; --n >= 0;
  306:                         phdr = (Elf32_Phdr*)((B*)phdr + hdr->e_phentsize) ) {
  307: 
  308:                 if ( phdr->p_type == PT_DYNAMIC )
  309:                         goto found;
  310:         }
  311: 
  312:         Vfree(phdr_buf);
  313:         return FALSE;
  314: 
  315: found:
  316:         Vfree(phdr_buf);
  317:         return TRUE;
  318: 
  319: err_ret2:
  320:         Vfree(phdr_buf);
  321: err_ret1:
  322:         TM_DEBUG_PRINT(("HasDynSeg ercd = %d\n", er));
  323:         return FALSE;
  324: }
  325: 
  326: /*
  327:  * Check if sections with relocation information exist
  328:  */
  329: LOCAL BOOL HasRelSec( Elf32_Ehdr *hdr, LoadSource *ldr )
  330: {
  331:         Elf32_Shdr     *shdr_buf, *shdr;
  332:         W              n;
  333:         ER             er;
  334: 
  335:         if ( hdr->e_shentsize < sizeof(Elf32_Shdr) || hdr->e_shnum == 0 )
  336:                                 { er = EX_NOEXEC; goto err_ret1; }
  337: 
  338:         /* Allocate buffer for reading section header */
  339:         n = hdr->e_shentsize * hdr->e_shnum;
  340:         shdr_buf = Vmalloc(n);
  341:         if ( shdr_buf == NULL ) { er = EX_NOMEM; goto err_ret1; }
  342: 
  343:         /* Read section header */
  344:         er = ldr->read(ldr, hdr->e_shoff, shdr_buf, n);
  345:         if ( er < E_OK ) goto err_ret2;
  346:         if ( er < n ) { er = EX_NOEXEC; goto err_ret2; }
  347: 
  348:         for ( n = hdr->e_shnum, shdr = shdr_buf; --n >= 0;
  349:                         shdr = (Elf32_Shdr*)((B*)shdr + hdr->e_shentsize) ) {
  350: 
  351:                 switch ( shdr->sh_type ) {
  352:                   case SHT_RELTYPE:
  353:                         goto found;
  354:                   default:
  355:                         continue; /* ignore */
  356:                 }
  357:         }
  358:         Vfree(shdr_buf);
  359:         return FALSE;
  360: 
  361: found:
  362:         Vfree(shdr_buf);
  363:         return TRUE;
  364: 
  365: err_ret2:
  366:         Vfree(shdr_buf);
  367: err_ret1:
  368:         TM_DEBUG_PRINT(("HasRelSec ercd = %d\n", er));
  369:         return FALSE;
  370: }
  371: 
  372: /*
  373:  * Get ELF loading information from program header
  374:  */
  375: LOCAL ER GetELFLoadInfoPhdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, LoadSource *ldr )
  376: {
  377:         Elf32_Phdr     *phdr_buf, *phdr;
  378:         W              n;
  379:         B              *adr;
  380:         ER             er;
  381: 
  382:         if ( hdr->e_phentsize < sizeof(Elf32_Phdr) || hdr->e_phnum < 2 )
  383:                                 { er = EX_NOEXEC; goto err_ret1; }
  384: 
  385:         /* Allocate buffer for reading program header */
  386:         n = hdr->e_phentsize * hdr->e_phnum;
  387:         phdr_buf = Vmalloc(n);
  388:         if ( phdr_buf == NULL ) { er = EX_NOMEM; goto err_ret1; }
  389: 
  390:         /* Read program header */
  391:         er = ldr->read(ldr, hdr->e_phoff, phdr_buf, n);
  392:         if ( er < E_OK ) goto err_ret2;
  393:         if ( er < n ) { er = EX_NOEXEC; goto err_ret2; }
  394: 
  395:         for ( n = hdr->e_phnum, phdr = phdr_buf; --n >= 0;
  396:                         phdr = (Elf32_Phdr*)((B*)phdr + hdr->e_phentsize) ) {
  397: 
  398:                 /* Ignore except for loadable segments */
  399:                 if ( phdr->p_type != PT_LOAD ) continue;
  400: 
  401:                 switch ( phdr->p_flags ) {
  402:                   case PF_R|PF_X:     /* text area */
  403:                         if ( eli->text_size != 0 )
  404:                                         { er = EX_NOEXEC; goto err_ret2; }
  405:                         eli->text_ladr = phdr->p_vaddr;
  406:                         eli->text_fofs = phdr->p_offset;
  407:                         eli->text_size = phdr->p_filesz;
  408:                         break;
  409: 
  410:                   case PF_R|PF_W:     /* data or bss area */
  411:                   case PF_R|PF_W|PF_X:
  412:                         if ( eli->data_ladr != NULL )
  413:                                         { er = EX_NOEXEC; goto err_ret2; }
  414:                         eli->data_ladr = phdr->p_vaddr;
  415:                         eli->data_fofs = phdr->p_offset;
  416:                         eli->data_size = phdr->p_filesz;
  417:                         eli->bss_ladr = (B*)phdr->p_vaddr + phdr->p_filesz;
  418:                         eli->bss_size = phdr->p_memsz - phdr->p_filesz;
  419:                         break;
  420: 
  421:                   case 0:
  422:                         if ( phdr->p_filesz > 0 || phdr->p_memsz > 0 )
  423:                                         { er = EX_NOEXEC; goto err_ret2; }
  424:                         continue; /* ignore */
  425: 
  426:                   default:
  427:                         er = EX_NOEXEC; goto err_ret2;
  428:                 }
  429:         }
  430: 
  431:         /* Check for loading information validity */
  432:         if ( eli->text_size == 0 || eli->data_ladr == NULL )
  433:                                 { er = EX_NOEXEC; goto err_ret2; }
  434:         adr = eli->text_ladr + eli->text_size;
  435:         if ( eli->data_ladr < (B*)PageAlignU(adr) )
  436:                                 { er = EX_NOEXEC; goto err_ret2; }
  437: 
  438:         Vfree(phdr_buf);
  439: 
  440:         return E_OK;
  441: 
  442: err_ret2:
  443:         Vfree(phdr_buf);
  444: err_ret1:
  445:         TM_DEBUG_PRINT(("GetELFLoadInfoPhdr ercd = %d\n", er));
  446:         return er;
  447: }
  448: 
  449: /*
  450:  * Get ELF loading information
  451:  */
  452: LOCAL ER GetELFLoadInfo( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, LoadSource *ldr, BOOL relsec )
  453: {
  454:         ER     er;
  455: 
  456:         memset(eli, 0, sizeof(ELF_LoadInfo));
  457: 
  458:         /* Check if header is valid */
  459:         if ( !(hdr->e_ident[EI_CLASS] == ELFCLASS32
  460:             && CHK_ELFDATA(hdr->e_ident[EI_DATA])
  461:             && hdr->e_ident[EI_VERSION] == 1
  462:             && CHK_ELFMACH(hdr->e_machine)
  463:             && hdr->e_version == EV_CURRENT) ) {
  464:                 er = EX_NOEXEC; goto err_ret;
  465:         }
  466: 
  467:         switch ( hdr->e_type ) {
  468:           case ET_EXEC:
  469:                if ( relsec ) {
  470:                         /* Get loading information from section header */
  471:                         eli->vir_or_off = TRUE;
  472:                         er = GetELFLoadInfoShdr(eli, hdr, ldr);
  473:                 } else {
  474:                         /* Get loading information from program header */
  475:                         er = GetELFLoadInfoPhdr(eli, hdr, ldr);
  476:                 }
  477:                 if ( er < E_OK ) goto err_ret;
  478:                 break;
  479: 
  480:           case ET_DYN:
  481:                 /* Get loading information from program header */
  482:                 er = GetELFLoadInfoPhdr(eli, hdr, ldr);
  483:                 if ( er < E_OK ) goto err_ret;
  484:                 break;
  485: 
  486:           case ET_REL:
  487:                 /* Get loading information from section header */
  488:                 er = GetELFLoadInfoShdr(eli, hdr, ldr);
  489:                 if ( er < E_OK ) goto err_ret;
  490:                 break;
  491: 
  492:           default:
  493:                 er = EX_NOEXEC; goto err_ret;
  494:         }
  495: 
  496:         return E_OK;
  497: 
  498: err_ret:
  499:         TM_DEBUG_PRINT(("GetELFLoadInfo ercd = %d\n", er));
  500:         return er;
  501: }
  502: 
  503: #if CPU_MIPS
  504: typedef struct {
  505:         W      *addr;
  506:         UW     val;
  507: } Ahi_Info;
  508: #define AHI_INFO_UNIT   1
  509: #endif
  510: 
  511: /*
  512:  * Relocate a single section
  513:  */
  514: LOCAL ER reloc1( ELF_LoadInfo *eli, LoadSource *ldr, W rtbl, W rtblsz, W lofs,
  515:                 B *sect, W sectsz, Elf32_Sym *symtbl, W syment )
  516: {
  517: #if SHT_RELTYPE == SHT_REL
  518:         Elf32_Rel      *reloc, *rp, *reloc_end;
  519: #endif
  520: #if SHT_RELTYPE == SHT_RELA
  521:         Elf32_Rela     *reloc, *rp, *reloc_end;
  522: #endif
  523: #if CPU_ARM
  524:         W              ofs;
  525: #endif
  526: #if CPU_MIPS
  527:         Ahi_Info       *ahi_info = NULL;
  528:         Ahi_Info       *ahi_infotmp;
  529:         W              ahi_infomax = AHI_INFO_UNIT;
  530:         W              ahi_infonext = 0;
  531:         W              ahi_infoused = 0;
  532:         W              ind;
  533:         W              ahl, addend, nadr;
  534:         UH             *hp;
  535: #endif
  536:         W              *wp, sv, i;
  537:         B              *ladr;
  538:         ER             er;
  539: 
  540:         if ( rtblsz == 0 ) return E_OK;  /* No relocation target */
  541: 
  542:         /* Read relocation information */
  543:         reloc = Vmalloc(rtblsz);
  544:         if ( reloc == NULL ) { er = EX_NOMEM; goto err_ret1; }
  545:         er = ldr->read(ldr, rtbl, reloc, rtblsz);
  546:         if ( er < E_OK ) goto err_ret2;
  547:         if ( er < rtblsz ) { er = EX_NOEXEC; goto err_ret2; }
  548: 
  549:         reloc_end = &reloc[rtblsz / sizeof(*reloc)];
  550:         if ( eli->vir_or_off ) {
  551:                 for ( rp = reloc; rp < reloc_end; rp++ ) {
  552:                         /* Convert to offset inside section */
  553:                         rp->r_offset -= ((UW)sect - lofs);
  554:                 }
  555:         }
  556: 
  557:         for ( rp = reloc; rp < reloc_end; rp++ ) {
  558: 
  559:                 i = ELF32_R_SYM(rp->r_info);
  560:                 if ( i >= syment || (UW)rp->r_offset >= (UW)sectsz )
  561:                                         { er = EX_NOEXEC; goto err_ret2; }
  562: 
  563:                 /* Skip unless relocation is needed */
  564:                 if ( ELF32_R_TYPE(rp->r_info) == 0 ) continue;
  565: 
  566:                 /* Get relocation target and its symbol value */
  567:                 wp = (W*)(sect + (UW)rp->r_offset);
  568:                 sv = (W)symtbl[i].st_value;
  569: 
  570:                 /* Get section to which the symbol belongs */
  571:                 if ( symtbl[i].st_shndx == eli->text_shndx ) {
  572:                         ladr = eli->text_ladr;
  573:                 } else if ( symtbl[i].st_shndx == eli->data_shndx ) {
  574:                         ladr = eli->data_ladr;
  575:                 } else if ( symtbl[i].st_shndx == eli->bss_shndx ) {
  576:                         ladr = eli->bss_ladr;
  577:                 } else if ( symtbl[i].st_shndx == SHN_ABS ) {
  578:                         ladr = (B*)0 - lofs;
  579:                 } else if ( symtbl[i].st_shndx == SHN_UNDEF ) {
  580:                         if ( ELF32_ST_BIND(symtbl[i].st_info) == STB_WEAK )
  581:                                                                 continue;
  582: #if 1
  583:                 /*
  584:                  * GNU strip seems to have a bug that makes symbol numbers 
  585:                  * of relocation information to 0, when symbols having 
  586:                  * the value 0 are referred to. Such phonomenon is observed 
  587:                  * on SH, ARM, MIPS, while other architecture might be 
  588:                  * affected as well.
  589:                  * As a countermeasure, here we treat symbols having 
  590:                  * number 0 to have the value of 0. However, the lack of 
  591:                  * correct symbol number results in the lack of knowledge 
  592:                  * of the section the symbol belongs to. For this reason, 
  593:                  * it is assumed that only ABS section contains symbols with 
  594:                  * value 0. Hence, it is not allowed to locate symbols at 
  595:                  * address 0 at link time. 
  596:                  */
  597:                         if ( i == 0 ) {
  598:                                 ladr = (B*)0 - lofs; /* ABS section */
  599:                                 sv = 0;
  600:                         } else
  601: #endif
  602:                         { er = EX_NOEXEC; goto err_ret2; }
  603:                 } else {
  604:                         er = EX_NOEXEC; goto err_ret2;
  605:                 }
  606: 
  607: #if CPU_I386
  608:                 /* 
  609:                  * GNU strip 2.8.1 seems to have a bug that converts 
  610:                  * st_value to a corresponding logical address, 
  611:                  * where section offset value should instead be given 
  612:                  * according to the ELF specification. 
  613:                  * In order to cope with it, st_value is converted back to 
  614:                  * a section offset when st_value >= LINK_ADDR (0x00100000), 
  615:                  * as the logical address starts at LINK_ADDR as specified 
  616:                  * in linker script.
  617:                  */
  618:                 if ( sv >= LINK_ADDR ) sv -= (W)ladr;
  619: #endif
  620: 
  621:                 /* Execute relocation */
  622:                 switch ( ELF32_R_TYPE(rp->r_info) ) {
  623: #if CPU_I386
  624:                   case R_386_32:
  625:                         if ( eli->vir_or_off ) {
  626:                                 sv = 0;
  627:                                 *wp -= (W)ladr;
  628:                         }
  629:                         *wp += sv + (W)ladr + lofs;
  630:                         break;
  631: 
  632:                   case R_386_PC32:
  633:                         if ( eli->vir_or_off ) {
  634:                                 break;
  635:                         }
  636:                         *wp += sv - (W)rp->r_offset;
  637:                         break;
  638: #endif
  639: #if CPU_ARM
  640:                   case R_ARM_PC24:
  641:                         if ( eli->vir_or_off ) {
  642:                                 break;
  643:                         }
  644:                         ofs = (W)((UW)*wp << 8) >> 8; /* sign expansion of 24-bit integer */
  645:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){
  646:                                 ofs -= (W)rp->r_offset >> 2;
  647:                         } else {
  648:                                 ofs += (sv - (W)rp->r_offset) >> 2;
  649:                         }
  650:                         *wp = (*wp & 0xff000000) | (ofs & 0x00ffffff);
  651:                         break;
  652: 
  653:                   case R_ARM_ABS32:
  654:                         if ( eli->vir_or_off ) {
  655:                                 sv = 0;
  656:                                 *wp -= (W)ladr;
  657:                         }
  658:                         *wp += sv + (W)ladr + lofs;
  659:                         break;
  660:                   case R_ARM_THM_PC22:
  661:                         if ( !eli->vir_or_off ) {
  662:                                 er = EX_NOEXEC; goto err_ret2;
  663:                         }
  664:                         break;
  665: #endif
  666: #if CPU_MIPS
  667:                   case R_MIPS_32:
  668:                         if ( eli->vir_or_off ) {
  669:                                 SetMisalignW((UB*)wp, GetMisalignW((UB*)wp) - sv);
  670:                                 sv -= (W)ladr;
  671:                         }
  672:                         SetMisalignW((UB*)wp, GetMisalignW((UB*)wp) + (W)ladr + sv + lofs);
  673:                       break;
  674: 
  675:                   case R_MIPS_26:
  676:                         if ( eli->vir_or_off ) {
  677:                                 if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){     
  678:                                         nadr = (((*wp & 0x03ffffff) << 2) - (W)ladr) >> 2;
  679:                                         *wp = ( *wp & 0xfc000000) | ( nadr & 0x03ffffff);
  680:                                 } else {
  681:                                         *wp &= 0xfc000000;
  682:                                 }
  683:                                 sv -= (W)ladr;
  684:                         }
  685:                         addend = *wp & 0x03ffffff;
  686:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){      
  687:                                 nadr = (addend << 2) | (((W)ladr + (W)rp->r_offset) & 0xf0000000);
  688:                         }else{
  689:                                 nadr = (W)((UW)addend << 6) >> 4; 
  690:                         }
  691:                         nadr += (W)ladr + sv + lofs;
  692:                         nadr >>= 2;
  693:                         *wp = ( *wp & 0xfc000000) | ( nadr & 0x03ffffff);
  694:                       break;
  695: 
  696:                   case R_MIPS_HI16:
  697:                         if ( ahi_info == NULL) {
  698:                                 ahi_info = Vmalloc( sizeof( Ahi_Info) * AHI_INFO_UNIT);
  699:                                 if ( ahi_info == NULL) { er = EX_NOMEM; goto err_ret2; }
  700:                         }
  701:                         if( ahi_infoused ) {
  702:                                 ahi_infonext = 0;
  703:                                 ahi_infoused = 0;
  704:                         }
  705:                         if( ahi_infomax <= ahi_infonext){
  706:                                 ahi_infotmp = Vrealloc( ahi_info, sizeof( Ahi_Info) * ( ahi_infomax + AHI_INFO_UNIT));
  707:                                 if ( ahi_infotmp == NULL ) { er = EX_NOMEM; goto err_ret2; }
  708:                                 ahi_info = ahi_infotmp;
  709:                                 ahi_infomax += AHI_INFO_UNIT;
  710:                         }
  711:                         ahi_info[ ahi_infonext].addr = wp;
  712:                         ahi_info[ ahi_infonext].val  = (UW)*wp << 16;
  713:                         ahi_infonext++;
  714:                       break;
  715: 
  716:                   case R_MIPS_LO16:
  717:                         if ( ahi_info == NULL) { err = EX_NOEXEC; goto err_ret2; }
  718:                         if ( ahi_infoused == 0 ) {
  719:                                 ahi_infoused = 1;
  720:                              for ( ind = 0; ind < ahi_infonext; ind++ ) {
  721:                                     ahl = ( ahi_info[ ind].val & 0xffff0000) + ( short)(*wp & 0xffff);
  722:                                         if ( eli->vir_or_off ) {
  723:                                                 ahl -= sv;
  724:                                                 sv -= (W)ladr;
  725:                                         }
  726:                                         nadr = ahl + (W)ladr + sv + lofs;
  727:                                      *ahi_info[ ind].addr = ((( nadr - (short)nadr) >> 16) & 0x0000ffff) 
  728:                                                              | ( *ahi_info[ ind].addr & 0xffff0000);
  729:                                 }
  730:                                 if ( 1 < ahi_infonext ) {
  731:                                         ahi_info[ 0] = ahi_info[ ahi_infonext - 1];
  732:                                         ahi_infonext = 1;
  733:                                 }
  734:                         } else {
  735:                              ahl = ( ahi_info[ 0].val & 0xffff0000) + ( short)(*wp & 0xffff);
  736:                                 if ( eli->vir_or_off ) {
  737:                                         ahl -= sv;
  738:                                         sv -= (W)ladr;
  739:                                 }
  740:                                 nadr = ahl + (W)ladr + sv + lofs;
  741:                         }
  742:                       *wp = ( nadr & 0xffff) | (*wp & 0xffff0000);
  743:                       break;
  744: 
  745:                   case R_MIPS_GPREL16:
  746:                   case R_MIPS_LITERAL:
  747:                       if ( eli->vir_or_off ) {
  748:                                 break;
  749:                       }
  750:                         addend = *wp & 0xffff;
  751:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){
  752:                                 nadr = ((W)ladr + (( sv + addend + eli->gp ) & 0x0000ffff) - eli->gp) & 0x0000ffff;
  753:                         }else{
  754:                                 nadr = ((W)ladr + sv + addend - eli->gp ) & 0x0000ffff;
  755:                         }
  756:                       *wp = nadr | (*wp & 0xffff0000);
  757:                       break;
  758: 
  759:                   case R_MIPS16_26:
  760:                       if ( !eli->vir_or_off ) {
  761:                                 er = EX_NOEXEC; goto err_ret2;
  762:                       }
  763: 
  764:                         hp = (UH*)wp;
  765:                         addend =  ((UW)(*hp & 0x03e0) << 13)
  766:                                 | ((UW)(*hp & 0x001f) << 23)
  767:                                 | ((UW)*(hp + 1) << 2);
  768:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){      
  769:                                 addend -= (W)ladr;
  770:                         } else {
  771:                                 addend = 0;
  772:                         }
  773:                         sv -= (W)ladr;
  774: 
  775:                         /***/
  776:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){      
  777:                                 nadr = (addend << 2) | (((W)ladr + (W)rp->r_offset) & 0xf0000000);
  778:                         }else{
  779:                                 nadr = (W)((UW)addend << 6) >> 4; 
  780:                         }
  781:                         nadr += (W)ladr + sv + lofs;
  782:                         nadr >>= 2;
  783: 
  784:                         *hp = (*hp & 0xfc00) 
  785:                                 | (( nadr & 0x03e00000) >> 21)
  786:                                 | (( nadr & 0x001f0000) >> 11);
  787:                       *(hp+1) = nadr & 0xffff;
  788:                       break;
  789: 
  790:                   case        R_MIPS16_GPREL:
  791:                       if ( !eli->vir_or_off ) {
  792:                                 er = EX_NOEXEC; goto err_ret2;
  793:                       }
  794:                       break;
  795:                   
  796: #endif
  797: #if CPU_SH3|CPU_SH4
  798:                   case R_SH_DIR32:
  799:                         if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){
  800:                                 *wp += rp->r_addend + lofs;
  801:                         } else {
  802:                                 if ( eli->vir_or_off ) {
  803:                                         *wp -= sv;
  804:                                         sv -= (W)ladr;
  805:                                 }
  806:                                 *wp += sv + rp->r_addend + (W)ladr + lofs;
  807:                         }
  808:                         break;
  809:                   case R_SH_REL32:
  810:                         if ( !eli->vir_or_off ) {
  811:                                 er = EX_NOEXEC; goto err_ret2;
  812:                         }
  813:                       break;
  814: #endif
  815: #if CPU_PPC
  816:                   case R_PPC_ADDR32:
  817:                         if ( !eli->vir_or_off ) sv += (W)ladr;
  818:                         *wp = sv + rp->r_addend + lofs;
  819:                         break;
  820:                   case R_PPC_ADDR16_LO:
  821:                         if ( !eli->vir_or_off ) sv += (W)ladr;
  822:                         *(H*)wp = sv + rp->r_addend + lofs;
  823:                         break;
  824:                   case R_PPC_ADDR16_HI:
  825:                         if ( !eli->vir_or_off ) sv += (W)ladr;
  826:                         *(H*)wp = (sv + rp->r_addend + lofs) >> 16;
  827:                         break;
  828:                   case R_PPC_ADDR16_HA:
  829:                         if ( !eli->vir_or_off ) sv += (W)ladr;
  830:                         sv += rp->r_addend + lofs;
  831:                         *(H*)wp = (sv >> 16) - ((H)sv >> 15);
  832:                         break;
  833:                   case R_PPC_REL32:
  834:                         if ( eli->vir_or_off ) break;
  835:                         *wp = sv + rp->r_addend - (W)rp->r_offset;
  836:                         break;
  837:                   case R_PPC_REL24:
  838:                   case R_PPC_PLTREL24:        /* direct jump (not using PLT) */
  839:                         if ( eli->vir_or_off ) break;
  840:                         sv += rp->r_addend - (W)rp->r_offset;
  841:                         if ( sv < -0x02000000 || sv > 0x01fffffc )
  842:                                 { er = EX_NOEXEC; goto err_ret2; }
  843:                         *wp = (*wp & 0xfc000003) | (sv & 0x03fffffc);
  844:                         break;
  845:                   case R_PPC_REL14:
  846:                   case R_PPC_REL14_BRTAKEN:
  847:                   case R_PPC_REL14_BRNTAKEN:
  848:                         if ( eli->vir_or_off ) break;
  849:                         sv += rp->r_addend - (W)rp->r_offset;
  850:                         if ( sv < -0x00008000 || sv > 0x00007ffc )
  851:                                 { er = EX_NOEXEC; goto err_ret2; }
  852:                         *wp = (*wp & 0xffff0003) | (sv & 0x0000fffc);
  853:                         switch ( ELF32_R_TYPE(rp->r_info) ) {
  854:                           case R_PPC_REL14_BRTAKEN:
  855:                                 if ( sv >= 0 )      *wp |=  0x00200000;
  856:                                 else                *wp &= ~0x00200000;
  857:                                 break;
  858:                           case R_PPC_REL14_BRNTAKEN:
  859:                                 if ( sv >= 0 )      *wp &= ~0x00200000;
  860:                                 else                *wp |=  0x00200000;
  861:                                 break;
  862:                         }
  863:                         break;
  864:                   case R_PPC_SDAREL16:
  865:                         if ( eli->vir_or_off ) break;
  866:                         sv += rp->r_addend + (W)ladr - eli->gp;
  867:                         if ( sv < -0x00008000 || sv > 0x00007fff )
  868:                                 { er = EX_NOEXEC; goto err_ret2; }
  869:                         *(H*)wp = sv;
  870:                         break;
  871: #endif
  872:                   default:
  873:                         er = EX_NOEXEC; goto err_ret2;
  874:                 }
  875:         }
  876: 
  877: #if CPU_MIPS
  878:         if( ahi_info ) { 
  879:                 Vfree(ahi_info);
  880:         }
  881: #endif
  882:         Vfree(reloc);
  883: 
  884:         return E_OK;
  885: 
  886: err_ret2:
  887: #if CPU_MIPS
  888:         if( ahi_info ) {
  889:                 Vfree(ahi_info);
  890:         }
  891: #endif
  892:         Vfree(reloc);
  893: err_ret1:
  894:         TM_DEBUG_PRINT(("reloc1 ercd = %d\n", er));
  895:         return er;
  896: }
  897: 
  898: #if CPU_MIPS
  899: /*
  900:  * Get gp
  901:  */
  902: LOCAL ER elf_get_gp( LoadSource *ldr, ELF_LoadInfo *eli )
  903: {
  904:         ER     er;
  905:         W      n;
  906:         Elf32_RegInfo  reginfo;
  907: 
  908:         /* Read register information */
  909:         n = eli->reginf_size;
  910:         if( n <= 0 ) { er = EX_NOEXEC; goto err_ret; }
  911: 
  912:         er = ldr->read(ldr, eli->reginf_fofs, &reginfo, n);
  913:         if ( er < E_OK ) goto err_ret;
  914:         if ( er < n ) { er = EX_NOEXEC; goto err_ret; }
  915: 
  916:         eli->gp = reginfo.ri_gp_value;
  917:         return E_OK;
  918: 
  919: err_ret:
  920:         TM_DEBUG_PRINT(("elf_get_gp ercd = %d\n", er));
  921:         return er;
  922: }
  923: #endif
  924: 
  925: #if CPU_PPC
  926: /*
  927:  * Get gp
  928:  */
  929: LOCAL ER elf_get_gp( LoadSource* ldr, ELF_LoadInfo *eli )
  930: {
  931:         UW     gp_info;
  932:         ER     er;
  933: 
  934:         if ( eli->gp_info_fofs == 0 ) { er = EX_NOEXEC; goto err_ret; }
  935: 
  936:         /* Read gp information */
  937:         er = ldr->read(ldr, eli->gp_info_fofs, (B*)&gp_info, sizeof(gp_info));
  938:         if ( er < E_OK ) goto err_ret;
  939:         if ( er < sizeof(gp_info) ) { er = EX_NOEXEC; goto err_ret; }
  940: 
  941:         eli->gp = gp_info;
  942: 
  943:         return E_OK;
  944: 
  945: err_ret:
  946:         TM_DEBUG_PRINT(("elf_get_gp ercd = %d \n", er));
  947:         return er;
  948: }
  949: #endif
  950: 
  951: /*
  952:  * ELF relocation
  953:  */
  954: LOCAL ER elf_relocation( ProgInfo *pg, LoadSource *ldr, ELF_LoadInfo *eli, W lofs )
  955: {
  956:         Elf32_Sym      *symtbl;
  957:         W              n;
  958:         ER             er;
  959: 
  960:         if ( eli->symtbl_size == 0 )
  961:                         return E_OK;  /* no relocation information */
  962: 
  963:         /* Read symbol table */
  964:         n = eli->symtbl_size;
  965:         symtbl = Vmalloc(n);
  966:         if ( symtbl == NULL ) { er = EX_NOMEM; goto err_ret1; }
  967:         er = ldr->read(ldr, eli->symtbl_fofs, symtbl, n);
  968:         if ( er < E_OK ) goto err_ret2;
  969:         if ( er < n ) { er = EX_NOEXEC; goto err_ret2; }
  970: 
  971:         n /= sizeof(Elf32_Sym);
  972: 
  973: #if CPU_MIPS|CPU_PPC
  974:         er = elf_get_gp(ldr, eli); /* get gp */
  975:         if ( er < E_OK ) goto err_ret2;
  976: #endif
  977: 
  978:         /* text area relocation */
  979:         er = reloc1(eli, ldr, eli->rel_text_fofs, eli->rel_text_size, lofs,
  980:                         eli->text_ladr + lofs, eli->text_size, symtbl, n);
  981:         if ( er < E_OK ) goto err_ret2;
  982: 
  983:         /* data area relocation */
  984:         er = reloc1(eli, ldr, eli->rel_data_fofs, eli->rel_data_size, lofs,
  985:                         eli->data_ladr + lofs, eli->data_size, symtbl, n);
  986:         if ( er < E_OK ) goto err_ret2;
  987: 
  988:         Vfree(symtbl);
  989: 
  990:         return E_OK;
  991: 
  992: err_ret2:
  993:         Vfree(symtbl);
  994: err_ret1:
  995:         TM_DEBUG_PRINT(("elf_relocation ercd = %d\n", er));
  996:         return er;
  997: }
  998: 
  999: /*
 1000:  * Load ELF object
 1001:  */
 1002: EXPORT ER elf_load( ProgInfo *pg, LoadSource *ldr, UINT attr, Elf32_Ehdr *hdr )
 1003: {
 1004:         ELF_LoadInfo   eli;
 1005:         B              *ladr, *top_adr;
 1006:         UW             npage;
 1007:         W              lofs, sz;
 1008:         BOOL           relsec;
 1009:         ER             er;
 1010: 
 1011:         if ( hdr->e_type == ET_EXEC ) {
 1012:                 relsec = (HasDynSeg(hdr, ldr) ? FALSE : HasRelSec(hdr, ldr));
 1013:         } else {
 1014:                 relsec = FALSE;
 1015:         }
 1016: 
 1017:         /* Dynamic link library is not allowed as program module */
 1018:         if ( hdr->e_type == ET_DYN )
 1019:                 { er = EX_NOEXEC; goto err_ret1; }
 1020: 
 1021:         /* Get ELF loading information */
 1022:         er = GetELFLoadInfo(&eli, hdr, ldr, relsec);
 1023:         if ( er < E_OK ) goto err_ret1;
 1024: 
 1025:         top_adr = PageAlignL(eli.text_ladr);
 1026: 
 1027:         /* Get load size (the number of pages) */
 1028:         npage = PageCount(eli.bss_ladr + eli.bss_size - top_adr);
 1029: 
 1030:         ladr = top_adr;
 1031:         if ( hdr->e_type != ET_EXEC
 1032:                 || (hdr->e_type == ET_EXEC && eli.vir_or_off) ) {
 1033: 
 1034:                 /* Allocate memory for loading program */
 1035:                 er = tk_get_smb((void**)&ladr, npage, attr);
 1036:                 if ( er < E_OK ) { er = EX_NOMEM; goto err_ret1; }
 1037:         }
 1038: 
 1039:         pg->loadadr = ladr; /* load address */
 1040:         pg->loadsz = eli.bss_ladr + eli.bss_size - top_adr; /* program size (including bss) */
 1041: 
 1042:         lofs = ladr - top_adr;
 1043: 
 1044:         /* Read text area */
 1045:         er = ldr->read(ldr, eli.text_fofs, eli.text_ladr + lofs, eli.text_size);
 1046:         if ( er < E_OK ) goto err_ret2;
 1047:         if ( er < eli.text_size ) { er = EX_NOEXEC; goto err_ret2; }
 1048: 
 1049:         /* Read data area */
 1050:         er = ldr->read(ldr, eli.data_fofs, eli.data_ladr + lofs, eli.data_size);
 1051:         if ( er < E_OK ) goto err_ret2;
 1052:         if ( er < eli.data_size ) { er = EX_NOEXEC; goto err_ret2; }
 1053: 
 1054:         if ( hdr->e_type == ET_REL
 1055:                         || ( hdr->e_type == ET_EXEC && eli.vir_or_off) ) {
 1056:                 /* Relocation */
 1057:                 er = elf_relocation(pg, ldr, &eli, lofs);
 1058:                 if ( er < E_OK ) goto err_ret2;
 1059:         }
 1060: 
 1061:         /* Make text area executable, and non-writable */
 1062:         sz = eli.text_ladr + eli.text_size - top_adr;
 1063:         er = SetMemoryAccess(ladr, sz, MM_READ|MM_EXECUTE);
 1064:         if ( er < 0 ) goto err_ret2;
 1065: 
 1066:         /* Flush memory cache
 1067:                 data area is flushed as well, as it may be executed on some platforms(PowerPC) */
 1068:         FlushMemCache(ladr, sz, TCM_ICACHE|TCM_DCACHE);
 1069:         FlushMemCache(eli.data_ladr + lofs, eli.data_size, TCM_ICACHE|TCM_DCACHE);
 1070: 
 1071:         /* Get entry point address */
 1072:         pg->entry = (FP)((B*)hdr->e_entry + lofs);
 1073:         pg->modentry = NULL;
 1074: 
 1075:         return E_OK;
 1076: 
 1077: err_ret2:
 1078:         if ( hdr->e_type != ET_EXEC
 1079:                 || ( hdr->e_type == ET_EXEC && eli.vir_or_off) ) {
 1080:                 tk_rel_smb(ladr);
 1081:         }
 1082: err_ret1:
 1083:         TM_DEBUG_PRINT(("elf_load ercd = %d\n", er));
 1084:         return er;
 1085: }