aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/section.c95
1 files changed, 59 insertions, 36 deletions
diff --git a/bfd/section.c b/bfd/section.c
index e4188a4..35d084a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -152,7 +152,6 @@ CODE_FRAGMENT
.
. CONST char *name;
.
-.
. {* Which section is it 0.nth *}
.
. int index;
@@ -172,36 +171,31 @@ CODE_FRAGMENT
. {* Tells the OS to allocate space for this section when loaded.
. This would 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 would be clear for a .bss section *}
-.
.#define SEC_LOAD 0x002
+.
. {* The section contains data still to be relocated, so there will
. be some relocation information too. *}
-.
.#define SEC_RELOC 0x004
.
-. {* Obsolete ? *}
-.
+.#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
+.#define SEC_DATA 0x040
.
. {* The section will reside in ROM. *}
-.
.#define SEC_ROM 0x080
.
. {* The section contains constructor information. This section
@@ -214,47 +208,54 @@ CODE_FRAGMENT
. sections called <<__CTOR_LIST__>> and relocte 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 . *}
-.
+. 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 not to output sections
. containing this flag even if they have information which
. would normally be written. *}
-.
.#define SEC_NEVER_LOAD 0x400
.
. {* The section is a shared library section. The linker must leave
. these completely alone, as the vma and size are used when
. the executable is loaded. *}
-.
.#define SEC_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 (.bss), but
-. ECOFF has two. *}
-.
+. used). Most targets have exactly one of these (which we
+. translate to bfd_com_section), but ECOFF has two. *}
.#define SEC_IS_COMMON 0x8000
-.
+.
+. {* 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 (eg, the
. size of <<.bss>>). This will be filled in after relocation *}
@@ -298,9 +299,9 @@ CODE_FRAGMENT
. unsigned reloc_count;
.
. {* Information below is back end specific - and not always used
-. or updated
+. or updated. *}
.
-. File position of section data *}
+. {* File position of section data *}
.
. file_ptr filepos;
.
@@ -350,29 +351,33 @@ CODE_FRAGMENT
. {* A symbol which points at this section only *}
. struct symbol_cache_entry *symbol;
. struct symbol_cache_entry **symbol_ptr_ptr;
+.
. struct bfd_seclet *seclets_head;
. struct bfd_seclet *seclets_tail;
.} asection ;
.
.
+. {* These sections are global, and are managed by BFD. The application
+. and target back end are not permitted to change the values in
+. these sections. *}
.#define BFD_ABS_SECTION_NAME "*ABS*"
.#define BFD_UND_SECTION_NAME "*UND*"
.#define BFD_COM_SECTION_NAME "*COM*"
.#define BFD_IND_SECTION_NAME "*IND*"
.
. {* the absolute section *}
-. extern asection bfd_abs_section;
+.extern asection bfd_abs_section;
. {* Pointer to the undefined section *}
-. extern asection bfd_und_section;
+.extern asection bfd_und_section;
. {* Pointer to the common section *}
-. extern asection bfd_com_section;
+.extern asection bfd_com_section;
. {* Pointer to the indirect section *}
-. extern asection bfd_ind_section;
+.extern asection bfd_ind_section;
.
-. extern struct symbol_cache_entry *bfd_abs_symbol;
-. extern struct symbol_cache_entry *bfd_com_symbol;
-. extern struct symbol_cache_entry *bfd_und_symbol;
-. extern struct symbol_cache_entry *bfd_ind_symbol;
+.extern struct symbol_cache_entry *bfd_abs_symbol;
+.extern struct symbol_cache_entry *bfd_com_symbol;
+.extern struct symbol_cache_entry *bfd_und_symbol;
+.extern struct symbol_cache_entry *bfd_ind_symbol;
.#define bfd_get_section_size_before_reloc(section) \
. (section->reloc_done ? (abort(),1): (section)->_raw_size)
.#define bfd_get_section_size_after_reloc(section) \
@@ -391,7 +396,7 @@ static CONST asymbol global_syms[] = {
#define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \
asymbol *SYM = (asymbol *) &global_syms[IDX]; \
- asection SEC = { NAME, 0, 0, FLAGS, 0, (boolean) 0, 0, 0, 0, &SEC,\
+ asection SEC = { NAME, 0, 0, FLAGS, 0, 0, (boolean) 0, 0, 0, 0, &SEC,\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \
(asymbol *) &global_syms[IDX], &SYM, }
@@ -757,7 +762,7 @@ DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
return(false);
}
- if (offset < 0 || count < 0)
+ if (offset < 0)
{
bad_val:
bfd_error = bad_value;
@@ -769,6 +774,24 @@ DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
|| offset + count > sz)
goto bad_val;
+ switch (abfd->direction)
+ {
+ case read_direction:
+ case no_direction:
+ bfd_error = invalid_operation;
+ return false;
+
+ case write_direction:
+ break;
+
+ case both_direction:
+ /* File is opened for update. `output_has_begun' some time ago when
+ the file was created. Do not recompute sections sizes or alignments
+ in _bfd_set_section_content. */
+ abfd->output_has_begun = true;
+ break;
+ }
+
if (BFD_SEND (abfd, _bfd_set_section_contents,
(abfd, section, location, offset, count)))
{
@@ -818,7 +841,7 @@ DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count),
return true;
}
- if (offset < 0 || count < 0)
+ if (offset < 0)
{
bad_val:
bfd_error = bad_value;
66'>466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
/* Handle PA64 shared libraries for GDB, the GNU Debugger.

   Copyright (C) 2004, 2007-2012 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* HP in their infinite stupidity choose not to use standard ELF dynamic
   linker interfaces.  They also choose not to make their ELF dymamic
   linker interfaces compatible with the SOM dynamic linker.  The
   net result is we can not use either of the existing somsolib.c or
   solib.c.  What a crock.

   Even more disgusting.  This file depends on functions provided only
   in certain PA64 libraries.  Thus this file is supposed to only be
   used native.  When will HP ever learn that they need to provide the
   same functionality in all their libraries!  */

#include "defs.h"
#include "symtab.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbcore.h"
#include "target.h"
#include "inferior.h"
#include "regcache.h"

#include "hppa-tdep.h"
#include "solist.h"
#include "solib.h"
#include "solib-pa64.h"

#undef SOLIB_PA64_DBG

/* We can build this file only when running natively on 64-bit HP/UX.
   We check for that by checking for the elf_hp.h header file.  */
#if defined(HAVE_ELF_HP_H) && defined(__LP64__)

/* FIXME: kettenis/20041213: These includes should be eliminated.  */
#include <dlfcn.h>
#include <elf.h>
#include <elf_hp.h>

struct lm_info {
  struct load_module_desc desc;
  CORE_ADDR desc_addr;
};

/* When adding fields, be sure to clear them in _initialize_pa64_solib.  */
typedef struct
  {
    CORE_ADDR dld_flags_addr;
    LONGEST dld_flags;
    struct bfd_section *dyninfo_sect;
    int have_read_dld_descriptor;
    int is_valid;
    CORE_ADDR load_map;
    CORE_ADDR load_map_addr;
    struct load_module_desc dld_desc;
  }
dld_cache_t;

static dld_cache_t dld_cache;

static int read_dynamic_info (asection *dyninfo_sect,
			      dld_cache_t *dld_cache_p);

static void
pa64_relocate_section_addresses (struct so_list *so,
				 struct target_section *sec)
{
  asection *asec = sec->the_bfd_section;
  CORE_ADDR load_offset;

  /* Relocate all the sections based on where they got loaded.  */

  load_offset = bfd_section_vma (so->abfd, asec) - asec->filepos;

  if (asec->flags & SEC_CODE)
    {
      sec->addr += so->lm_info->desc.text_base - load_offset;
      sec->endaddr += so->lm_info->desc.text_base - load_offset;
    }
  else if (asec->flags & SEC_DATA)
    {
      sec->addr += so->lm_info->desc.data_base - load_offset;
      sec->endaddr += so->lm_info->desc.data_base - load_offset;
    }
}

static void
pa64_free_so (struct so_list *so)
{
  xfree (so->lm_info);
}

static void
pa64_clear_solib (void)
{
}

/* Wrapper for target_read_memory for dlgetmodinfo.  */

static void *
pa64_target_read_memory (void *buffer, CORE_ADDR ptr, size_t bufsiz, int ident)
{
  if (target_read_memory (ptr, buffer, bufsiz) != 0)
    return 0;
  return buffer;
}

/* Read the dynamic linker's internal shared library descriptor.

   This must happen after dld starts running, so we can't do it in
   read_dynamic_info.  Record the fact that we have loaded the
   descriptor.  If the library is archive bound or the load map
   hasn't been setup, then return zero; else return nonzero.  */

static int
read_dld_descriptor (void)
{
  char *dll_path;
  asection *dyninfo_sect;

  /* If necessary call read_dynamic_info to extract the contents of the
     .dynamic section from the shared library.  */
  if (!dld_cache.is_valid) 
    {
      if (symfile_objfile == NULL)
	error (_("No object file symbols."));

      dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd, 
					      ".dynamic");
      if (!dyninfo_sect) 
	{
	  return 0;
	}

      if (!read_dynamic_info (dyninfo_sect, &dld_cache))
	error (_("Unable to read in .dynamic section information."));
    }

  /* Read the load map pointer.  */
  if (target_read_memory (dld_cache.load_map_addr,
			  (char *) &dld_cache.load_map,
			  sizeof (dld_cache.load_map))
      != 0)
    {
      error (_("Error while reading in load map pointer."));
    }

  if (!dld_cache.load_map)
    return 0;

  /* Read in the dld load module descriptor.  */
  if (dlgetmodinfo (-1, 
		    &dld_cache.dld_desc,
		    sizeof (dld_cache.dld_desc), 
		    pa64_target_read_memory, 
		    0, 
		    dld_cache.load_map)
      == 0)
    {
      error (_("Error trying to get information about dynamic linker."));
    }

  /* Indicate that we have loaded the dld descriptor.  */
  dld_cache.have_read_dld_descriptor = 1;

  return 1;
}


/* Read the .dynamic section and extract the information of interest,
   which is stored in dld_cache.  The routine elf_locate_base in solib.c 
   was used as a model for this.  */

static int
read_dynamic_info (asection *dyninfo_sect, dld_cache_t *dld_cache_p)
{
  char *buf;
  char *bufend;
  CORE_ADDR dyninfo_addr;
  int dyninfo_sect_size;
  CORE_ADDR entry_addr;

  /* Read in .dynamic section, silently ignore errors.  */
  dyninfo_addr = bfd_section_vma (symfile_objfile->obfd, dyninfo_sect);
  dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
  buf = alloca (dyninfo_sect_size);
  if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
    return 0;

  /* Scan the .dynamic section and record the items of interest. 
     In particular, DT_HP_DLD_FLAGS.  */
  for (bufend = buf + dyninfo_sect_size, entry_addr = dyninfo_addr;
       buf < bufend;
       buf += sizeof (Elf64_Dyn), entry_addr += sizeof (Elf64_Dyn))
    {
      Elf64_Dyn *x_dynp = (Elf64_Dyn*)buf;
      Elf64_Sxword dyn_tag;
      CORE_ADDR	dyn_ptr;

      dyn_tag = bfd_h_get_64 (symfile_objfile->obfd, 
			      (bfd_byte*) &x_dynp->d_tag);

      /* We can't use a switch here because dyn_tag is 64 bits and HP's
	 lame comiler does not handle 64bit items in switch statements.  */
      if (dyn_tag == DT_NULL)
	break;
      else if (dyn_tag == DT_HP_DLD_FLAGS)
	{
	  /* Set dld_flags_addr and dld_flags in *dld_cache_p.  */
	  dld_cache_p->dld_flags_addr = entry_addr + offsetof(Elf64_Dyn, d_un);
	  if (target_read_memory (dld_cache_p->dld_flags_addr,
	  			  (char*) &dld_cache_p->dld_flags, 
				  sizeof (dld_cache_p->dld_flags))
	      != 0)
	    {
	      error (_("Error while reading in "