Beispiel #1
0
void
plugin_maybe_claim (struct ld_plugin_input_file *file,
		    lang_input_statement_type *entry)
{
  int claimed = 0;

  /* We create a dummy BFD, initially empty, to house whatever symbols
     the plugin may want to add.  */
  file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
					  entry->the_bfd);
  if (plugin_call_claim_file (file, &claimed))
    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
	   plugin_error_plugin ());
  /* fd belongs to us, not the plugin; but we don't need it.  */
  close (file->fd);
  if (claimed)
    {
      /* Discard the real file's BFD and substitute the dummy one.  */

      /* BFD archive handling caches elements so we can't call
	 bfd_close for archives.  */
      if (entry->the_bfd->my_archive == NULL)
	bfd_close (entry->the_bfd);
      entry->the_bfd = file->handle;
      entry->flags.claimed = TRUE;
      bfd_make_readable (entry->the_bfd);
    }
  else
    {
      /* If plugin didn't claim the file, we don't need the dummy bfd.
	 Can't avoid speculatively creating it, alas.  */
      bfd_close_all_done (file->handle);
      entry->flags.claimed = FALSE;
    }
}
Beispiel #2
0
 ~bfd_cache() {
   if (abfd) {
     bfd_cache_close(abfd);
     bfd_free_cached_info(abfd);
     bfd_close_all_done(abfd);
   }
 }
Beispiel #3
0
void objdump(const char *path)
{
    bfd_init();

    bfd *abfd = bfd_openr(path, NULL);

    if (abfd == NULL)
        errx(1, bfd_errmsg(bfd_get_error()));

    if (!bfd_check_format(abfd, bfd_object)) {
        bfd_close_all_done(abfd);
        errx(1, "File is not a valid object file.");
    }

    printf("%s:     file format %s\n", path, bfd_get_target(abfd));
    printf("architecture: %s, flags: 0x%08x\n", bfd_printable_arch_mach(bfd_get_arch(abfd), bfd_get_mach(abfd)), abfd->flags);
    printf("start address 0x%016lx", bfd_get_start_address(abfd));
    printf("\n");
    printf("Sections:\n");
    printf("Idx Name          Size      VMA               LMA               File off  Algn\n");
    printf("                  Flags    Content\n");

    object_stats stats = { FALSE, FALSE };
    bfd_map_over_sections(abfd, (void (*)(bfd *, asection *, void *))print_section, &stats);

    if (stats.contains_hello && stats.contains_world)
        printf("\nThis file might be a hello world program!\n");

    bfd_close(abfd);
}
Beispiel #4
0
/**
 * Close BFD context, releasing its resources and nullifying its pointer.
 */
static void
bfd_util_close_context_null(bfd_ctx_t **bc_ptr)
{
	bfd_ctx_t *bc = *bc_ptr;

	if (bc != NULL) {
		mutex_lock(&bc->lock);	/* Not a fast mutex since we'll destroy it */
		if (bc->symbols != NULL)
			free(bc->symbols);	/* Not xfree(): created by the bfd library */

		/*
		 * We use bfd_close_all_done() and not bfd_close() because the latter
		 * causes a SIGSEGV now that we are using bfd_fdopenr(). The fault
		 * occurs in some part trying to write changes to the file...
		 *
		 * Since the file is opened as read-only and we don't expect any
		 * write operation, using bfd_close_all_done() is a viable workaround
		 * for this BFD library bug.
		 */

		if (bc->handle != NULL)
			bfd_close_all_done(bc->handle);		/* Workaround for BFD bug */
		symbols_free_null(&bc->text_symbols);
		bc->magic = 0;
		mutex_destroy(&bc->lock);
		xfree(bc);
		*bc_ptr = NULL;
	}
}
Beispiel #5
0
void asmir_close(asm_program_t *p)
{
  // FIXME: free sections
  bfd_close_all_done(p->abfd);
  free(p);
  vx_FreeAll();
}
Beispiel #6
0
static void arch_bfdDestroy(bfd_t * bfdParams)
{
    if (bfdParams->syms) {
        free(bfdParams->syms);
    }
    if (bfdParams->bfdh) {
        bfd_close_all_done(bfdParams->bfdh);
    }
}
Beispiel #7
0
trap::ExecLoader::~ExecLoader() {
  if (this->exec_image != NULL) {
    if (!bfd_close_all_done(this->exec_image)) {
      //An Error has occurred; lets see what it is
      THROW_ERROR("Cannot close binary parser: " << bfd_errmsg(bfd_get_error()) << '.');
    }
  }
  if (this->program_data != NULL) {
    delete [] this->program_data;
  }
} // ExecLoader::~ExecLoader()
Beispiel #8
0
static
struct bfd* new_bfd_internal( const char* filename,
                              int arch, int machine )
{
    char** matching;
    enum bfd_architecture _arch = (enum bfd_architecture) arch;
    struct bfd* p = bfd_openr( filename, DEFAULT_TARGET );
    const bfd_arch_info_type* info;

    if ( !p ) error_exit( "failure: bfd_openr" );

    if ( _arch == bfd_arch_unknown ) {
        if ( bfd_check_format( p, bfd_archive ) ) {
            // TODO: add archive handling code
            bfd_close_all_done( p );
            error_exit( "currently not supported." );
        }
        if ( bfd_check_format_matches( p, bfd_object, &matching ) ) {
            return p;
        }
        if ( bfd_get_error() == bfd_error_file_ambiguously_recognized ) {
            bfd_close_all_done( p );
            error_exit( "file format is ambiguosly matched" );
        }
        if ( bfd_get_error() != bfd_error_file_not_recognized ) {
            bfd_close_all_done( p );
            error_exit( "file is not recognized" );
        }
        if ( bfd_check_format_matches( p, bfd_core, &matching ) ) {
            return p;
        }
        error_exit( "failed to load the given file" );
        return NULL; /* this will never be called */
    } else {
        info = bfd_lookup_arch( _arch, machine );
        if ( !info ) error_exit( "failed to lookup archicture" );
        bfd_set_arch_info( p, info );
        return p;
    }
}
Beispiel #9
0
static bfd *
initialize_bfd(const char *filename)
{
  bfd * abfd;
  char **matching;
  char *target = "i686-pc-linux-gnu";

  bfd_init();

  if(!bfd_set_default_target(target)) {
    fprintf(stderr, "initialize_bfd: couldn't set default bfd target\n");
    return NULL;
  }

  abfd = bfd_openr(filename, target);
  if(abfd == NULL) {
    fprintf(stderr, "initialize_bfd: cannot open %s\n", filename);
    return NULL;
  }

  if (bfd_check_format (abfd, bfd_archive)) {
    fprintf(stderr, "initalize_bfd: archive files  not supported\n");
    bfd_close_all_done(abfd);
    return NULL;
  }

  /* if(!bfd_check_format_matches(abfd, bfd_object, &matching)) { */
  if( (!bfd_check_format_matches(abfd, bfd_object, &matching)) &&
      (!bfd_check_format_matches(abfd, bfd_core, &matching)) ) {

    fprintf(stderr, "initialize_bfd: bfd_check_format_matches failed\n");
    bfd_close_all_done(abfd);
    return NULL;
  }
  return abfd;
}
Beispiel #10
0
void free_asm_program(asm_program_t *p)
{
  for(map<address_t, section_t *>::const_iterator it = 
	p->sections.begin(); it != p->sections.end();
      it++) {
    // FIXME: is this all that's required to free sections?
    free(it->second);
  }  
  for(map<address_t, asm_function_t *>::const_iterator it = 
	p->functions.begin(); it != p->functions.end();
      it++) {
    free_asm_function(it->second);
  }  
  bfd_close_all_done(p->abfd);
  delete p;
}
Beispiel #11
0
void delete_bfd( bhp _p )
{
    bh* p = (bh*) _p;

    if ( p->disasp ) {
        free( p->disasp->buffer );
        free( p->disasp );
        p->disasp = NULL;
    }

    if ( bfd_close_all_done( p->bfdp ) == TRUE ) return;
    else error_exit( "failed to close with bfd_close_all_done" );

    free( p );
    p = NULL;
}
Beispiel #12
0
void arch_bfdDisasm(pid_t pid, uint8_t * mem, size_t size, char *instr)
{
    while (pthread_mutex_lock(&arch_bfd_mutex)) ;

    bfd_init();

    char fname[PATH_MAX];
    snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
    bfd *bfdh = bfd_openr(fname, NULL);
    if (bfdh == NULL) {
        LOGMSG(l_WARN, "bfd_openr('/proc/%d/exe') failed", pid);
        goto out;
    }

    if (!bfd_check_format(bfdh, bfd_object)) {
        LOGMSG(l_WARN, "bfd_check_format() failed");
        goto out;
    }

    disassembler_ftype disassemble = disassembler(bfdh);
    if (disassemble == NULL) {
        LOGMSG(l_WARN, "disassembler() failed");
        goto out;
    }

    struct disassemble_info info;
    init_disassemble_info(&info, instr, arch_bfdFPrintF);
    info.arch = bfd_get_arch(bfdh);
    info.mach = bfd_get_mach(bfdh);
    info.buffer = mem;
    info.buffer_length = size;
    info.section = NULL;
    info.endian = bfd_little_endian(bfdh) ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
    disassemble_init_for_target(&info);

    strcpy(instr, "");
    if (disassemble(0, &info) <= 0) {
        snprintf(instr, _HF_INSTR_SZ, "[DIS-ASM_FAILURE]");
    }

 out:
    bfdh ? bfd_close_all_done(bfdh) : 0;

    while (pthread_mutex_unlock(&arch_bfd_mutex)) ;
    return;
}
Beispiel #13
0
void replace_hello(const char *input_path, const char *output_path)
{
    bfd_init();

    bfd *ibfd = bfd_openr(input_path, NULL);

    if (ibfd == NULL)
        errx(1, bfd_errmsg(bfd_get_error()));

    if (!bfd_check_format(ibfd, bfd_object)) {
        bfd_close_all_done(ibfd);
        errx(1, "Input file is not a valid object file.");
    }

    bfd *obfd = bfd_openw(output_path, bfd_get_target(ibfd));

    if (obfd == NULL) {
        bfd_close_all_done(ibfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_format(obfd, bfd_get_format(ibfd))) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, "Setting obfd format failed: %s\n", bfd_errmsg(bfd_get_error()));
    }

    bfd_set_arch_info(obfd, bfd_get_arch_info(ibfd));

    // Create sections for .data
    asection *section = bfd_get_section_by_name(ibfd, ".data");
    while (section != NULL) {
        if (section->flags & SEC_HAS_CONTENTS) {
            char *section_contents = (char *)malloc(section->size);
            bfd_get_section_contents(ibfd, section, section_contents, 0, section->size);

            char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5);
            if (hello_pos != NULL) {
                if (bfd_make_section_anyway_with_flags(obfd, ".data", section->flags) == NULL) {
                    free(section_contents);
                    bfd_close_all_done(ibfd);
                    bfd_close_all_done(obfd);
                    errx(1, bfd_errmsg(bfd_get_error()));
                }
            }

            free(section_contents);
        }

        section = bfd_get_next_section_by_name(ibfd, section);
    }

    asection *comment_section = bfd_make_section_anyway_with_flags(obfd, ".comment.my_objcopy", SEC_HAS_CONTENTS);
    if (comment_section == NULL) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_section_size(obfd, comment_section, 3)) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_section_contents(obfd, comment_section, "moo", 0, 3)) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    // section = bfd_get_section_by_name(ibfd, ".data");
    // asection *osection = bfd_get_section_by_name(obfd, ".data");
    // if (osection == NULL) {
    // 	bfd_close_all_done(ibfd);
    // 	bfd_close_all_done(obfd);
    // 	errx(1, bfd_errmsg(bfd_get_error()));
    // }
    // while (section != NULL) {
    // 	if (section->flags & SEC_HAS_CONTENTS) {
    // 		char *section_contents = (char *)malloc(section->size);
    // 		bfd_get_section_contents(ibfd, section, section_contents, 0, section->size);
    //
    // 		char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5);
    // 		if (hello_pos != NULL) {
    // 			hello_pos[1] = 'o';
    // 			hello_pos[4] = 'a';
    // 			if (bfd_set_section_contents(obfd, osection, section_contents, 0, section->size)) {
    // 				free(section_contents);
    // 				bfd_close_all_done(ibfd);
    // 				bfd_close_all_done(obfd);
    // 				errx(1, bfd_errmsg(bfd_get_error()));
    // 			}
    // 		}
    //
    // 		free(section_contents);
    // 		osection = bfd_get_next_section_by_name(obfd, osection);
    // 	}
    //
    // 	section = bfd_get_next_section_by_name(ibfd, section);
    // }

    if (!bfd_close(obfd))
        errx(1, "Closing obfd failed: %s\n", bfd_errmsg(bfd_get_error()));

    if (!bfd_close(ibfd))
        errx(1, "Closing ibfd failed: %s\n", bfd_errmsg(bfd_get_error()));
}
Beispiel #14
0
static const bfd_target *
plugin_object_p (bfd *ibfd)
{
    int claimed;
    plugin_input_file_t *input;
    struct ld_plugin_input_file file;
    bfd *abfd;

    /* Don't try the dummy object file.  */
    if ((ibfd->flags & BFD_PLUGIN) != 0)
        return NULL;

    if (ibfd->plugin_format != bfd_plugin_unknown)
    {
        if (ibfd->plugin_format == bfd_plugin_yes)
            return ibfd->plugin_dummy_bfd->xvec;
        else
            return NULL;
    }

    /* We create a dummy BFD, initially empty, to house whatever symbols
       the plugin may want to add.  */
    abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);

    input = bfd_alloc (abfd, sizeof (*input));
    if (input == NULL)
        einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
               bfd_get_error ());

    if (!bfd_plugin_open_input (ibfd, &file))
        return NULL;

    if (file.name == ibfd->filename)
    {
        /* We must copy filename attached to ibfd if it is not an archive
        member since it may be freed by bfd_close below.  */
        file.name = plugin_strdup (abfd, file.name);
    }

    file.handle = input;
    /* The plugin API expects that the file descriptor won't be closed
       and reused as done by the bfd file cache.  So dup one.  */
    file.fd = dup (file.fd);
    if (file.fd < 0)
        return NULL;

    input->abfd = abfd;
    input->view_buffer.addr = NULL;
    input->view_buffer.filesize = 0;
    input->view_buffer.offset = 0;
    input->fd = file.fd;
    input->use_mmap = FALSE;
    input->offset = file.offset;
    input->filesize = file.filesize;
    input->name = plugin_strdup (abfd, ibfd->filename);

    claimed = 0;

    if (plugin_call_claim_file (&file, &claimed))
        einfo (_("%P%F: %s: plugin reported error claiming file\n"),
               plugin_error_plugin ());

    if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec))
    {
        /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
        doesn't need fd after plugin_call_claim_file, doesn't use
         BFD plugin target vector.  Since GCC plugin doesn't call
         release_input_file, we close it here.  LLVM plugin, which
         needs fd after plugin_call_claim_file and calls
         release_input_file after it is done, uses BFD plugin target
         vector.  This scheme doesn't work when a plugin needs fd and
         doesn't use BFD plugin target vector neither.  */
        close (input->fd);
        input->fd = -1;
    }

    if (claimed)
    {
        ibfd->plugin_format = bfd_plugin_yes;
        ibfd->plugin_dummy_bfd = abfd;
        bfd_make_readable (abfd);
        return abfd->xvec;
    }
    else
    {
#if HAVE_MMAP
        if (input->use_mmap)
        {
            /* If plugin didn't claim the file, unmap the buffer.  */
            char *addr = input->view_buffer.addr;
            off_t size = input->view_buffer.filesize;
# if HAVE_GETPAGESIZE
            off_t bias = input->view_buffer.offset % plugin_pagesize;
            size += bias;
            addr -= bias;
# endif
            munmap (addr, size);
        }
#endif

        /* If plugin didn't claim the file, we don't need the dummy bfd.
        Can't avoid speculatively creating it, alas.  */
        ibfd->plugin_format = bfd_plugin_no;
        bfd_close_all_done (abfd);
        return NULL;
    }
}
Beispiel #15
0
static const bfd_target *
plugin_object_p (bfd *ibfd)
{
  int claimed;
  plugin_input_file_t *input;
  off_t offset, filesize;
  struct ld_plugin_input_file file;
  bfd *abfd;
  bfd_boolean inarchive;
  const char *name;
  int fd;

  /* Don't try the dummy object file.  */
  if ((ibfd->flags & BFD_PLUGIN) != 0)
    return NULL;

  if (ibfd->plugin_format != bfd_plugin_uknown)
    {
      if (ibfd->plugin_format == bfd_plugin_yes)
	return ibfd->plugin_dummy_bfd->xvec;
      else
	return NULL;
    }

  inarchive = bfd_my_archive (ibfd) != NULL;
  name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
  fd = open (name, O_RDONLY | O_BINARY);

  if (fd < 0)
    return NULL;

  /* We create a dummy BFD, initially empty, to house whatever symbols
     the plugin may want to add.  */
  abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);

  input = bfd_alloc (abfd, sizeof (*input));
  if (input == NULL)
    einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
	   bfd_get_error ());

  if (inarchive)
    {
      /* Offset and filesize must refer to the individual archive
	 member, not the whole file, and must exclude the header.
	 Fortunately for us, that is how the data is stored in the
	 origin field of the bfd and in the arelt_data.  */
      offset = ibfd->origin;
      filesize = arelt_size (ibfd);
    }
  else
    {
      offset = 0;
      filesize = lseek (fd, 0, SEEK_END);

      /* We must copy filename attached to ibfd if it is not an archive
	 member since it may be freed by bfd_close below.  */
      name = plugin_strdup (abfd, name);
    }

  file.name = name;
  file.offset = offset;
  file.filesize = filesize;
  file.fd = fd;
  file.handle = input;

  input->abfd = abfd;
  input->view_buffer.addr = NULL;
  input->view_buffer.filesize = 0;
  input->view_buffer.offset = 0;
  input->fd = fd;
  input->use_mmap = FALSE;
  input->offset = offset;
  input->filesize = filesize;
  input->name = plugin_strdup (abfd, ibfd->filename);

  claimed = 0;

  if (plugin_call_claim_file (&file, &claimed))
    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
	   plugin_error_plugin ());

  if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec))
    {
      /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
	 doesn't need fd after plugin_call_claim_file, doesn't use
	 BFD plugin target vector.  Since GCC plugin doesn't call
	 release_input_file, we close it here.  LLVM plugin, which
	 needs fd after plugin_call_claim_file and calls
	 release_input_file after it is done, uses BFD plugin target
	 vector.  This scheme doesn't work when a plugin needs fd and
	 doesn't use BFD plugin target vector neither.  */
      close (fd);
      input->fd = -1;
    }

  if (claimed)
    {
      ibfd->plugin_format = bfd_plugin_yes;
      ibfd->plugin_dummy_bfd = abfd;
      bfd_make_readable (abfd);
      return abfd->xvec;
    }
  else
    {
#if HAVE_MMAP
      if (input->use_mmap)
	{
	  /* If plugin didn't claim the file, unmap the buffer.  */
	  char *addr = input->view_buffer.addr;
	  off_t size = input->view_buffer.filesize;
# if HAVE_GETPAGESIZE
	  off_t bias = input->view_buffer.offset % plugin_pagesize;
	  size += bias;
	  addr -= bias;
# endif
	  munmap (addr, size);
	}
#endif

      /* If plugin didn't claim the file, we don't need the dummy bfd.
	 Can't avoid speculatively creating it, alas.  */
      ibfd->plugin_format = bfd_plugin_no;
      bfd_close_all_done (abfd);
      return NULL;
    }
}