2

我的问题是关于 bfd 以及以下代码中的部分数量如何工作。bfd 结构的 gdb 调试器中的代码和转储及其中的节结构如下所示。我还包括以下 bfd 和 bfd-> 部分的数据结构定义。我的问题是:为什么当我运行此代码时(可执行文件称为 getsections):getsections getsections.o(因此将其传递给它自己的目标文件) - 为什么部分结构为空白(全为零),如果您查看 bfd- >section_count,它的编号是 4218960?如果使用 Linux 命令:objdump -h getsections.o,它会显示 14 个部分(.text、.data、.bss、.rodata、.debug_info、.debug_abbrev、.debug_loc、.debug_aranges、.debug_line、.debug_str、.评论、.comment.SUSE.OPTS、.note-GNU-stack、.eh_frame)。我' 我已经阅读了我在网络上的 BFD 文档中可以找到的内容,但我不确定我在这里做错了什么,因为我的目标文件结构与您在 objdump 中看到的(14 节)相去甚远。任何帮助表示赞赏。谢谢。

unsigned int number_of_sections(bfd *abfd)
{
  unsigned int numSections = 0;
  numSections =  bfd_count_sections(abfd);
  return numSections;
} 

int main (int argc, char *argv[])
{
  bfd *ibfd = NULL;
  char filename[80];
  char *fptr = &filename[0];
  unsigned int numSections = 0;

  if (argc < 2)
    {
      printf("Argc < 2\n");
      exit(EXIT_FAILURE);
    }
  else
    {
      bfd_init();
      printf("filename = %s\n", argv[1]);
      ibfd = bfd_openr(argv[1], NULL);
      numSections = number_of_sections(ibfd);
      printf("num sections = %d\n", numSections);
      bfd_close(ibfd);
    }
  return 1;
}

在 number_of_sections() 处设置断点,bfd 的转储会产生以下内容:

(gdb) print abfd
$1 = (bfd *) 0x85c010
(gdb) print *abfd
$2 = {filename = 0x0, xvec = 0x7fffffffe06f, iostream = 0x7fff20 <bfd_elf64_x86_64_vec> "\211\345X", cacheable = (unknown: 8773984), target_defaulted = false, lru_prev = 0x7f6d40 <cache_iovec>, lru_next = 0x85c010, where = 8765456, opened_once = false, mtime_set = false, mtime = 0, ifd = 0, format = bfd_unknown, direction = read_direction, flags = 0, origin = 0, output_has_begun = false, sections = 0x85d180, section_count = 4218960, start_address = 8769872, symcount = 251, outsymbols = 0x130, arch_info = 0x0, arelt_data = 0x0, my_archive = 0x0, next = 0x0, archive_head = 0x0, has_armap = false, link_next = 0x0, archive_pass = 8673856, tdata = {aout_data = 0x0, aout_ar_data = 0x0, oasys_obj_data = 0x0, oasys_ar_data = 0x0, coff_obj_data = 0x0, pe_obj_data = 0x0, xcoff_obj_data = 0x0, ecoff_obj_data = 0x0, ieee_data = 0x0, ieee_ar_data = 0x0, srec_data = 0x0, tekhex_data = 0x0, elf_obj_data = 0x0, nlm_obj_data = 0x0, bout_data = 0x0, sun_core_data = 0x0, trad_core_data = 0x0, som_data = 0x0, hpux_core_data = 0x0, hppabsd_core_data = 0x0, sgi_core_data = 0x0, lynx_core_data = 0x0, osf_core_data = 0x0, cisco_core_data = 0x0, versados_data = 0x0, any = 0x0}, usrdata = 0x0, memory = {chunk_size = 0, chunk = 0x0, object_base = 0x0, next_free = 0x0, chunk_limit = 0x0, temp = {tempint = 0, tempptr = 0x0}, alignment_mask = 0, chunkfun = 0x85c140, freefun = 0x7, extra_arg = 0x21, use_extra_arg = 0, maybe_empty_object = 0, alloc_failed = 0}}

abfd->sections 的转储看起来好像什么都没有:

(gdb) print *(abfd->sections)
$4 = {name = 0x0, index = 0, next = 0x0, flags = 0, vma = 0, user_set_vma = false, lma = 0, _cooked_size = 0, _raw_size = 0, output_offset = 0, output_section = 0x0, alignment_power = 0, relocation = 0x0, orelocation = 0x0, reloc_count = 0, filepos = 0, rel_filepos = 0, line_filepos = 0, userdata = 0x0, contents = 0x0, lineno = 0x0, lineno_count = 0, moving_line_filepos = 0, target_index = 0, used_by_bfd = 0x0, constructor_chain = 0x0, owner = 0x0, reloc_done = false, symbol = 0x0, symbol_ptr_ptr = 0x0, link_order_head = 0x0, link_order_tail = 0x0}

bfd 结构如下所示:

struct _bfd 
{
 /* The filename the application opened the BFD with.  */
CONST char *filename;                

 /* A pointer to the target jump table.             */
const struct bfd_target *xvec;

 /* To avoid dragging too many header files into every file that
   includes `<<bfd.h>>', IOSTREAM has been declared as a "char
   *", and MTIME as a "long".  Their correct types, to which they
   are cast when used, are "FILE *" and "time_t".    The iostream
   is the result of an fopen on the filename. */
char *iostream;

 /* Is the file descriptor being cached?  That is, can it be closed as
   needed, and re-opened when accessed later?  */

boolean cacheable;

 /* Marks whether there was a default target specified when the
   BFD was opened. This is used to select which matching algorithm
   to use to choose the back end. */

boolean target_defaulted;

 /* The caching routines use these to maintain a
   least-recently-used list of BFDs */

struct _bfd *lru_prev, *lru_next;

 /* When a file is closed by the caching routines, BFD retains
   state information on the file here: */

file_ptr where;              

 /* and here: (``once'' means at least once) */

boolean opened_once;

 /* Set if we have a locally maintained mtime value, rather than
   getting it from the file each time: */

boolean mtime_set;

 /* File modified time, if mtime_set is true: */

long mtime;          

 /* Reserved for an unimplemented file locking extension.*/

int ifd;

 /* The format which belongs to the BFD. (object, core, etc.) */

bfd_format format;

 /* The direction the BFD was opened with*/

enum bfd_direction {no_direction = 0,
                    read_direction = 1,
                    write_direction = 2,
                    both_direction = 3} direction;

 /* Format_specific flags*/

flagword flags;              

 /* Currently my_archive is tested before adding origin to
   anything. I believe that this can become always an add of
   origin, with origin set to 0 for non archive files.   */

file_ptr origin;             

 /* Remember when output has begun, to stop strange things
   from happening. */
boolean output_has_begun;

 /* Pointer to linked list of sections*/
struct sec  *sections;

 /* The number of sections */
unsigned int section_count;

 /* Stuff only useful for object files: 
   The start address. */
bfd_vma start_address;

 /* Used for input and output*/
unsigned int symcount;

 /* Symbol table for output BFD (with symcount entries) */
struct symbol_cache_entry  **outsymbols;             

 /* Pointer to structure which contains architecture information*/
const struct bfd_arch_info *arch_info;

 /* Stuff only useful for archives:*/
PTR arelt_data;              
struct _bfd *my_archive;      /* The containing archive BFD.  */
struct _bfd *next;            /* The next BFD in the archive.  */
struct _bfd *archive_head;    /* The first BFD in the archive.  */
boolean has_armap;           

 /* A chain of BFD structures involved in a link.  */
struct _bfd *link_next;

 /* A field used by _bfd_generic_link_add_archive_symbols.  This will
   be used only for archive elements.  */
int archive_pass;

 /* Used by the back end to hold private data. */

union 
  {
  struct aout_data_struct *aout_data;
  struct artdata *aout_ar_data;
  struct _oasys_data *oasys_obj_data;
  struct _oasys_ar_data *oasys_ar_data;
  struct coff_tdata *coff_obj_data;
  struct pe_tdata *pe_obj_data;
  struct xcoff_tdata *xcoff_obj_data;
  struct ecoff_tdata *ecoff_obj_data;
  struct ieee_data_struct *ieee_data;
  struct ieee_ar_data_struct *ieee_ar_data;
  struct srec_data_struct *srec_data;
  struct tekhex_data_struct *tekhex_data;
  struct elf_obj_tdata *elf_obj_data;
  struct nlm_obj_tdata *nlm_obj_data;
  struct bout_data_struct *bout_data;
  struct sun_core_struct *sun_core_data;
  struct trad_core_struct *trad_core_data;
  struct som_data_struct *som_data;
  struct hpux_core_struct *hpux_core_data;
  struct hppabsd_core_struct *hppabsd_core_data;
  struct sgi_core_struct *sgi_core_data;
  struct lynx_core_struct *lynx_core_data;
  struct osf_core_struct *osf_core_data;
  struct cisco_core_struct *cisco_core_data;
  struct versados_data_struct *versados_data;
  PTR any;
  } tdata;

 /* Used by the application to hold private data*/
PTR usrdata;

 /* Where all the allocated stuff under this BFD goes */
struct obstack memory;
};

bfd->sections 结构(sec 结构)如下所示:

typedef struct sec
{
     /* The name of the section; the name isn't a copy, the pointer is
    the same as that passed to bfd_make_section. */

    CONST char *name;

     /* Which section is it; 0..nth.      */

    int index;

     /* The next section in the list belonging to the BFD, or NULL. */

    struct sec *next;

     /* The field flags contains attributes of the section. Some
       flags are read in from the object file, and some are
       synthesized from other information.  */

    flagword flags;

#define SEC_NO_FLAGS   0x000

     /* Tells the OS to allocate space for this section when loading.
       This is clear for a section containing debug information
       only. */
#define SEC_ALLOC      0x001

     /* Tells the OS to load the section from the file when loading.
       This is clear for a .bss section. */
#define SEC_LOAD       0x002

     /* The section contains data still to be relocated, so there is
       some relocation information too. */
#define SEC_RELOC      0x004

#if 0    /* Obsolete ? */
#define SEC_BALIGN     0x008
#endif

     /* A signal to the OS that the section contains read only
      data. */
#define SEC_READONLY   0x010

     /* The section contains code only. */
#define SEC_CODE       0x020

     /* The section contains data only. */
#define SEC_DATA       0x040

     /* The section will reside in ROM. */
#define SEC_ROM        0x080

     /* The section contains constructor information. This section
       type is used by the linker to create lists of constructors and
       destructors used by <<g++>>. When a back end sees a symbol
       which should be used in a constructor list, it creates a new
       section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
       the symbol to it, and builds a relocation. To build the lists
       of constructors, all the linker has to do is catenate all the
       sections called <<__CTOR_LIST__>> and relocate the data
       contained within - exactly the operations it would peform on
       standard data. */
#define SEC_CONSTRUCTOR 0x100

     /* The section is a constuctor, and should be placed at the
      end of the text, data, or bss section(?). */
#define SEC_CONSTRUCTOR_TEXT 0x1100
#define SEC_CONSTRUCTOR_DATA 0x2100
#define SEC_CONSTRUCTOR_BSS  0x3100

     /* The section has contents - a data section could be
       <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
       <<SEC_HAS_CONTENTS>> */ 
#define SEC_HAS_CONTENTS 0x200

     /* An instruction to the linker to not output the section
       even if it has information which would normally be written. */
#define SEC_NEVER_LOAD 0x400

     /* The section is a COFF shared library section.  This flag is
       only for the linker.  If this type of section appears in
       the input file, the linker must copy it to the output file
       without changing the vma or size.  FIXME: Although this
       was originally intended to be general, it really is COFF
       specific (and the flag was renamed to indicate this).  It
       might be cleaner to have some more general mechanism to
       allow the back end to control what the linker does with
       sections. */
#define SEC_COFF_SHARED_LIBRARY 0x800

     /* The section is a common section (symbols may be defined
       multiple times, the value of a symbol is the amount of
       space it requires, and the largest symbol value is the one
       used).  Most targets have exactly one of these (which we
    translate to bfd_com_section_ptr), but ECOFF has two. */
#define SEC_IS_COMMON 0x8000

     /* The section contains only debugging information.  For
       example, this is set for ELF .debug and .stab sections.
       strip tests this flag to see if a section can be
       discarded. */
#define SEC_DEBUGGING 0x10000

     /* The contents of this section are held in memory pointed to
       by the contents field.  This is checked by
       bfd_get_section_contents, and the data is retrieved from
       memory if appropriate.  */
#define SEC_IN_MEMORY 0x20000

 /*  End of section flags.  */

    /*  The virtual memory address of the section - where it will be
       at run time.  The symbols are relocated against this.  The
    user_set_vma flag is maintained by bfd; if it's not set, the
    backend can assign addresses (for example, in <<a.out>>, where
    the default address for <<.data>> is dependent on the specific
    target and various flags).  */

   bfd_vma vma;
   boolean user_set_vma;

    /*  The load address of the section - where it would be in a
       rom image; really only used for writing section header
    information. */

   bfd_vma lma;

     /* The size of the section in bytes, as it will be output.
       contains a value even if the section has no contents (e.g., the
       size of <<.bss>>). This will be filled in after relocation */

   bfd_size_type _cooked_size;

     /* The original size on disk of the section, in bytes.  Normally this
    value is the same as the size, but if some relaxing has
    been done, then this value will be bigger.  */

   bfd_size_type _raw_size;

     /* If this section is going to be output, then this value is the
       offset into the output section of the first byte in the input
       section. E.g., if this was going to start at the 100th byte in
       the output section, this value would be 100. */

   bfd_vma output_offset;

     /* The output section through which to map on output. */

   struct sec *output_section;

     /* The alignment requirement of the section, as an exponent of 2 -
       e.g., 3 aligns to 2^3 (or 8). */

   unsigned int alignment_power;

     /* If an input section, a pointer to a vector of relocation
       records for the data in this section. */

   struct reloc_cache_entry *relocation;

     /* If an output section, a pointer to a vector of pointers to
       relocation records for the data in this section. */

   struct reloc_cache_entry **orelocation;

     /* The number of relocation records in one of the above  */

   unsigned reloc_count;

     /* Information below is back end specific - and not always used
       or updated.  */

     /* File position of section data    */

   file_ptr filepos;

     /* File position of relocation info */

   file_ptr rel_filepos;

     /* File position of line data       */

   file_ptr line_filepos;

     /* Pointer to data for applications */

   PTR userdata;

     /* If the SEC_IN_MEMORY flag is set, this points to the actual
       contents.  */
   unsigned char *contents;

     /* Attached line number information */

   alent *lineno;

     /* Number of line number records   */

   unsigned int lineno_count;

     /* When a section is being output, this value changes as more
       linenumbers are written out */

   file_ptr moving_line_filepos;

     /* What the section number is in the target world  */

   int target_index;

   PTR used_by_bfd;

     /* If this is a constructor section then here is a list of the
       relocations created to relocate items within it. */

   struct relent_chain *constructor_chain;

     /* The BFD which owns the section. */

   bfd *owner;

   boolean reloc_done;
  /* A symbol which points at this section only */
   struct symbol_cache_entry *symbol;
   struct symbol_cache_entry **symbol_ptr_ptr;

   struct bfd_link_order *link_order_head;
   struct bfd_link_order *link_order_tail;
} asection ;
4

1 回答 1

3

我没有尝试你的程序。但是,我注意到它没有调用 bfd_check_format。这是必需的。BFD 文档对这类事情并不总是很清楚(欢迎改进!)所以当我需要处理 BFD 时,我通常最终会阅读示例程序,比如 objdump。

我的 BFD 测试之一开始:

fd = open (argv[1], O_RDONLY | O_CLOEXEC, 0);
if (fd == -1)
  die ("open");

abfd = bfd_fopen (argv[1], NULL, "r", fd);

if (!bfd_check_format (abfd, bfd_object))
  {
    bfd_close (abfd);
    die ("bfd_check_format");
  }
于 2014-03-29T04:20:02.007 回答