rickjr/bin/blockgen/source/symfile.cpp

231 lines
5 KiB
C++

//
// symfile.cpp
//
#include "symfile.h"
#include <stdio.h>
//------------------------------------------------------------------------------
// Static Helpers
static bool contains(char x, const char* pSeparators)
{
while (*pSeparators)
{
if (x == *pSeparators)
{
return true;
}
pSeparators++;
}
return false;
}
static std::vector<std::string> split(const std::string& s, const char* separators)
{
std::vector<std::string> output;
std::string::size_type prev_pos = 0, pos = 0;
for (int index = 0; index < s.length(); ++index)
{
pos = index;
// if the index is a separator
if (contains(s[index], separators))
{
// if we've skipped a token, collect it
if (prev_pos != index)
{
output.push_back(s.substr(prev_pos, index-prev_pos));
// skip white space here
while (index < s.length())
{
if (contains(s[index], separators))
{
++index;
}
else
{
prev_pos = index;
pos = index;
break;
}
}
}
else
{
prev_pos++;
}
}
}
output.push_back(s.substr(prev_pos, pos-prev_pos+1)); // Last word
return output;
}
// make this string lowercase
static void tolower(std::string& s)
{
for (int index = 0; index < s.length(); ++index)
{
s[index] = tolower( s[index] );
}
}
//------------------------------------------------------------------------------
SYMFile::SYMFile( std::string filepath )
: m_filepath( filepath )
{
FILE* pFile = nullptr;
errno_t err = fopen_s(&pFile, filepath.c_str(), "rb");
if (0==err)
{
fseek(pFile, 0, SEEK_END);
size_t length = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
printf("\n// SYMFile %s - %lld bytes\n", filepath.c_str(), length);
printf("// Reading %s\n", filepath.c_str());
printf("//\n");
printf("// This file generated by blockgen.exe\n");
printf("//\n");
printf("//\n");
u8* pData = new u8[ length ];
fread(pData, sizeof(u8), length / sizeof(u8), pFile);
// Now we have a buffer, with the whole SYM File
// Read in the Sections
{
MemoryStream memStream(pData, length);
while (memStream.NumBytesAvailable())
{
std::string lineData = memStream.ReadLine();
// symbols are case sensitive
// we care about the first 32 bit value in hex, and the last value on the line, the symbol
std::vector<std::string> tokens = split(lineData, " \t");
if (tokens.size() >= 3)
{
if (IsHexAddress(tokens[0]))
{
// We're only interested in lines that start with a hex address
std::string sym_name = tokens[ tokens.size() - 1 ];
u32 address = strtoul(tokens[0].c_str(), nullptr, 16);
//printf("address = %08x\n", address);
if (0 != (address >> 24))
{
printf("#define %s_BLOCK %d\n", sym_name.c_str(), address>>24);
}
else if (0 != (address & 0xFF0000))
{
printf("#define %s_high %d\n", sym_name.c_str(), (address>>16) & 0xFF);
printf("#define %s_BLOCK %d\n", sym_name.c_str(), ((address&0xFFFFFF) / 0x2000));
}
}
}
}
}
delete[] pData;
fclose(pFile);
printf("\n// Read Completed\n");
}
else
{
printf("// SYMFile could not open %s\n", filepath.c_str());
printf("//\n");
printf("Feed in a symbol dump file, and I will print out a header file\n");
printf("Capture my output with a pipe.\n");
printf("\nGenerate a .sym file like this:\n");
printf("\nllvm-objdump --syms <program>.elf > program.sym\n");
}
}
//------------------------------------------------------------------------------
SYMFile::~SYMFile()
{
}
//------------------------------------------------------------------------------
u32 SYMFile::GetAddress(std::string symbolName)
{
u32 result_address = 0;
// If the address is in there, return it
// First remove trailing spaces from the sectionName
const size_t strEnd = symbolName.find_last_not_of(" ");
if (strEnd != std::string::npos)
{
if ((strEnd+1) != symbolName.length())
{
symbolName.resize(strEnd+1);
}
}
// Make sure not case sensitive
tolower(symbolName);
for (int labelIndex = 0; labelIndex < m_symbols.size(); ++labelIndex)
{
if (symbolName == m_symbols[labelIndex])
{
result_address = m_addresses[labelIndex];
break;
}
}
return result_address;
}
//------------------------------------------------------------------------------
bool SYMFile::IsHexAddress(const std::string& address)
{
if (8 == address.size())
{
for (int idx = 0; idx < 8; ++idx)
{
if ((address[idx] >= '0')&&(address[idx] <= '9'))
{
continue; // this is good
}
else if ((address[idx] >= 'a')&&(address[idx] <= 'f'))
{
continue; // this is good
}
else if ((address[idx] >= 'A')&&(address[idx] <= 'F'))
{
continue; // this is good
}
else
{
return false;
}
}
return true;
}
return false;
}
//------------------------------------------------------------------------------