OpenCores
URL https://opencores.org/ocsvn/forwardcom/forwardcom/trunk

Subversion Repositories forwardcom

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /forwardcom/bintools
    from Rev 59 to Rev 60
    Reverse comparison

Rev 59 → Rev 60

/library.cpp
0,0 → 1,794
/**************************** library.cpp **********************************
* Author: Agner Fog
* date created: 2017-11-08
* Last modified: 2018-03-30
* Version: 1.10
* Project: Binary tools for ForwardCom instruction set
* Description:
* This module contains code for reading, writing and manipulating function
* libraries (archives) of the UNIX type
*
* Copyright 2017-2020 GNU General Public License http://www.gnu.org/licenses
*****************************************************************************/
 
#include "stdafx.h"
 
CLibrary::CLibrary() {
// Constructor
longNames = 0;
alignBy = 8;
}
 
void CLibrary::go() {
// Do to library whatever the command line says
 
// check libraryOptions and whether an output file is specified
if (cmd.fileOptions & CMDL_FILE_OUTPUT) {
// Output is a library file
if ((cmd.outputFile == 0) && !(cmd.libraryOptions & CMDL_LIBRARY_ADDMEMBER)) {
err.submit(2503); // Output file name missing
return;
}
// Check extension
const char * outputFile = cmd.getFilename(cmd.outputFile);
uint32_t len = (uint32_t)strlen(outputFile);
if (len < 4 || strncasecmp_(outputFile + len - 3, ".li", 3) != 0) {
err.submit(1101, outputFile); // Warning wrong extension
}
}
if (err.number()) return;
 
// strip path from member names and search for duplicates
checkActionList();
if (err.number()) return;
 
if (dataSize()) {
// library exists
// check file type
if (getFileType() != FILETYPE_LIBRARY) {
err.submit(ERR_LIBRARY_FILE_TYPE, getFileFormatName(getFileType()));
return;
}
// make list of member names and offsets
makeMemberList();
if (err.number()) return;
}
 
if (cmd.libraryOptions == CMDL_LIBRARY_LISTMEMBERS) {
// list members. do nothing else
listMembers();
return;
}
 
// do all commands
runActionList();
if (err.number()) return;
 
// collect contents of new library
generateNewLibraryBody();
if (err.number()) return;
 
// Make library header, symbol table, longnames record, data
makeBinaryFile();
if (err.number()) return;
 
if (cmd.fileOptions & CMDL_FILE_OUTPUT) {
// Write output file
const char * outputFileName = cmd.getFilename(cmd.outputFile);
outFile.write(outputFileName);
}
}
 
// Check action list for errors
void CLibrary::checkActionList() {
uint32_t numCommands = cmd.lcommands.numEntries(); // number of commands on command line
uint32_t i, j; // loop counters
const char * fname; // name of object file
for (i = 0; i < numCommands; i++) { // loop through commands
if (cmd.lcommands[i].filename) {
fname = cmd.getFilename(cmd.lcommands[i].filename);
// strip path from name
const char * fname2 = removePath(fname);
if (fname2 != fname) {
// filename contains path. strip path
cmd.lcommands[i].value = cmd.fileNameBuffer.pushString(fname2);
}
else {
// filename does not contain path. membername is same as filename
cmd.lcommands[i].value = cmd.lcommands[i].filename;
}
 
// search for duplicate names
for (j = 0; j < i; j++) {
if (strcmp(fname, cmd.getFilename((uint32_t)cmd.lcommands[j].value)) == 0) {
// duplicate name found
if (cmd.lcommands[j].command == CMDL_LIBRARY_DELETEMEMBER && cmd.lcommands[i].command == CMDL_LIBRARY_ADDMEMBER) {
// delete member before adding new member with same name
cmd.lcommands[j].command = 0; // ignore delete
}
else { // duplicate name not allowed
err.submit(ERR_DUPLICATE_NAME_COMMANDL, fname); break;
}
}
}
}
}
}
 
// Make list of library member names
void CLibrary::makeMemberList() {
// Unix style library. First header at offset 8 = strlen(archiveSignature)
uint32_t offset = 8;
SUNIXLibraryHeader * header; // member header
uint32_t memberSize; // size of member
const char * memberName = 0; // name of member
longNames = 0; // no longnames record
const char * namebuffer = (const char *)cmd.fileNameBuffer.buf(); // filenames buffer
 
// Loop through library headers.
while (offset + sizeof(SUNIXLibraryHeader) < dataSize()) {
// Find header
header = &get<SUNIXLibraryHeader>(offset);
// Size of member
memberSize = atoi(header->fileSize);
if (int32_t(memberSize) < 0 || memberSize + offset + sizeof(SUNIXLibraryHeader) > dataSize()) {
err.submit(ERR_LIBRARY_FILE_CORRUPT); // Points outside file
return;
}
// member name
memberName = header->name;
if (strncmp(memberName, "// ", 3) == 0) {
// This is the long names member. Remember its position
longNames = offset + sizeof(SUNIXLibraryHeader);
longNamesSize = memberSize;
}
else if (strncasecmp_(memberName, "/SYMDEF SORTED/", 15) == 0) {
// This is the symbol list
//symDef = offset;
}
else {
// Normal member. get name
if (memberName[0] == '/' && memberName[1] >= '0' && memberName[1] <= '9' && longNames) {
// name contains index into longNames record
uint32_t nameIndex = atoi(memberName+1);
if (nameIndex < longNamesSize) {
memberName = (char*)buf() + longNames + nameIndex;
}
else {
memberName = "NoName!";
}
}
else {
// ordinary short name
// name is terminated by '/'. Replace termination char by 0
for (int i = 15; i >= 0; i--) {
if (header->name[i] == '/') {
header->name[i] = 0; break;
}
}
// Terminate name with max length by overwriting date field, which we are not using
header->date[0] = 0;
memberName = header->name;
}
// check if name is valid
if (memberName[0] == 0) memberName = "NoName!";
// store member name and offset
SLibMember libmem;
libmem.name = cmd.fileNameBuffer.pushString(memberName);
libmem.oldOffset = offset;
libmem.newOffset = 0;
libmem.size = memberSize;
libmem.action = CMDL_LIBRARY_PRESERVEMEMBER;
members.push(libmem);
}
// get next offset
offset += sizeof(SUNIXLibraryHeader) + memberSize;
// Round up for alignment. Nominal alignment = 8, max alignment = 256
while ((offset & 0xFF)
&& offset + sizeof(SUNIXLibraryHeader) < dataSize()
&& get<uint8_t>(offset) <= ' ') offset++;
//offset = (offset + alignBy - 1) & ~ alignBy;
}
// sort member list alphabetically
members.sort();
// check for duplicate names
for (uint32_t j = 1; j < members.numEntries(); j++) {
if (strcmp(namebuffer + members[j-1].name, namebuffer + members[j].name) == 0) {
err.submit(ERR_DUPLICATE_NAME_IN_LIB, namebuffer + members[j].name);
members[j].action = CMDL_LIBRARY_DELETEMEMBER; // delete duplicate member
}
}
}
 
// Find a module. Return offset
uint32_t CLibrary::findMember(uint32_t name) {
// make list of members
if (members.numEntries() == 0) makeMemberList();
// make record to search for
SLibMember memberSearch;
memberSearch.name = name;
int32_t i = members.findFirst(memberSearch);
if (i < 0) return 0; // not found
return members[i].oldOffset; // return offset
}
 
 
// Run through commands from command line
void CLibrary::runActionList() {
uint32_t i; // loop counter
if (cmd.verbose) {
// Tell name of library
uint32_t name = cmd.inputFile;
if (name == 0) name = cmd.outputFile;
if (dataSize() == 0) {
printf("\nBuilding ForwardCom library %s", cmd.getFilename(name));
}
else if (cmd.libraryOptions & (CMDL_LIBRARY_ADDMEMBER | CMDL_LIBRARY_DELETEMEMBER)) {
printf("\nModifying ForwardCom library %s", cmd.getFilename(name));
}
else {
printf("\nForwardCom library %s", cmd.getFilename(name));
}
}
// loop through commands
for (i = 0; i < cmd.lcommands.numEntries(); i++) {
uint32_t command = cmd.lcommands[i].command;
switch (command) {
case CMDL_LIBRARY_ADDMEMBER: // add object file to library
addMember(cmd.lcommands[i].filename, (uint32_t)cmd.lcommands[i].value);
break;
case CMDL_LIBRARY_DELETEMEMBER: // delete object file to library
deleteMember((uint32_t)cmd.lcommands[i].value);
break;
case CMDL_LIBRARY_LISTMEMBERS: // list library members
listMembers();
break;
case CMDL_LIBRARY_EXTRACTMEM: // Extract specified object file(s) from library
extractMember(cmd.lcommands[i].filename, (uint32_t)cmd.lcommands[i].value);
break;
case CMDL_LIBRARY_EXTRACTALL: // Extract all object files from library
extractAllMembers();
break;
case 0:
break;
default:
err.submit(ERR_UNKNOWN_OPTION, "?"); // should not occur
}
}
}
 
// Add object file to library member list
void CLibrary::addMember(uint32_t filename, uint32_t membername) {
SLibMember libmem;
libmem.name = membername;
libmem.oldOffset = 0;
libmem.newOffset = filename; // store filename temporarily here
libmem.action = CMDL_LIBRARY_ADDMEMBER;
libmem.size = 0;
 
// replace existing member with same name
int32_t m = members.findFirst(libmem);
if (m >= 0) {
// existing member with same name found
members[m] = libmem;
members[m].action = CMDL_LIBRARY_DELETEMEMBER | CMDL_LIBRARY_ADDMEMBER;
if (cmd.verbose) {
printf("\n replacing member %s", cmd.getFilename(membername));
}
}
else {
if (cmd.verbose) {
printf("\n adding member %s", cmd.getFilename(membername));
}
members.addUnique(libmem); // add to list. keep alphabetical order
}
}
 
// Add delete member from library
void CLibrary::deleteMember(uint32_t membername) {
SLibMember libmem;
libmem.name = membername;
int32_t m = members.findFirst(libmem);
if (m < 0) {
err.submit(ERR_MEMBER_NOT_FOUND_DEL, cmd.getFilename(membername));
return;
}
members[m].action = CMDL_LIBRARY_DELETEMEMBER;
if (cmd.verbose) {
printf("\n deleting member %s", cmd.getFilename(membername));
}
}
 
// Extract member from library
void CLibrary::extractMember(uint32_t filename, uint32_t membername) {
// find member
SLibMember libmem;
libmem.name = membername;
int32_t m = members.findFirst(libmem);
if (m < 0) {
err.submit(ERR_MEMBER_NOT_FOUND_EXTRACT, cmd.getFilename(membername));
return;
}
uint32_t headerOffset = members[m].oldOffset;
//uint32_t memberSize = (uint32_t)atoi(header->fileSize);
uint32_t memberSize = members[m].size;
if (memberSize + headerOffset + sizeof(SUNIXLibraryHeader) > dataSize()) {
err.submit(ERR_LIBRARY_FILE_CORRUPT); // Points outside file
return;
}
// file name
if (filename == 0) filename = membername;
const char * filenm = cmd.getFilename(filename);
 
// Tell what we are doing
if (cmd.verbose) {
if (filename == membername) {
printf("\nExtracting file %s from library", filenm);
}
else {
printf("\nExtracting library member %s to file %s",
cmd.getFilename(membername), filenm);
}
}
// extract file
CFileBuffer memberbuf;
memberbuf.push(buf() + headerOffset + sizeof(SUNIXLibraryHeader), memberSize);
// write file
memberbuf.write(filenm);
}
 
// Extract all members from library
void CLibrary::extractAllMembers() {
uint32_t num = members.numEntries();
if (num == 0) {
err.submit(ERR_MEMBER_NOT_FOUND_EXTRACT, "");
}
for (uint32_t i = 0; i < num; i++) {
extractMember(members[i].name, members[i].name);
}
}
 
// List all library members
void CLibrary::listMembers() {
CDynamicArray<SSymbolEntry> symbolList; // symbol list
 
printf("\nMembers of library %s:", cmd.getFilename(cmd.inputFile));
uint32_t m, i; // loop counters
for (m = 0; m < members.numEntries(); m++) {
if (members[m].name == 0) continue; // has been deleted
// print member name
if (cmd.verbose < 2) {
printf("\n %s", cmd.getFilename(members[m].name));
}
else if (cmd.verbose >= 2) {
printf("\n %s export:", cmd.getFilename(members[m].name));
// print exported symbol names for this member
// clear buffers
memberBuffer.setSize(0); symbolNameBuffer.setSize(0); symbolList.setSize(0);
// put member into buffer in order to extract symbols
memberBuffer.push(buf() + members[m].oldOffset + (uint32_t)sizeof(SUNIXLibraryHeader), members[m].size);
// extract symbols from ELF file
memberBuffer.listSymbols(&symbolNameBuffer, &symbolList, m, 0, 1);
// sort alphabetically
symbolList.sort();
// list names
for (i = 0; i < symbolList.numEntries(); i++) {
printf("\n %s", symbolNameBuffer.getString(symbolList[i].name));
}
}
if (cmd.verbose >= 3) {
// print imported symbol names for this member
printf("\n import:");
// clear buffers
memberBuffer.setSize(0); symbolNameBuffer.setSize(0); symbolList.setSize(0);
// put member into buffer in order to extract symbols
memberBuffer.push(buf() + members[m].oldOffset + (uint32_t)sizeof(SUNIXLibraryHeader), members[m].size);
// extract symbols from ELF file
memberBuffer.listSymbols(&symbolNameBuffer, &symbolList, m, 0, 2);
// sort alphabetically
symbolList.sort();
// list names
for (i = 0; i < symbolList.numEntries(); i++) {
printf("\n %s", symbolNameBuffer.getString(symbolList[i].name));
}
}
}
}
 
 
// Generate data contents of new library from old one with possible additions and deletions
void CLibrary::generateNewLibraryBody() {
uint32_t m; // member number
SUNIXLibraryHeader header; // new member header
 
// loop through member list
for (m = 0; m < members.numEntries(); m++) {
if (members[m].name && members[m].action != 0 && members[m].action != CMDL_LIBRARY_DELETEMEMBER) {
if (members[m].oldOffset && members[m].action == CMDL_LIBRARY_PRESERVEMEMBER) {
// preserve existing member
SUNIXLibraryHeader * phead = &get<SUNIXLibraryHeader>(members[m].oldOffset);
uint32_t size = atoi(phead->fileSize);
if (sizeof(SUNIXLibraryHeader) + size + members[m].oldOffset > dataSize()) {
err.submit(ERR_LIBRARY_FILE_CORRUPT); return;
}
// put header and file into buffer
members[m].newOffset = dataBuffer.push(buf() + members[m].oldOffset, size + (uint32_t)sizeof(SUNIXLibraryHeader));
}
else if (members[m].action & CMDL_LIBRARY_ADDMEMBER) {
// get member from file
// filename is temporarily stored in newOffset
if (members[m].newOffset == 0 || (members[m].newOffset >= cmd.fileNameBuffer.dataSize())) {
members[m].newOffset = members[m].name;
}
const char * filename = cmd.getFilename(members[m].newOffset);
memberBuffer.setSize(0); // clear memberBuffer first
memberBuffer.read(filename);
if (err.number()) return;
// check file type
if (memberBuffer.getFileType() != FILETYPE_FWC) {
err.submit(ERR_LIBRARY_MEMBER_TYPE, filename, getFileFormatName(memberBuffer.getFileType()));
return;
}
// remove path from file name
const char * membername = removePath(filename);
// make member header
memset(&header, ' ', sizeof(header));
// date
sprintf(header.date, "%llu ", (unsigned long long)time(0));
// User and group id
header.userID[0] = '0';
header.groupID[0] = '0';
// File mode
memcpy(header.fileMode, "100666", 6);
// Name
uint32_t namelength = (uint32_t)strlen(membername);
if (namelength < 16) {
memcpy(header.name, membername, namelength);
header.name[namelength] = '/'; // terminate with '/'
}
else {
// cannot save name now, wait until longnames record is made
members[m].name = cmd.fileNameBuffer.pushString(membername);
}
// Size
sprintf(header.fileSize, "%u", memberBuffer.dataSize());
members[m].size = memberBuffer.dataSize();
// End
header.headerEnd[0] = '`'; header.headerEnd[1] = '\n';
// remove terminating zeroes left by sprintf
char * p = (char *)&header;
for (uint32_t i = 0; i < sizeof(header); i++) {
if (p[i] == 0) p[i] = ' ';
}
// put header and file into buffer
members[m].newOffset = dataBuffer.push(&header, (uint32_t)sizeof(header));
dataBuffer.push(memberBuffer.buf(), memberBuffer.dataSize());
}
}
// align next member
dataBuffer.align(alignBy);
}
}
 
// Make library header, symbol table, longnames record, data
void CLibrary::makeBinaryFile() {
// make signature
outFile.push(archiveSignature, 8);
 
// make symbol list and longnames record
CMemoryBuffer longNamesBuf; // list of long member names
CDynamicArray<SSymbolEntry> symbolList; // symbol list, part of symdefSorted
uint32_t m; // member number
uint32_t i; // loop counter
 
// loop through members to generate longnames and symbol list
for (m = 0; m < members.numEntries(); m++) {
if (members[m].action & (CMDL_LIBRARY_PRESERVEMEMBER | CMDL_LIBRARY_ADDMEMBER)) {
// get member header
SUNIXLibraryHeader * phead = &dataBuffer.get<SUNIXLibraryHeader>(members[m].newOffset);
// member name
const char * name = cmd.getFilename(members[m].name);
if (strlen(name) > 15) {
// put name in longnames record
uint32_t longnameos = longNamesBuf.pushString(name);
sprintf(phead->name, "/%u", longnameos);
phead->name[strlen(phead->name)] = ' '; // remove terminating zero
}
// put member into buffer in order to extract symbols
memberBuffer.setSize(0);
memberBuffer.push(dataBuffer.buf() + members[m].newOffset + (uint32_t)sizeof(SUNIXLibraryHeader), members[m].size);
// extract public symbols from ELF file
memberBuffer.listSymbols(&symbolNameBuffer, &symbolList, m, 0, 1);
}
}
 
// sort symbol list and check for duplicate symbol names
checkDuplicateSymbols(symbolList);
 
// calculate size of symbol list
uint32_t symbolListSize = (uint32_t)sizeof(SUNIXLibraryHeader) + symbolList.numEntries()*8 + 8 + symbolNameBuffer.dataSize();
symbolListSize = (symbolListSize + alignBy - 1) & - alignBy; // align
// calculate size of longnames record
uint32_t longnamesSize = 0;
if (longNamesBuf.dataSize() > 1) { // longnames record needed
longnamesSize = sizeof(SUNIXLibraryHeader) + longNamesBuf.dataSize();
longnamesSize = (longnamesSize + alignBy - 1) & - alignBy; // align
}
// offset to first normal member
uint32_t firstMemberOffset = 8 + symbolListSize + longnamesSize;
 
// make Mach-O style symbol list
// put member addresses into symbol list
for (i = 0; i < symbolList.numEntries(); i++) {
m = symbolList[i].member;
if (m < members.numEntries()) {
symbolList[i].member = members[m].newOffset + firstMemberOffset;
}
else symbolList[i].member = 0; // should not occur
}
// make header
SUNIXLibraryHeader header;
memset(&header, ' ', sizeof(header));
memcpy(header.name, "/SYMDEF SORTED/", 15);
sprintf(header.date, "%llu ", (unsigned long long)time(0));
header.userID[0] = '0';
header.groupID[0] = '0';
memcpy(header.fileMode, "100666", 6);
sprintf(header.fileSize, "%u", symbolListSize - (uint32_t)sizeof(SUNIXLibraryHeader));
header.headerEnd[0] = '`'; header.headerEnd[1] = '\n';
// remove terminating zeroes
char * p = (char*)&header;
for (i = 0; i < sizeof(header); i++) {
if (p[i] == 0) p[i] = ' ';
}
// save header
outFile.push(&header, (uint32_t)sizeof(header));
uint32_t n = symbolList.numEntries()*8; // length of list
outFile.push(&n, 4);
// symbol list
for (i = 0; i < symbolList.numEntries(); i++) {
outFile.push(&symbolList[i].name, 4);
outFile.push(&symbolList[i].member, 4);
}
// length of string table
n = symbolNameBuffer.dataSize();
outFile.push(&n, 4);
// string table
outFile.push(symbolNameBuffer.buf(), n);
// align
outFile.align(alignBy);
 
// Make longnames record if needed
if (longnamesSize) {
memcpy(header.name, "// ", 16);
sprintf(header.fileSize, "%u", longNamesBuf.dataSize());
header.fileSize[strlen(header.fileSize)] = ' '; // remove terminating zero
outFile.push(&header, (uint32_t)sizeof(header));
outFile.push(longNamesBuf.buf(), longNamesBuf.dataSize());
outFile.align(alignBy);
}
 
// Insert all regular members
outFile.push(dataBuffer.buf(), dataBuffer.dataSize());
}
 
// Check if symbollist contains duplicate names
void CLibrary::checkDuplicateSymbols(CDynamicArray<SSymbolEntry> & symbolList) {
uint32_t i, j; // loop counters
 
// sort symbol list
symbolList.sort();
 
// check symbol list for duplicates
for (i = 1; i < symbolList.numEntries(); i++) {
if (symbolList[i-1] == symbolList[i] && !(symbolList[i-1].st_bind & STB_WEAK) && !(symbolList[i].st_bind & STB_WEAK)) {
// make a list of modules containing this symbol name
CMemoryBuffer moduleNames;
j = i - 1;
while (j < symbolList.numEntries() && symbolList[j] == symbolList[i]) {
if (j >= i) moduleNames.push(", ", 2);
uint32_t m = symbolList[j].member;
const char * mname = "?";
if (m < members.numEntries()) {
mname = cmd.getFilename(members[m].name);
}
moduleNames.push(mname, (uint32_t)strlen(mname));
j++;
}
moduleNames.pushString("");
const char * symbolname = symbolNameBuffer.getString(symbolList[i].name);
err.submit(ERR_DUPLICATE_SYMBOL_IN_LIB, symbolname, (char*)moduleNames.buf());
i = j - 1;
}
}
}
 
// get name of a library member
const char * CLibrary::getMemberName(uint32_t memberOffset) {
if (memberOffset >= dataSize()) return "unknown?";
char * namebuf = (char *)cmd.fileNameBuffer.buf();
SUNIXLibraryHeader * phead = (SUNIXLibraryHeader *)(buf() + memberOffset);
if (phead->name[0] == '/') {
// long name
uint32_t namei = atoi(phead->name+1);
if (longNames == 0) findLongNames();
// offset into longNames
uint32_t os = longNames + namei;
if (longNames == 0 || namei >= longNamesSize) return "unknown?";
return (char*)buf() + os;
}
// short name. replace terminating '/' by zero
uint32_t nm = cmd.fileNameBuffer.push(phead->name, 16);
namebuf += nm;
for (int i = 0; i < 16; i++) {
if (namebuf[i] == '/') namebuf[i] = 0;
}
namebuf[15] = 0; // make sure string ends even if '/' is missing
return namebuf;
}
 
// get size of a library member
uint32_t CLibrary::getMemberSize(uint32_t memberOffset) {
if (memberOffset >= dataSize()) return 0;
SUNIXLibraryHeader * phead = (SUNIXLibraryHeader *)(buf() + memberOffset);
uint32_t size = atoi(phead->fileSize);
return size;
}
 
// Find longNames record
void CLibrary::findLongNames() {
// find longNames record
uint32_t offset = 8;
SUNIXLibraryHeader * header;
uint32_t memberSize;
// Loop through library headers.
while (offset + sizeof(SUNIXLibraryHeader) < dataSize()) {
// Find header
header = &get<SUNIXLibraryHeader>(offset);
// Size of member
memberSize = atoi(header->fileSize);
if (int32_t(memberSize) < 0 || memberSize + offset + sizeof(SUNIXLibraryHeader) > dataSize()) {
err.submit(ERR_LIBRARY_FILE_CORRUPT); // Points outside file
return;
}
// member name
if (strncmp(header->name, "// ", 3) == 0) {
// This is the long names member. Remember its position
longNames = offset + sizeof(SUNIXLibraryHeader);
longNamesSize = memberSize;
return;
}
// get next offset
offset += sizeof(SUNIXLibraryHeader) + memberSize;
 
// Round up for alignment. Nominal alignment = 4, max alignment = 256
while ((offset & 0xFF)
&& offset + sizeof(SUNIXLibraryHeader) < dataSize()
&& get<uint8_t>(offset) <= ' ') offset++;
}
}
 
 
// Find exported symbol in library
// The return value is a file offset to the library member containing the symbol,
// or zero if not found
uint32_t CLibrary::findSymbol(const char * name) {
uint32_t memberSize;
uint32_t offset = 8;
SUNIXLibraryHeader * symdefHead = (SUNIXLibraryHeader *)(buf() + offset);
// expect symbol table as first record
while (strncasecmp_(symdefHead->name, "/SYMDEF SORTED/", 15) != 0) {
// not found. search whole library
memberSize = atoi(symdefHead->fileSize);
offset += memberSize + (uint32_t)sizeof(SUNIXLibraryHeader);
if (offset + (uint32_t)sizeof(SUNIXLibraryHeader) >= dataSize()) {
err.submit(ERR_NO_SYMTAB_IN_LIB); // library has no correct symbol table
return 0;
}
symdefHead = (SUNIXLibraryHeader *)(buf() + offset);
}
memberSize = atoi(symdefHead->fileSize);
// pointer to start of list
offset += (uint32_t)sizeof(SUNIXLibraryHeader);
uint32_t * listp = (uint32_t *)(buf() + offset);
uint32_t symlistlen = listp[0]; // length of symbol list
// string table
char * stringtab = (char *)(buf() + offset + symlistlen + 8);
// string table length
uint32_t stringtablen = *(uint32_t *)(stringtab-4);
// check integrity
if ((uint64_t)symlistlen + stringtablen + 8 > memberSize) {
err.submit(ERR_ELF_STRING_TABLE); return 0;
}
// binary search for name
uint32_t a = 0; // start of search interval
uint32_t b = symlistlen >> 3; // number of symbols
uint32_t c = 0; // middle of search interval
uint32_t nameindex; // index into string table
while (a < b) { // binary search loop:
c = (a + b) / 2;
nameindex = listp[1+2*c]; // index to name of symbol number c
if (nameindex >= stringtablen) { // check integrity
err.submit(ERR_ELF_STRING_TABLE); return 0;
}
if (strcmp(stringtab + nameindex, name) < 0) { // compare strings
a = c + 1;
}
else {
b = c;
}
}
nameindex = listp[1+2*a]; // index to name of symbol
if (a == symlistlen >> 3 || strcmp(stringtab + nameindex, name)) {
return 0; // not found
}
uint32_t memberIndex = listp[2+2*a]; // index to member containing symbol
if (memberIndex + (uint32_t)sizeof(SUNIXLibraryHeader) > dataSize()) {
err.submit(ERR_LIBRARY_FILE_CORRUPT); // out of range
return 0;
}
return memberIndex;
}
 
// check if this is a ForwardCom library
bool CLibrary::isForwardCom() {
uint32_t offset = 8;
SUNIXLibraryHeader * symdefHead = (SUNIXLibraryHeader *)(buf() + offset);
// expect symbol table as first record
return (strncasecmp_(symdefHead->name, "/SYMDEF SORTED/", 15) == 0);
}
 
 
// remove path from file name
const char * removePath(const char * filename) {
int p;
const char pathsep1 = '/'; // separator in file path
#if defined (_WIN32) || defined (__WINDOWS__)
const char pathsep2 = '\\', pathsep3 = ':'; // additional separators in Windows
#else
const char pathsep2 = pathsep1, pathsep3 = pathsep1;
#endif
// find last '/' or other path separator in object file name
for (p = (int)strlen(filename) - 1; p >= 0; p--) {
if (filename[p] == pathsep1 || filename[p] == pathsep2 || filename[p] == pathsep3) break;
}
if (p >= 0) {
// filename contains path. strip path
filename += p + 1;
}
if (filename[0] == 0) filename = "unknown?";
return filename;
}
 
// make library from CELF modules during relinking
void CLibrary::addELF(CELF & elf) {
SLibMember member; // entry into members list
SUNIXLibraryHeader header; // new member header
zeroAllMembers(member);
zeroAllMembers(header);
member.name = elf.moduleName;
member.action = CMDL_LIBRARY_ADDMEMBER;
member.size = elf.dataSize();
sprintf(header.fileSize, "%u", elf.dataSize());
const char * membername = cmd.getFilename(elf.moduleName);
uint32_t namelength = (uint32_t)strlen(membername);
if (namelength < 16) {
memcpy(header.name, membername, namelength);
header.name[namelength] = '/'; // terminate with '/'
}
// put header and file into buffer
member.newOffset = dataBuffer.push(&header, (uint32_t)sizeof(header));
dataBuffer.push(elf.buf(), elf.dataSize());
members.push(member);
}
 
// make a library for internal use during relinking
void CLibrary::makeInternalLibrary() {
makeBinaryFile(); // make library file, but don't write to disk
*this << outFile; // transfer to own object as if it had been read from disk
members.setSize(0); // reset members list
makeMemberList(); // update internal list
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.