This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
problems using BFD to reproduce objdump functionality (--stabs)
- From: Roul Oldenburger <oldenburger dot roul at stn-atlas dot de>
- To: binutils at sources dot redhat dot com
- Date: Tue, 12 Aug 2003 11:49:59 +0200
- Subject: problems using BFD to reproduce objdump functionality (--stabs)
Hello everyone,
could you please advice me in my attempt to reproduce 'objdump --stabs
xyz' functionality.
I like to extract the same information objdump delivers from
executables, but don't want to parse objdump's output, so I like to use
the BFD lib, but my programm's output looks different and omits the most
important part (the string information / last column of 'objdump
--stabs' output) and I have almost no idea why.
I am compiling on a suse linux 8.1 system with
linux kernel 2.4.19,
a Pentium 4 processor and
I do link libbfd and libiberty to my program and of course I include bfd.h.
I don't use any special compile options and gcc seems to be satisfied.
This is what the output should look like (objdump's output from a simple
testfile):
.
.
318 LSYM 0 0 00000000 12677
my_date:T(0,20)=s12Tag:(0,1),0,32;Monat:(0,1),32,32;Jahr:(0,1),64,32;;
319 LSYM 0 0 00000000 12748 my_date:t(0,21)=(0,20)
320 LSYM 0 0 00000000 12771
my_time:T(0,22)=s8Minute:(0,1),0,32;Stunde:(0,1),32,32;;
321 LSYM 0 0 00000000 12828 my_time:t(0,23)=(0,22)
322 LSYM 0 0 00000000 12851
my_date_time:T(0,24)=s20Datum:(0,21),0,96;Zeit:(0,23),96,64;;
323 LSYM 0 0 00000000 12913 my_date_time:t(0,25)=(0,24)
324 FUN 0 0 08048460 12941 main:F(0,1)
.
.
This is my program's output (from the same testfile):
.
.
318 107 95 14964 2c392874 1668246638 *
319 LCSYM 48 12588 74700029 1026110002 *
320 SO 95 24930 65697272 1634038376 *
321 116 40 11321 3d293332 980705138 *
322 NOMAP 41 29501 5f5f3032 841759016 *
323 111 99 14955 312c3928 1818190178 *
324 54 52 24379 5f61625f 741354537 *
.
.
A colleague of mine thinks certain defines are maybe missing or there
are more header to be include than only bfd.h.
Could you please help me with this question what is missing or point me
to someone or other mailing list who can?
Thankyou very much!!
I have attached my program and beneath is my makefile.
Thanks
Roul Oldenburger
------------------
OBJS = $(patsubst %.c, %.o, $(wildcard *.c))
CFLAGS = -g -gstabs -Wall
bfd_test : $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ -lbfd -liberty
clean :
rm *~ $(OBJS) bfd_test
#include <stdio.h>
#include <bfd.h>
#define N_UNDF 0 /* Undefined symbol */
#define STRDXOFF (0)
#define TYPEOFF (4)
#define OTHEROFF (5)
#define DESCOFF (6)
#define VALOFF (8)
#define STABSIZE (12)
static bfd_size_type sec_size;
static bfd_size_type stabstr_size;
static bfd_byte *stabs;
static char *strtab;
void print_section_stabs (bfd *abfd, char *sec_name)
{
int i;
unsigned file_string_table_offset = 0, next_file_string_table_offset = 0;
bfd_byte *stabp, *stabs_end;
stabp = stabs;
stabs_end = stabp + sec_size;
printf ("Contents of %s section:\n\n", sec_name);
printf ("Symnum n_type n_othr n_desc n_value n_strx String\n");
/* Loop through all symbols and print them.
We start the index at -1 because there is a dummy symbol on
the front of stabs-in-{coff,elf} sections that supplies sizes. */
for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
{
const char *name;
unsigned long strx;
unsigned char type, other;
unsigned short desc;
bfd_vma value;
strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
value = bfd_h_get_32 (abfd, stabp + VALOFF);
printf ("\n%-6d ", i);
/* Either print the stab name, or, if unnamed, print its number
again (makes consistent formatting for tools like awk). */
name = bfd_get_stab_name (type);
if (name != NULL)
printf ("%-6s", name);
else if (type == N_UNDF)
printf ("HdrSym");
else
printf ("%-6d", type);
printf (" %-6d %-6d ", other, desc);
bfd_printf_vma (abfd, value);
printf (" %-6lu", strx);
/* Symbols with type == 0 (N_UNDF) specify the length of the
string table associated with this file. We use that info
to know how to relocate the *next* file's string table indices. */
if (type == N_UNDF)
{
file_string_table_offset = next_file_string_table_offset;
next_file_string_table_offset += value;
}
else
{
/* Using the (possibly updated) string table offset, print the
string (if any) associated with this symbol. */
if ((strx + file_string_table_offset) < stabstr_size)
printf (" %s", &strtab[strx + file_string_table_offset]);
else
printf (" *");
}
}
printf ("\n\n");
}
void retrieve_stab(bfd *abfd, asection *section, char *sec_name)
{
printf("Der Sektionsname ist: %s\n", sec_name);
sec_size = bfd_section_size (abfd, section);
stabs = (bfd_byte *) xmalloc (sec_size);
printf("sec_size ist jetzt %d\n", (int) sec_size);
if (! bfd_get_section_contents (abfd, section, (PTR) stabs, 0, sec_size))
{
if (sec_name == ".stab")
free (stabs);
bfd_errmsg( bfd_get_error() );
return;
}
}
void retrieve_stabstr(bfd *abfd, asection *section, char *sec_name)
{
printf("Der Sektionsname ist: %s\n", sec_name);
stabstr_size = bfd_section_size (abfd, section);
strtab = (char *) xmalloc (stabstr_size);
printf("stabstr_size ist %d\n", (int) stabstr_size);
if (! bfd_get_section_contents (abfd, section, (PTR) stabs, 0, sec_size))
{
if (sec_name == ".stabstr")
free (strtab);
bfd_errmsg( bfd_get_error() );
return;
}
}
void retrieve_section_stab(bfd *abfd, asection *section, PTR jnk)
{
char * sec_name;
sec_name = bfd_get_section_name (abfd, section);
printf("sec_name vor if : %s!!\n", sec_name);
printf("Compare zu .stab %d\n", strncmp(sec_name, ".stab", 4));
printf("Compare zu .stabstr %d\n", strncmp(sec_name, ".stabstr", 7));
if ( strncmp(sec_name, ".stabstr", 7)==0 )
{
retrieve_stabstr(abfd, section, sec_name);
}
else if ( strncmp(sec_name, ".stab", 4)==0 )
{
retrieve_stab(abfd, section, sec_name);
}
if ( (sec_size != 0) && (stabstr_size != 0) )
{
print_section_stabs(abfd, sec_name);
free (stabs);
free (strtab);
sec_size = 0;
stabstr_size = 0;
return;
}
printf("Sektionsname: %s\n", sec_name);
return;
}
// comment from objdump.c
/* Stabs entries use a 12 byte format:
4 byte string table index
1 byte stab type
1 byte stab other field
2 byte stab desc field
4 byte stab value
FIXME: This will have to change for a 64 bit object format. */
void close_it(bfd *abfd)
{
if (!bfd_close(abfd))
{
bfd_perror("Fehler beim Schliessen mit bfd_close");
exit(1);
}
}
boolean check_format(bfd *abfd)
{
int x;
char **matching;
extern bfd_target *bfd_target_vector[];
if (! bfd_check_format_matches(abfd, bfd_object, &matching))
{
printf("Unrecognized File!\n Supported targets: ");
bfd_errmsg( bfd_get_error() );
for ( x = 0; bfd_target_vector[x]; x++)
{
bfd_target *p = bfd_target_vector[x];
printf("%s ", p->name);
}
return false;
}
return true;
}
int main( int argc, char* argv[])
{
bfd *abfd;
char *target = NULL;
// asection *p;
bfd_init(); // necesary to use BFD at all
if (argc < 2)
{
printf("Missing argument: No input file selected!\n");
return 1;
}
else
{
abfd = bfd_openr(argv[1], target);
if ( abfd == NULL)
{
printf("Unable to open %s\n", argv[1]);
bfd_errmsg( bfd_get_error() );
return 1;
}
}
if (!check_format(abfd))
return 1;
// use of this bfd_ function is necessary to get hold of the actual
// sections, it runs through them calls retrieve_section_stab for each one
bfd_map_over_sections(abfd, retrieve_section_stab, (PTR) NULL);
//some info from the bfd structure
printf("File in abfd : %s\n", abfd->filename);
if (abfd->target_defaulted)
printf("A default target was set!!\n");
if (abfd->format==bfd_object)
printf("The format is bfd_object.\n");
if (abfd->direction == read_direction)
printf("%s was opened for reading...\n",abfd->filename);
close_it(abfd);
return 0;
}