ec2-3-145-131-238.us-east-2.compute.amazonaws.com | ToothyWiki | Binutils | RecentChanges | Login | Webcomic
libbfd
This library provides functions to read and write the contents of executable binaries and libraries. To use the library, simply include "bfd.h", and link your program against libbdf.so.
A binary file is represented by an instance of the "bfd" object. Each file is broken into sections represented by "struct bfd_section" objects. These can be retrieved by name. For example, ".text" and ".data" are the standard section names in ELF for the code and data segments.
Although it would be possible to access the linking information directly from the appropriate bfd_sections, libbfd abstracts this functionality to allow the API to work independently of the binary structure. To achieve this, bfd objects can be used to retrieve arrays of "struct bfd_symbol" that represent entries in the binary's linker tables.
Primary bfd object methods
Class representing a Binary File Descriptor
// Open and close binary files
bfd * bfd_openr( const char * filename, const char * target );
bfd_boolean bfd_close( bfd * );
// Query file properties
char * bfd_get_filename( bfd * );
char * bfd_get_target( bfd * );
bfd_flavour bfd_get_flavour( bfd * );
flagword bfd_get_flags( bfd * );
// Address of the start of executable code when loaded into memory (.text section in standard ELF)
bfd_vma bfd_get_start_address( bfd * );
// Enumerate or retrieve file sections (for example ".text", ".data")
//
// Callback prototype is:
// void callback( bfd * bfdFile,
// struct bfd_section * section,
// void * user_data );
//
void bfd_map_over_sections( bfd *, &callback, void * user_data );
struct bfd_section * get_section_by_name( bfd *, const char * name );
// Symbol access
long bfd_get_symtab_upper_bound( bfd * );
long bfd_canonicalize_symtab( bfd *, struct bfd_symbol ** symbols );
long bfd_get_dynamic_symtab_upper_bound( bfd * );
long bfd_canonicalize_dynamic_symtab( bfd *, struct bfd_symbol ** symbols );
Primary struct bfd_sections properties
Class representing a section in an binary file
// Section name
const char * name;
// Address and size of section when loaded into memory
bfd_vma vma;
bfd_size_type size;
Primary "struct bfd_symbol" properties
Class representing an entry in one of the binary's symbol table
// The symbol name, the section it resides in, and standard symbol information structure
const char * name
struct bfd_section * section
void bfd_symbol_info( struct bfd_symbol *, symbol_info * info );
Example: Opening an existing binary file
This code opens /bin/ls as an 64-bit x86 ELF binary. Note that it is necessary to call bfd_check_format() before using the bfd instance.
bfd_init();
bfd * bfdFile = bfd_openr( "/bin/ls", "elf64-x86-64" );
if ( bfdFile == NULL )
{
printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
return;
}
if ( !bfd_check_format( bfdFile, bfd_object ))
{
printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
return;
}
// Program goes here
bfd_close( bfdFile );
Reading symbol tables
Retrieving the symbols included in the bfd file is slightly more complicated (you need to pass in a buffer of appropriate size). The code below extracts the dynamic symbols from a bfd instance (static symbols are similar):
struct bfd_symbol ** symbols;
long symbolsSize;
long symbolsCount;
long i;
// Calculate required buffer size
symbolsSize = bfd_get_dynamic_symtab_upper_bound( bfdFile );
if ( symbolsSize < 0 )
{
printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
return;
}
// Allocate buffer
symbols = malloc( symbolsSize );
if ( symbols == NULL )
{
printf( "Could not allocate memory\n" );
return;
}
// Retrieve unpacked symbols
symbolsCount = bfd_canonicalize_dynamic_symtab( bfdFile, symbols );
if ( symbolsCount < 0 )
{
printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
free( symbols );
return;
}
// List symbols
for ( i = 0; i < symbolsCount; i++ )
{
printf( "Symbol [flags %x][value %x] %s\n", symbols[i]->flags, symbols[i]->value, symbols[i]->name );
}
free( symbols );
Modifying and linking binary files
In addition to examining existing files, libbfd also has functionality for creating and modifying them. The most advanced functionality is in the area of code disassemble/reassembly and linking. This can even support code compiled for different machine architectures.