2

私の質問は、bfd と、次のコードでセクション数がどのように機能するかに関するものです。bfd 構造の gdb デバッガー内のコードとダンプ、およびその中のセクション構造を以下に示します。また、以下の bfd および bfd-> セクションのデータ構造定義も含めました。私の質問は次のとおりです: なぜこのコードを実行すると (実行可能ファイルは getsections と呼ばれます): >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)。私' Web 上の 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 テストの 1 つが開始されます。

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 に答える