mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
300
Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_bfd.cc
Normal file
300
Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_bfd.cc
Normal file
|
@ -0,0 +1,300 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* EXCLUDE: YES
|
||||
* NOTE: Links to GNU BFD library which is GPL 3
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "loadimage_bfd.hh"
|
||||
|
||||
int4 LoadImageBfd::bfdinit = 0; // Global initialization variable
|
||||
|
||||
LoadImageBfd::LoadImageBfd(const string &f,const string &t) : LoadImage(f)
|
||||
|
||||
{
|
||||
target = t;
|
||||
|
||||
if (bfdinit == 0) {
|
||||
bfdinit = 1;
|
||||
bfd_init();
|
||||
}
|
||||
thebfd = (bfd *)0;
|
||||
spaceid = (AddrSpace *)0;
|
||||
symbol_table = (asymbol **)0;
|
||||
|
||||
bufsize = 512; // Default buffer size
|
||||
bufoffset = ~((uintb)0);
|
||||
buffer = new uint1[ bufsize ];
|
||||
}
|
||||
|
||||
LoadImageBfd::~LoadImageBfd(void)
|
||||
|
||||
{
|
||||
if (symbol_table != (asymbol **)0)
|
||||
delete [] symbol_table;
|
||||
if (thebfd != (bfd *) 0)
|
||||
close();
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
string LoadImageBfd::getArchType(void) const
|
||||
|
||||
{
|
||||
string type;
|
||||
string targ;
|
||||
type = bfd_printable_name(thebfd);
|
||||
type += ':';
|
||||
targ = thebfd->xvec->name;
|
||||
type += targ;
|
||||
return type;
|
||||
}
|
||||
|
||||
void LoadImageBfd::adjustVma(long adjust)
|
||||
|
||||
{
|
||||
asection *s;
|
||||
adjust = AddrSpace::addressToByte(adjust,spaceid->getWordSize());
|
||||
for(s=thebfd->sections;s!=(asection *)NULL;s = s->next) {
|
||||
s->vma += adjust;
|
||||
s->lma += adjust;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadImageBfd::open(void)
|
||||
|
||||
{
|
||||
if (thebfd != (bfd *)0) throw LowlevelError("BFD library did not initialize");
|
||||
thebfd = bfd_openr(filename.c_str(),target.c_str());
|
||||
if (thebfd == (bfd *)0) {
|
||||
string errmsg="Unable to open image file: ";
|
||||
errmsg += filename;
|
||||
throw LowlevelError(errmsg);
|
||||
}
|
||||
if (!bfd_check_format( thebfd, bfd_object)) {
|
||||
string errmsg="File: ";
|
||||
errmsg += filename;
|
||||
errmsg += " : not in recognized object file format";
|
||||
throw LowlevelError(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadImageBfd::close(void)
|
||||
|
||||
{
|
||||
bfd_close(thebfd);
|
||||
thebfd = (bfd *)0;
|
||||
}
|
||||
|
||||
asection *LoadImageBfd::findSection(uintb offset,uintb &secsize) const
|
||||
|
||||
{ // Return section containing offset, or closest greater section
|
||||
asection *p;
|
||||
uintb start,stop;
|
||||
|
||||
for(p = thebfd->sections; p != (asection *)NULL; p = p->next) {
|
||||
start = p->vma;
|
||||
secsize = (p->size!=0) ? p->size : p->rawsize;
|
||||
stop = start + secsize;
|
||||
if ((offset>=start)&&(offset<stop))
|
||||
return p;
|
||||
}
|
||||
asection *champ = (asection *)0;
|
||||
for(p = thebfd->sections; p != (asection *)NULL; p = p->next) {
|
||||
if (p->vma > offset) {
|
||||
if (champ == (asection *)0)
|
||||
champ = p;
|
||||
else if (p->vma < champ->vma)
|
||||
champ = p;
|
||||
}
|
||||
}
|
||||
return champ;
|
||||
}
|
||||
|
||||
void LoadImageBfd::loadFill(uint1 *ptr,int4 size,const Address &addr)
|
||||
|
||||
{
|
||||
asection *p;
|
||||
uintb secsize;
|
||||
uintb curaddr,offset;
|
||||
bfd_size_type readsize;
|
||||
int4 cursize;
|
||||
|
||||
if (addr.getSpace() != spaceid)
|
||||
throw DataUnavailError("Trying to get loadimage bytes from space: "+addr.getSpace()->getName());
|
||||
curaddr = addr.getOffset();
|
||||
if ((curaddr>=bufoffset)&&(curaddr+size<bufoffset+bufsize)) { // Requested bytes were previously buffered
|
||||
uint1 *bufptr = buffer + (curaddr-bufoffset);
|
||||
memcpy(ptr,bufptr,size);
|
||||
return;
|
||||
}
|
||||
bufoffset = curaddr; // Load buffer with bytes from new address
|
||||
offset = 0;
|
||||
cursize = bufsize; // Read an entire buffer
|
||||
|
||||
while(cursize>0) {
|
||||
p = findSection(curaddr,secsize);
|
||||
if (p == (asection *)0) {
|
||||
if (offset==0) // Initial address not mapped
|
||||
break;
|
||||
memset(buffer+offset,0,cursize); // Fill out the rest of the buffer with 0
|
||||
memcpy(ptr,buffer,size);
|
||||
return;
|
||||
}
|
||||
if (p->vma > curaddr) { // No section matches
|
||||
if (offset==0) // Initial address not mapped
|
||||
break;
|
||||
readsize = p->vma - curaddr;
|
||||
if (readsize > cursize)
|
||||
readsize = cursize;
|
||||
memset(buffer+offset,0,readsize); // Fill in with zeroes to next section
|
||||
}
|
||||
else {
|
||||
readsize = cursize;
|
||||
if (curaddr+readsize>p->vma+secsize) // Adjust to biggest possible read
|
||||
readsize = (bfd_size_type)(p->vma+secsize-curaddr);
|
||||
bfd_get_section_contents(thebfd,p,buffer+offset,(file_ptr)(curaddr-p->vma),readsize);
|
||||
}
|
||||
offset += readsize;
|
||||
cursize -= readsize;
|
||||
curaddr += readsize;
|
||||
}
|
||||
if (cursize > 0) {
|
||||
ostringstream errmsg;
|
||||
errmsg << "Unable to load " << dec << cursize << " bytes at " << addr.getShortcut();
|
||||
addr.printRaw(errmsg);
|
||||
throw DataUnavailError(errmsg.str());
|
||||
}
|
||||
memcpy(ptr,buffer,size); // Copy requested bytes from the buffer
|
||||
}
|
||||
|
||||
void LoadImageBfd::advanceToNextSymbol(void) const
|
||||
|
||||
{
|
||||
while(cursymbol < number_of_symbols) {
|
||||
const asymbol *a = symbol_table[cursymbol];
|
||||
if ((a->flags & BSF_FUNCTION)!=0) {
|
||||
if (a->name != (const char *)0)
|
||||
return;
|
||||
}
|
||||
cursymbol += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadImageBfd::openSymbols(void) const
|
||||
|
||||
{
|
||||
long storage_needed;
|
||||
cursymbol = 0;
|
||||
if (symbol_table != (asymbol **)0) {
|
||||
advanceToNextSymbol();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(bfd_get_file_flags(thebfd) & HAS_SYMS)) { // There are no symbols
|
||||
number_of_symbols = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
storage_needed = bfd_get_symtab_upper_bound(thebfd);
|
||||
if (storage_needed <= 0) {
|
||||
number_of_symbols = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
symbol_table = (asymbol **) new uint1[storage_needed]; // Storage needed in bytes
|
||||
number_of_symbols = bfd_canonicalize_symtab(thebfd,symbol_table);
|
||||
if (number_of_symbols <= 0) {
|
||||
delete [] symbol_table;
|
||||
symbol_table = (asymbol **)0;
|
||||
number_of_symbols = 0;
|
||||
return;
|
||||
}
|
||||
advanceToNextSymbol();
|
||||
// sort(symbol_table,symbol_table+number_of_symbols,compare_symbols);
|
||||
}
|
||||
|
||||
bool LoadImageBfd::getNextSymbol(LoadImageFunc &record) const
|
||||
|
||||
{ // Get record for next symbol if it exists, otherwise return false
|
||||
if (cursymbol >= number_of_symbols) return false;
|
||||
|
||||
const asymbol *a = symbol_table[cursymbol];
|
||||
cursymbol += 1;
|
||||
advanceToNextSymbol();
|
||||
record.name = a->name;
|
||||
uintb val = bfd_asymbol_value(a);
|
||||
record.address = Address(spaceid,val);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoadImageBfd::openSectionInfo(void) const
|
||||
|
||||
{
|
||||
secinfoptr = thebfd->sections;
|
||||
}
|
||||
|
||||
void LoadImageBfd::closeSectionInfo(void) const
|
||||
|
||||
{
|
||||
secinfoptr = (asection *)0;
|
||||
}
|
||||
|
||||
bool LoadImageBfd::getNextSection(LoadImageSection &record) const
|
||||
|
||||
{
|
||||
if (secinfoptr == (asection *)0)
|
||||
return false;
|
||||
|
||||
record.address = Address(spaceid,secinfoptr->vma);
|
||||
record.size = (secinfoptr->size!=0) ? secinfoptr->size : secinfoptr->rawsize;
|
||||
record.flags = 0;
|
||||
if ((secinfoptr->flags & SEC_ALLOC)==0)
|
||||
record.flags |= LoadImageSection::unalloc;
|
||||
if ((secinfoptr->flags & SEC_LOAD)==0)
|
||||
record.flags |= LoadImageSection::noload;
|
||||
if ((secinfoptr->flags & SEC_READONLY)!=0)
|
||||
record.flags |= LoadImageSection::readonly;
|
||||
if ((secinfoptr->flags & SEC_CODE)!=0)
|
||||
record.flags |= LoadImageSection::code;
|
||||
if ((secinfoptr->flags & SEC_DATA)!=0)
|
||||
record.flags |= LoadImageSection::data;
|
||||
secinfoptr = secinfoptr->next;
|
||||
return (secinfoptr != (asection *)0);
|
||||
}
|
||||
|
||||
void LoadImageBfd::closeSymbols(void) const
|
||||
|
||||
{
|
||||
if (symbol_table != (asymbol **)0)
|
||||
delete [] symbol_table;
|
||||
symbol_table = (asymbol **)0;
|
||||
number_of_symbols = 0;
|
||||
cursymbol = 0;
|
||||
}
|
||||
|
||||
void LoadImageBfd::getReadonly(RangeList &list) const
|
||||
|
||||
{ // List all ranges that are read only
|
||||
uintb start,stop,secsize;
|
||||
asection *p;
|
||||
|
||||
for(p = thebfd->sections; p != (asection *)NULL; p = p->next) {
|
||||
if ((p->flags & SEC_READONLY)!=0) {
|
||||
start = p->vma;
|
||||
secsize = (p->size!=0) ? p->size : p->rawsize;
|
||||
if (secsize == 0) continue;
|
||||
stop = start + secsize - 1;
|
||||
list.insertRange(spaceid,start,stop);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue