681 lines
17 KiB
C
681 lines
17 KiB
C
/*
|
|
* Copyright (c) 2010-2014 Wind River Systems, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief generate offset definition header file
|
|
*
|
|
* genOffsetHeader -i <objectModule> -o <outputHeaderName>
|
|
*
|
|
* This Zephyr development host utility will process an ELF object module that
|
|
* consists of a series of absolute symbols representing the byte offset of a
|
|
* structure member and the size of the structure. Each absolute symbol will
|
|
* be translated into a C preprocessor '#define' directive. For example,
|
|
* assuming that the module offsets.o contains the following absolute symbols:
|
|
*
|
|
* $ nm offsets.o
|
|
* 00000010 A __tNANO_common_isp_OFFSET
|
|
* 00000008 A __tNANO_current_OFFSET
|
|
* 0000000c A __tNANO_nested_OFFSET
|
|
* 00000000 A __tNANO_fiber_OFFSET
|
|
* 00000004 A __tNANO_task_OFFSET
|
|
*
|
|
* ... the following C preprocessor code will be generated:
|
|
*
|
|
* #define __tNANO_common_isp_OFFSET 0x10
|
|
* #define __tNANO_current_OFFSET 0x8
|
|
* #define __tNANO_nested_OFFSET 0xC
|
|
* #define __tNANO_fiber_OFFSET 0x0
|
|
* #define __tNANO_task_OFFSET 0x4
|
|
*/
|
|
|
|
/* includes */
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include "elf.h"
|
|
#include <stdlib.h> /* for malloc()/free()/exit() */
|
|
#include <string.h> /* for strstr() */
|
|
#include <getopt.h>
|
|
#include <errno.h>
|
|
|
|
/* defines */
|
|
|
|
#undef DEBUG
|
|
|
|
/* the symbol name suffix used to denote structure member offsets */
|
|
|
|
#define STRUCT_OFF_SUFFIX "_OFFSET"
|
|
#define STRUCT_SIZ_SUFFIX "_SIZEOF"
|
|
|
|
#ifdef DEBUG
|
|
#define DBG_PRINT(args...) printf(args)
|
|
#else
|
|
#define DBG_PRINT(args...)
|
|
#endif
|
|
|
|
|
|
/* byte swapping macros */
|
|
|
|
#define SWAB_Elf32_Half(x) ((x >> 8) | (x << 8))
|
|
#define SWAB_Elf32_Word(x) (((x >> 24) & 0xff) | \
|
|
((x << 8) & 0xff0000) | \
|
|
((x >> 8) & 0xff00) | \
|
|
((x << 24) & 0xff000000))
|
|
|
|
#define SWAB_Elf32_Addr SWAB_Elf32_Word
|
|
#define SWAB_Elf32_Off SWAB_Elf32_Word
|
|
#define SWAB_Elf32_Sword SWAB_Elf32_Word
|
|
|
|
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__WIN32__)
|
|
#define OPEN_FLAGS (O_RDONLY|O_BINARY)
|
|
#else
|
|
#define OPEN_FLAGS (O_RDONLY)
|
|
#endif
|
|
|
|
/* locals */
|
|
|
|
/* global indicating whether ELF structures need to be byte swapped */
|
|
|
|
static char swabRequired;
|
|
|
|
|
|
/* usage information */
|
|
|
|
static char usage[] = "usage: %s -i <objectModule> -o <outputHeaderName>\n";
|
|
|
|
|
|
/* output header file preamble */
|
|
|
|
static char preamble1[] = "\
|
|
/* %s - structure member offsets definition header */\n\
|
|
\n\
|
|
/*\n\
|
|
* Copyright (c) 2010-2014 Wind River Systems, Inc.\n\
|
|
*\n\
|
|
* Licensed under the Apache License, Version 2.0 (the \"License\");\n\
|
|
* you may not use this file except in compliance with the License.\n\
|
|
* You may obtain a copy of the License at\n\
|
|
*\n\
|
|
* http://www.apache.org/licenses/LICENSE-2.0\n\
|
|
*\n\
|
|
* Unless required by applicable law or agreed to in writing, software\n\
|
|
* distributed under the License is distributed on an \"AS IS\" BASIS,\n\
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\
|
|
* See the License for the specific language governing permissions and\n\
|
|
* limitations under the License.\n\
|
|
*/\n\
|
|
\n\
|
|
/* THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT */\n\
|
|
\n\
|
|
/*\n\
|
|
* This header file provides macros for the offsets of various structure\n\
|
|
* members. These offset macros are primarily intended to be used in\n\
|
|
* assembly code.\n\
|
|
*/\n\n";
|
|
|
|
static char preamble2[] = "\
|
|
/*\n\
|
|
* Auto-generated header guard.\n\
|
|
*/\n\
|
|
#ifndef %s\n\
|
|
#define %s\n\
|
|
\n\
|
|
#ifdef __cplusplus\n\
|
|
extern \"C\" {\n\
|
|
#endif\n\
|
|
\n\
|
|
/* defines */\n\n";
|
|
|
|
|
|
/* output header file postscript */
|
|
|
|
static char postscript[] = "\
|
|
\n\
|
|
#ifdef __cplusplus\n\
|
|
}\n\
|
|
#endif\n\
|
|
\n\
|
|
#endif /* _HGUARD_ */\n";
|
|
|
|
static Elf32_Ehdr ehdr; /* ELF header */
|
|
static Elf32_Shdr * shdr; /* pointer to array ELF section headers */
|
|
|
|
/**
|
|
* @brief byte swap the Elf32_Ehdr structure
|
|
*
|
|
* @returns N/A
|
|
*/
|
|
static void swabElfHdr(Elf32_Ehdr *pHdrToSwab)
|
|
{
|
|
if (swabRequired == 0)
|
|
{
|
|
return; /* do nothing */
|
|
}
|
|
|
|
pHdrToSwab->e_type = SWAB_Elf32_Half(pHdrToSwab->e_type);
|
|
pHdrToSwab->e_machine = SWAB_Elf32_Half(pHdrToSwab->e_machine);
|
|
pHdrToSwab->e_version = SWAB_Elf32_Word(pHdrToSwab->e_version);
|
|
pHdrToSwab->e_entry = SWAB_Elf32_Addr(pHdrToSwab->e_entry);
|
|
pHdrToSwab->e_phoff = SWAB_Elf32_Off(pHdrToSwab->e_phoff);
|
|
pHdrToSwab->e_shoff = SWAB_Elf32_Off(pHdrToSwab->e_shoff);
|
|
pHdrToSwab->e_flags = SWAB_Elf32_Word(pHdrToSwab->e_flags);
|
|
pHdrToSwab->e_ehsize = SWAB_Elf32_Half(pHdrToSwab->e_ehsize);
|
|
pHdrToSwab->e_phentsize = SWAB_Elf32_Half(pHdrToSwab->e_phentsize);
|
|
pHdrToSwab->e_phnum = SWAB_Elf32_Half(pHdrToSwab->e_phnum);
|
|
pHdrToSwab->e_shentsize = SWAB_Elf32_Half(pHdrToSwab->e_shentsize);
|
|
pHdrToSwab->e_shnum = SWAB_Elf32_Half(pHdrToSwab->e_shnum);
|
|
pHdrToSwab->e_shstrndx = SWAB_Elf32_Half(pHdrToSwab->e_shstrndx);
|
|
}
|
|
|
|
/**
|
|
* @brief byte swap the Elf32_Shdr structure
|
|
*
|
|
* @returns N/A
|
|
*/
|
|
static void swabElfSectionHdr(Elf32_Shdr *pHdrToSwab)
|
|
{
|
|
if (swabRequired == 0)
|
|
{
|
|
return; /* do nothing */
|
|
}
|
|
|
|
pHdrToSwab->sh_name = SWAB_Elf32_Word(pHdrToSwab->sh_name);
|
|
pHdrToSwab->sh_type = SWAB_Elf32_Word(pHdrToSwab->sh_type);
|
|
pHdrToSwab->sh_flags = SWAB_Elf32_Word(pHdrToSwab->sh_flags);
|
|
pHdrToSwab->sh_addr = SWAB_Elf32_Addr(pHdrToSwab->sh_addr);
|
|
pHdrToSwab->sh_offset = SWAB_Elf32_Off(pHdrToSwab->sh_offset);
|
|
pHdrToSwab->sh_size = SWAB_Elf32_Word(pHdrToSwab->sh_size);
|
|
pHdrToSwab->sh_link = SWAB_Elf32_Word(pHdrToSwab->sh_link);
|
|
pHdrToSwab->sh_info = SWAB_Elf32_Word(pHdrToSwab->sh_info);
|
|
pHdrToSwab->sh_addralign = SWAB_Elf32_Word(pHdrToSwab->sh_addralign);
|
|
pHdrToSwab->sh_addralign = SWAB_Elf32_Word(pHdrToSwab->sh_addralign);
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @brief byte swap the Elf32_Sym structure
|
|
*
|
|
* @returns N/A
|
|
*/
|
|
static void swabElfSym(Elf32_Sym *pHdrToSwab)
|
|
{
|
|
if (swabRequired == 0)
|
|
{
|
|
return; /* do nothing */
|
|
}
|
|
|
|
pHdrToSwab->st_name = SWAB_Elf32_Word(pHdrToSwab->st_name);
|
|
pHdrToSwab->st_value = SWAB_Elf32_Addr(pHdrToSwab->st_value);
|
|
pHdrToSwab->st_size = SWAB_Elf32_Word(pHdrToSwab->st_size);
|
|
pHdrToSwab->st_shndx = SWAB_Elf32_Half(pHdrToSwab->st_shndx);
|
|
}
|
|
|
|
/**
|
|
* @brief load the ELF header
|
|
*
|
|
* @param fd file descriptor of file from which to read
|
|
* @returns 0 on success, -1 on failure
|
|
*/
|
|
static int ehdrLoad(int fd)
|
|
{
|
|
unsigned ix = 0x12345678; /* used to auto-detect endian-ness */
|
|
size_t nBytes; /* number of bytes read from file */
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == -1) {
|
|
fprintf(stderr, "Unable to seek\n");
|
|
return -1;
|
|
}
|
|
|
|
nBytes = read(fd, &ehdr, sizeof(ehdr));
|
|
if (nBytes != sizeof(ehdr))
|
|
{
|
|
fprintf(stderr, "Failed to read ELF header\n");
|
|
return -1;
|
|
}
|
|
|
|
/* perform some rudimentary ELF file validation */
|
|
|
|
if (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0)
|
|
{
|
|
fprintf(stderr, "Input object module not ELF format\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 64-bit ELF module not supported (for now) */
|
|
|
|
if (ehdr.e_ident[EI_CLASS] != ELFCLASS32)
|
|
{
|
|
fprintf(stderr, "ELF64 class not supported\n");
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Dynamically determine the endianess of the host (in the absence of
|
|
* a compile time macro ala _BYTE_ORDER). The ELF structures will require
|
|
* byte swapping if the host and target have different byte ordering.
|
|
*/
|
|
|
|
if (((*(char*)&ix == 0x78) && (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)) ||
|
|
((*(char*)&ix == 0x12) && (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)))
|
|
{
|
|
swabRequired = 1;
|
|
DBG_PRINT("Swab required\n");
|
|
}
|
|
|
|
swabElfHdr(&ehdr); /* swap bytes (if required) */
|
|
|
|
/* debugging: dump some important ELF header fields */
|
|
|
|
DBG_PRINT("Elf header Magic = %s\n", ehdr.e_ident);
|
|
DBG_PRINT("Elf header e_type = %d\n", ehdr.e_type);
|
|
DBG_PRINT("Elf header e_shstrndx = %d\n", ehdr.e_shstrndx);
|
|
DBG_PRINT("Elf header e_shnum = %d\n", ehdr.e_shnum);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief load the section headers
|
|
* @param fd file descriptor of file from which to read
|
|
*
|
|
* @returns 0 on success, -1 on failure
|
|
*/
|
|
static int shdrsLoad(int fd)
|
|
{
|
|
size_t nBytes; /* number of bytes read from file */
|
|
unsigned ix; /* loop index */
|
|
|
|
shdr = malloc(ehdr.e_shnum * sizeof(Elf32_Shdr));
|
|
if (shdr == NULL)
|
|
{
|
|
fprintf(stderr, "No memory for section headers!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Seek to the start of the table of section headers */
|
|
if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1) {
|
|
fprintf(stderr, "Unable to seek\n");
|
|
return -1;
|
|
}
|
|
|
|
for (ix = 0; ix < ehdr.e_shnum; ix++)
|
|
{
|
|
nBytes = read(fd, &shdr[ix], sizeof(Elf32_Shdr));
|
|
if (nBytes != sizeof(Elf32_Shdr))
|
|
{
|
|
fprintf(stderr, "Unable to read entire section header (#%d)\n",
|
|
ix);
|
|
return -1;
|
|
}
|
|
|
|
swabElfSectionHdr(&shdr[ix]); /* swap bytes (if required) */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* symTblFind - search the section headers for the symbol table
|
|
*
|
|
* This routine searches the section headers for the symbol table. There is
|
|
* expected to be only one symbol table in the section headers.
|
|
*
|
|
* @param pSymTblOffset ptr to symbol table offset
|
|
* @param pSymTblSize ptr to symbol table size
|
|
* @returns 0 if found, -1 if not
|
|
*/
|
|
static int symTblFind(unsigned *pSymTblOffset, unsigned *pSymTblSize)
|
|
{
|
|
unsigned ix; /* loop index */
|
|
|
|
for (ix = 0; ix < ehdr.e_shnum; ++ix)
|
|
{
|
|
if (shdr[ix].sh_type == SHT_SYMTAB)
|
|
{
|
|
*pSymTblOffset = shdr[ix].sh_offset;
|
|
*pSymTblSize = shdr[ix].sh_size;
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "Object module missing symbol table!\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief search the section headers for the string table
|
|
*
|
|
* This routine searches the section headers for the string table associated
|
|
* with the symbol names.
|
|
*
|
|
* Typically, there are two string tables defined in the section headers. These
|
|
* are ".shstrtbl" and ".strtbl" for section header names and symbol names
|
|
* respectively. It has been observed with the DIAB compiler (but not with
|
|
* either the GCC nor ICC compilers) that the two tables may be mashed together
|
|
* into one. Consequently, the following algorithm is used to select the
|
|
* appropriate string table.
|
|
*
|
|
* 1. Assume that the first found string table is valid.
|
|
* 2. If another string table is found, use that only if its section header
|
|
* index does not match the index for ".shstrtbl" stored in the ELF header.
|
|
*
|
|
* @param pStrTblIx ptr to string table's index
|
|
* @returns 0 if found, -1 if not
|
|
*/
|
|
static int strTblFind(unsigned *pStrTblIx)
|
|
{
|
|
unsigned strTblIx = 0xffffffff;
|
|
unsigned ix;
|
|
|
|
for (ix = 0; ix < ehdr.e_shnum; ++ix)
|
|
{
|
|
if (shdr[ix].sh_type == SHT_STRTAB)
|
|
{
|
|
if ((strTblIx == 0xffffffff) ||
|
|
(ix != ehdr.e_shstrndx))
|
|
{
|
|
strTblIx = ix;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strTblIx == 0xffffffff)
|
|
{
|
|
fprintf(stderr, "Object module missing string table!\n");
|
|
return -1;
|
|
}
|
|
|
|
*pStrTblIx = strTblIx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief load the string table
|
|
*
|
|
* @param fd file descriptor of file from which to read
|
|
* @param strTblIx string table's index
|
|
* @param ppStringTable ptr to ptr to string table
|
|
* @returns 0 on success, -1 on failure
|
|
*/
|
|
static int strTblLoad(int fd, unsigned strTblIx, char **ppStringTable)
|
|
{
|
|
char * pTable;
|
|
int nBytes;
|
|
|
|
DBG_PRINT("Allocating %d bytes for string table\n",
|
|
shdr[strTblIx].sh_size);
|
|
|
|
pTable = malloc(shdr[strTblIx].sh_size);
|
|
if (pTable == NULL)
|
|
{
|
|
fprintf(stderr, "No memory for string table!");
|
|
return -1;
|
|
}
|
|
|
|
if (lseek(fd, shdr[strTblIx].sh_offset, SEEK_SET) == -1) {
|
|
fprintf(stderr, "Unable to seek\n");
|
|
return -1;
|
|
}
|
|
|
|
nBytes = read(fd, pTable, shdr[strTblIx].sh_size);
|
|
if (nBytes != shdr[strTblIx].sh_size)
|
|
{
|
|
free(pTable);
|
|
fprintf(stderr, "Unable to read entire string table!\n");
|
|
return -1;
|
|
}
|
|
|
|
*ppStringTable = pTable;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief dump the header preamble to the header file
|
|
*
|
|
* @param fd file pointer to which to write
|
|
* @parama filename name of the output file
|
|
* @returns N/A
|
|
*/
|
|
static void headerPreambleDump(FILE *fp, char *filename)
|
|
{
|
|
unsigned hash = 5381; /* hash value */
|
|
size_t ix; /* loop counter */
|
|
char fileNameHash[20]; /* '_HGUARD_' + 8 character hash + '\0' */
|
|
|
|
/* dump header file preamble1[] */
|
|
|
|
fprintf(fp, preamble1, filename, filename, filename);
|
|
|
|
/*
|
|
* Dump header file preamble2[]. Hash file name into something that
|
|
* is small enough to be a C macro name and does not have invalid
|
|
* characters for a macro name to use as a header guard. The result
|
|
* of the hash should be unique enough for our purposes.
|
|
*/
|
|
|
|
for (ix = 0; ix < sizeof(filename); ++ix)
|
|
{
|
|
hash = (hash * 33) + (unsigned int) filename[ix];
|
|
}
|
|
|
|
sprintf(fileNameHash, "_HGUARD_%08x", hash);
|
|
fprintf(fp, preamble2, fileNameHash, fileNameHash);
|
|
}
|
|
|
|
/**
|
|
* @brief dump the absolute symbols to the header file
|
|
*
|
|
* @param fd file descriptor of file from which to read
|
|
* @param fp file pointer to which to write
|
|
* @param symTblOffset symbol table offset
|
|
* @param symTblSize size of the symbol table
|
|
* @param pStringTable ptr to the string table
|
|
* @returns N/A
|
|
*/
|
|
static void headerAbsoluteSymbolsDump(int fd, FILE *fp, Elf32_Off symTblOffset,
|
|
Elf32_Word symTblSize, char *pStringTable)
|
|
{
|
|
Elf32_Sym aSym; /* absolute symbol */
|
|
unsigned ix; /* loop counter */
|
|
unsigned numSyms; /* number of symbols in the symbol table */
|
|
size_t nBytes;
|
|
|
|
/* context the symbol table: pick out absolute syms */
|
|
|
|
numSyms = symTblSize / sizeof(Elf32_Sym);
|
|
if (lseek(fd, symTblOffset, SEEK_SET) == -1) {
|
|
fprintf(stderr, "Unable to seek\n");
|
|
return;
|
|
}
|
|
|
|
for (ix = 0; ix < numSyms; ++ix)
|
|
{
|
|
/* read in a single symbol structure */
|
|
nBytes = read(fd, &aSym, sizeof(Elf32_Sym));
|
|
|
|
if (nBytes) {
|
|
swabElfSym(&aSym); /* swap bytes (if required) */
|
|
}
|
|
|
|
/*
|
|
* Only generate definitions for global absolute symbols
|
|
* of the form *_OFFSET
|
|
*/
|
|
|
|
if ((aSym.st_shndx == SHN_ABS) &&
|
|
(ELF_ST_BIND(aSym.st_info) == STB_GLOBAL))
|
|
{
|
|
if ((strstr(&pStringTable[aSym.st_name],
|
|
STRUCT_OFF_SUFFIX) != NULL) ||
|
|
(strstr(&pStringTable[aSym.st_name],
|
|
STRUCT_SIZ_SUFFIX) != NULL))
|
|
{
|
|
fprintf(fp, "#define\t%s\t0x%X\n",
|
|
&pStringTable[aSym.st_name], aSym.st_value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief dump the header postscript to the header file
|
|
* @param fp file pointer to which to write
|
|
* @returns N/A
|
|
*/
|
|
static void headerPostscriptDump(FILE *fp)
|
|
{
|
|
fputs(postscript, fp);
|
|
}
|
|
|
|
/**
|
|
* @brief entry point for the genOffsetHeader utility
|
|
*
|
|
* usage: $ genOffsetHeader -i <objectModule> -o <outputHeaderName>
|
|
*
|
|
* @returns 0 on success, 1 on failure
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
Elf32_Off symTblOffset = 0;
|
|
Elf32_Word symTblSize; /* in bytes */
|
|
char * pStringTable = NULL;
|
|
char * inFileName = NULL;
|
|
char * outFileName = NULL;
|
|
int option;
|
|
int inFd = -1;
|
|
FILE * outFile = NULL;
|
|
unsigned strTblIx;
|
|
|
|
/* argument parsing */
|
|
|
|
if (argc != 5)
|
|
{
|
|
fprintf(stderr, usage, argv[0]);
|
|
goto errorReturn;
|
|
}
|
|
|
|
while ((option = getopt(argc, argv, "i:o:")) != -1)
|
|
{
|
|
switch (option)
|
|
{
|
|
case 'i':
|
|
inFileName = optarg;
|
|
break;
|
|
case 'o':
|
|
outFileName = optarg;
|
|
break;
|
|
default:
|
|
fprintf(stderr, usage, argv[0]);
|
|
goto errorReturn;
|
|
}
|
|
}
|
|
|
|
/* open input object ELF module and output header file */
|
|
|
|
inFd = open(inFileName, OPEN_FLAGS);
|
|
|
|
if (inFd == -1)
|
|
{
|
|
fprintf(stderr, "Cannot open input object module");
|
|
goto errorReturn;
|
|
}
|
|
|
|
outFile = fopen(outFileName, "w");
|
|
|
|
if (outFile == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot open output header file");
|
|
goto errorReturn;
|
|
}
|
|
|
|
/*
|
|
* In the following order, attempt to ...
|
|
* 1. Load the ELF header
|
|
* 2. Load the section headers
|
|
* 3. Find the symbol table
|
|
* 4. Find the string table
|
|
* 5. Load the string table
|
|
* Bail if any of those steps fail.
|
|
*/
|
|
|
|
if ((ehdrLoad(inFd) != 0) ||
|
|
(shdrsLoad(inFd) != 0) ||
|
|
(symTblFind(&symTblOffset, &symTblSize) != 0) ||
|
|
(strTblFind(&strTblIx) != 0) ||
|
|
(strTblLoad(inFd, strTblIx, &pStringTable) != 0))
|
|
{
|
|
goto errorReturn;
|
|
}
|
|
|
|
|
|
/*
|
|
* Dump the following to the header file ...
|
|
* 1. Header file preamble
|
|
* 2. Absolute symbols
|
|
* 3. Header file postscript
|
|
*/
|
|
|
|
headerPreambleDump(outFile, outFileName);
|
|
headerAbsoluteSymbolsDump(inFd, outFile,
|
|
symTblOffset, symTblSize, pStringTable);
|
|
headerPostscriptDump(outFile);
|
|
|
|
/* done: cleanup */
|
|
|
|
close(inFd);
|
|
fclose(outFile);
|
|
free(shdr);
|
|
free(pStringTable);
|
|
|
|
return 0;
|
|
|
|
errorReturn:
|
|
if (inFd != -1)
|
|
{
|
|
close(inFd);
|
|
}
|
|
|
|
if (outFile != NULL)
|
|
{
|
|
fclose(outFile);
|
|
}
|
|
|
|
if (shdr != NULL)
|
|
{
|
|
free(shdr);
|
|
}
|
|
|
|
if (pStringTable != NULL)
|
|
{
|
|
free(pStringTable);
|
|
}
|
|
|
|
return 1;
|
|
}
|