diff options
34 files changed, 1883 insertions, 1554 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 50e2546..5b6eee2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,51 @@ +2002-08-24 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * elf32-sh.c (sh_elf_copy_indirect_symbol): New. + (create_got_section, allocate_dynrelocs, readonly_dynrelocs): + Likewise. + (struct elf_sh_pcrel_relocs_copied): Removed. + (struct elf_sh_dyn_relocs): New. + (struct elf_sh_link_hash_entry): Replace pcrel_relocs_copied + field with dyn_relocs. + (struct elf_sh_link_hash_table): Add short-cuts to get dynamic + sections and sym_sec. + (sh_elf_link_hash_newfunc): Clear dyn_relocs. + (sh_elf_link_hash_table_create): Clear shorts-cuts and sym_sec. + (sh_elf_create_dynamic_sections): Use create_got_section instead + of _bfd_elf_create_got_section. + (sh_elf_check_relocs): Likewise. + (sh_elf_create_dynamic_sections): Use short-cuts to the dynamic + sections. + (sh_elf_adjust_dynamic_symbol, sh_elf_size_dynamic_sections, + sh_elf_relocate_section, sh_elf_check_relocs, + sh_elf_finish_dynamic_symbol, sh_elf_finish_dynamic_sections): + Likewise. + (sh_elf_adjust_dynamic_symbol): Handle nocopyreloc. Keep the + dynamic relocations and avoiding the copy relocation when we + didn't find any dynamic relocations in the section which has + contents or is read-only. + (WILL_CALL_FINISH_DYNAMIC_SYMBOL): New. + (sh_elf_size_dynamic_sections): Don't reset the size of + .rela.got section even if dynamic_sections_created flag is off. + Don't use sh_elf_discard_copies. Scan all input bfd and use + allocate_dynrelocs. Call readonly_dynrelocs to determine + whether we need DT_TEXTREL. + (sh_elf_adjust_dynamic_symbol): Use plt.refcount to determine + whether the symbol was never referred to. + (sh_elf_relocate_section): Use WILL_CALL_FINISH_DYNAMIC_SYMBOL. + (sh_elf_gc_sweep_hook): Fill with the real sweep function. + (sh_elf_check_relocs): Call create_got_section if the short-cut + to .got is null. Increment reference counters only instead of + allocating space on dynamic sections here. Don't conditionalize + uninitialized got.offset value when marking the symbol as a + global offset table entry. Keep relocations for symbols satisfied + by a dynamic library to avoid copy relocations for the symbol. + Set dynobj field of an elf hash table if needed. + (sh_elf_finish_dynamic_sections): Handle null section pointer + correctly. + (elf_backend_copy_indirect_symbol): Defined. + (elf_backend_can_refcount): Defined. + 2002-08-23 Nick Clifton <nickc@redhat.com> * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Undo diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index c8f179b..c8bbe71 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -56,6 +56,9 @@ static boolean sh_elf_relocate_section static bfd_byte *sh_elf_get_relocated_section_contents PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, boolean, asymbol **)); +static void sh_elf_copy_indirect_symbol + PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *, + struct elf_link_hash_entry *)); static boolean sh_elf_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); @@ -75,6 +78,8 @@ static boolean sh_elf_finish_dynamic_sections static bfd_reloc_status_type sh_elf_reloc_loop PARAMS ((int, bfd *, asection *, bfd_byte *, bfd_vma, asection *, bfd_vma, bfd_vma)); +static boolean create_got_section + PARAMS((bfd *, struct bfd_link_info *)); static boolean sh_elf_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static asection * sh_elf_gc_mark_hook @@ -83,6 +88,10 @@ static asection * sh_elf_gc_mark_hook static boolean sh_elf_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); +static boolean allocate_dynrelocs + PARAMS ((struct elf_link_hash_entry *, PTR)); +static boolean readonly_dynrelocs + PARAMS ((struct elf_link_hash_entry *, PTR)); static enum elf_reloc_type_class sh_elf_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); #ifdef INCLUDE_SHMEDIA @@ -430,33 +439,33 @@ static reloc_howto_type sh_elf_howto_table[] = /* GNU extension to record C++ vtable hierarchy */ HOWTO (R_SH_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - NULL, /* special_function */ - "R_SH_GNU_VTINHERIT", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_SH_GNU_VTINHERIT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage */ HOWTO (R_SH_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_SH_GNU_VTENTRY", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_SH_GNU_VTENTRY", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ /* 8 bit PC relative divided by 2 - but specified in a very odd way. */ HOWTO (R_SH_LOOP_START, /* type */ @@ -510,7 +519,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xfc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in SHARI, SHLLI et al. */ HOWTO (R_SH_DIR6U, /* type */ @@ -525,7 +534,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xfc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in BxxI, LDHI.L et al. */ HOWTO (R_SH_DIR6S, /* type */ @@ -540,7 +549,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xfc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in ADDI, ANDI et al. */ HOWTO (R_SH_DIR10S, /* type */ @@ -555,9 +564,9 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ - /* Used in LD.UW, ST.W et al. */ + /* Used in LD.UW, ST.W et al. */ HOWTO (R_SH_DIR10SW, /* type */ 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -570,9 +579,9 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ - /* Used in LD.L, FLD.S et al. */ + /* Used in LD.L, FLD.S et al. */ HOWTO (R_SH_DIR10SL, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -585,7 +594,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in FLD.D, FST.P et al. */ HOWTO (R_SH_DIR10SQ, /* type */ @@ -600,7 +609,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ #else EMPTY_HOWTO (45), @@ -857,11 +866,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_GOT_LOW16", /* name */ + "R_SH_GOT_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 16) & 65536). */ HOWTO (R_SH_GOT_MEDLOW16, /* type */ @@ -876,7 +885,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 32) & 65536). */ HOWTO (R_SH_GOT_MEDHI16, /* type */ @@ -891,7 +900,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 48) & 65536). */ HOWTO (R_SH_GOT_HI16, /* type */ @@ -906,7 +915,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (x & 65536). */ HOWTO (R_SH_GOTPLT_LOW16, /* type */ @@ -917,11 +926,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_GOTPLT_LOW16", /* name */ + "R_SH_GOTPLT_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 16) & 65536). */ HOWTO (R_SH_GOTPLT_MEDLOW16, /* type */ @@ -936,7 +945,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 32) & 65536). */ HOWTO (R_SH_GOTPLT_MEDHI16, /* type */ @@ -951,7 +960,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 48) & 65536). */ HOWTO (R_SH_GOTPLT_HI16, /* type */ @@ -966,7 +975,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (x & 65536). */ HOWTO (R_SH_PLT_LOW16, /* type */ @@ -977,11 +986,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_PLT_LOW16", /* name */ + "R_SH_PLT_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 16) & 65536). */ HOWTO (R_SH_PLT_MEDLOW16, /* type */ @@ -996,7 +1005,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 32) & 65536). */ HOWTO (R_SH_PLT_MEDHI16, /* type */ @@ -1011,7 +1020,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 48) & 65536). */ HOWTO (R_SH_PLT_HI16, /* type */ @@ -1026,7 +1035,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI (x & 65536). */ HOWTO (R_SH_GOTOFF_LOW16, /* type */ @@ -1037,11 +1046,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_GOTOFF_LOW16", /* name */ + "R_SH_GOTOFF_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 16) & 65536). */ HOWTO (R_SH_GOTOFF_MEDLOW16, /* type */ @@ -1056,7 +1065,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 32) & 65536). */ HOWTO (R_SH_GOTOFF_MEDHI16, /* type */ @@ -1071,7 +1080,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 48) & 65536). */ HOWTO (R_SH_GOTOFF_HI16, /* type */ @@ -1086,7 +1095,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (x & 65536). */ HOWTO (R_SH_GOTPC_LOW16, /* type */ @@ -1097,11 +1106,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_GOTPC_LOW16", /* name */ + "R_SH_GOTPC_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 16) & 65536). */ HOWTO (R_SH_GOTPC_MEDLOW16, /* type */ @@ -1116,7 +1125,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 32) & 65536). */ HOWTO (R_SH_GOTPC_MEDHI16, /* type */ @@ -1131,7 +1140,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ /* Used in MOVI and SHORI ((x >> 48) & 65536). */ HOWTO (R_SH_GOTPC_HI16, /* type */ @@ -1146,9 +1155,9 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - true), /* pcrel_offset */ + true), /* pcrel_offset */ - /* Used in LD.L, FLD.S et al. */ + /* Used in LD.L, FLD.S et al. */ HOWTO (R_SH_GOT10BY4, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1161,9 +1170,9 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ - /* Used in LD.L, FLD.S et al. */ + /* Used in LD.L, FLD.S et al. */ HOWTO (R_SH_GOTPLT10BY4, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1176,7 +1185,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in FLD.D, FST.P et al. */ HOWTO (R_SH_GOT10BY8, /* type */ @@ -1191,7 +1200,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in FLD.D, FST.P et al. */ HOWTO (R_SH_GOTPLT10BY8, /* type */ @@ -1206,7 +1215,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0xffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ HOWTO (R_SH_COPY64, /* type */ 0, /* rightshift */ @@ -1216,11 +1225,11 @@ static reloc_howto_type sh_elf_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_COPY64", /* name */ + "R_SH_COPY64", /* name */ false, /* partial_inplace */ 0, /* src_mask */ ((bfd_vma) 0) - 1, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ HOWTO (R_SH_GLOB_DAT64, /* type */ 0, /* rightshift */ @@ -1230,11 +1239,11 @@ static reloc_howto_type sh_elf_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_GLOB_DAT64", /* name */ + "R_SH_GLOB_DAT64", /* name */ false, /* partial_inplace */ 0, /* src_mask */ ((bfd_vma) 0) - 1, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ HOWTO (R_SH_JMP_SLOT64, /* type */ 0, /* rightshift */ @@ -1244,11 +1253,11 @@ static reloc_howto_type sh_elf_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_JMP_SLOT64", /* name */ + "R_SH_JMP_SLOT64", /* name */ false, /* partial_inplace */ 0, /* src_mask */ ((bfd_vma) 0) - 1, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ HOWTO (R_SH_RELATIVE64, /* type */ 0, /* rightshift */ @@ -1258,11 +1267,11 @@ static reloc_howto_type sh_elf_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_RELATIVE64", /* name */ + "R_SH_RELATIVE64", /* name */ false, /* partial_inplace */ 0, /* src_mask */ ((bfd_vma) 0) - 1, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ EMPTY_HOWTO (197), EMPTY_HOWTO (198), @@ -1363,7 +1372,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in SHORI. */ HOWTO (R_SH_IMMU16, /* type */ @@ -1378,7 +1387,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (x & 65536). */ HOWTO (R_SH_IMM_LOW16, /* type */ @@ -1389,11 +1398,11 @@ static reloc_howto_type sh_elf_howto_table[] = 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_IMM_LOW16", /* name */ + "R_SH_IMM_LOW16", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI ((x - $) & 65536). */ HOWTO (R_SH_IMM_LOW16_PCREL, /* type */ @@ -1423,7 +1432,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (((x - $) >> 16) & 65536). */ HOWTO (R_SH_IMM_MEDLOW16_PCREL, /* type */ @@ -1453,7 +1462,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (((x - $) >> 32) & 65536). */ HOWTO (R_SH_IMM_MEDHI16_PCREL, /* type */ @@ -1483,7 +1492,7 @@ static reloc_howto_type sh_elf_howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* Used in MOVI and SHORI (((x - $) >> 48) & 65536). */ HOWTO (R_SH_IMM_HI16_PCREL, /* type */ @@ -1509,11 +1518,11 @@ static reloc_howto_type sh_elf_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SH_64", /* name */ + "R_SH_64", /* name */ false, /* partial_inplace */ 0, /* src_mask */ ((bfd_vma) 0) - 1, /* dst_mask */ - false), /* pcrel_offset */ + false), /* pcrel_offset */ /* For the .uaquad pseudo, (x - $). */ HOWTO (R_SH_64_PCREL, /* type */ @@ -1955,9 +1964,9 @@ sh_elf_relax_section (abfd, sec, link_info, again) } /* The r_addend field of the R_SH_USES reloc will point us to - the register load. The 4 is because the r_addend field is - computed as though it were a jump offset, which are based - from 4 bytes after the jump instruction. */ + the register load. The 4 is because the r_addend field is + computed as though it were a jump offset, which are based + from 4 bytes after the jump instruction. */ laddr = irel->r_offset + 4 + irel->r_addend; if (laddr >= sec->_raw_size) { @@ -1969,7 +1978,7 @@ sh_elf_relax_section (abfd, sec, link_info, again) insn = bfd_get_16 (abfd, contents + laddr); /* If the instruction is not mov.l NN,rN, we don't know what to - do. */ + do. */ if ((insn & 0xf000) != 0xd000) { ((*_bfd_error_handler) @@ -1996,8 +2005,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) } /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is - actually being called. */ + being loaded. This reloc will tell us which function is + actually being called. */ for (irelfn = internal_relocs; irelfn < irelend; irelfn++) if (irelfn->r_offset == paddr && ELF32_R_TYPE (irelfn->r_info) == (int) R_SH_DIR32) @@ -2054,8 +2063,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) && h->root.type != bfd_link_hash_defweak) { /* This appears to be a reference to an undefined - symbol. Just ignore it--it will be caught by the - regular reloc processing. */ + symbol. Just ignore it--it will be caught by the + regular reloc processing. */ continue; } @@ -2095,13 +2104,13 @@ sh_elf_relax_section (abfd, sec, link_info, again) /* Replace the jsr with a bsr. */ /* Change the R_SH_USES reloc into an R_SH_IND12W reloc, and - replace the jsr with a bsr. */ + replace the jsr with a bsr. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_SH_IND12W); if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info) { /* If this needs to be changed because of future relaxing, - it will be handled here like other internal IND12W - relocs. */ + it will be handled here like other internal IND12W + relocs. */ bfd_put_16 (abfd, (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff), contents + irel->r_offset); @@ -2109,13 +2118,13 @@ sh_elf_relax_section (abfd, sec, link_info, again) else { /* We can't fully resolve this yet, because the external - symbol value may be changed by future relaxing. We let - the final link phase handle it. */ + symbol value may be changed by future relaxing. We let + the final link phase handle it. */ bfd_put_16 (abfd, (bfd_vma) 0xb000, contents + irel->r_offset); } /* See if there is another R_SH_USES reloc referring to the same - register load. */ + register load. */ for (irelscan = internal_relocs; irelscan < irelend; irelscan++) if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_USES && laddr == irelscan->r_offset + 4 + irelscan->r_addend) @@ -2130,8 +2139,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) } /* Look for a R_SH_COUNT reloc on the location where the - function address is stored. Do this before deleting any - bytes, to avoid confusion about the address. */ + function address is stored. Do this before deleting any + bytes, to avoid confusion about the address. */ for (irelcount = internal_relocs; irelcount < irelend; irelcount++) if (irelcount->r_offset == paddr && ELF32_R_TYPE (irelcount->r_info) == (int) R_SH_COUNT) @@ -2142,8 +2151,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) goto error_return; /* That will change things, so, just in case it permits some - other function call to come within range, we should relax - again. Note that this is not required, and it may be slow. */ + other function call to come within range, we should relax + again. Note that this is not required, and it may be slow. */ *again = true; /* Now check whether we got a COUNT reloc. */ @@ -2156,7 +2165,7 @@ sh_elf_relax_section (abfd, sec, link_info, again) } /* The number of uses is stored in the r_addend field. We've - just deleted one. */ + just deleted one. */ if (irelcount->r_addend == 0) { ((*_bfd_error_handler) (_("%s: 0x%lx: warning: bad count"), @@ -2168,8 +2177,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) --irelcount->r_addend; /* If there are no more uses, we can delete the address. Reload - the address from irelfn, in case it was changed by the - previous call to sh_elf_relax_delete_bytes. */ + the address from irelfn, in case it was changed by the + previous call to sh_elf_relax_delete_bytes. */ if (irelcount->r_addend == 0) { if (! sh_elf_relax_delete_bytes (abfd, sec, irelfn->r_offset, 4)) @@ -2355,7 +2364,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) (int) R_SH_NONE); /* If this is a PC relative reloc, see if the range it covers - includes the bytes we have deleted. */ + includes the bytes we have deleted. */ switch ((enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info)) { default: @@ -2378,9 +2387,9 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) case R_SH_DIR32: /* If this reloc is against a symbol defined in this - section, and the symbol will not be adjusted below, we - must check the addend to see it will put the value in - range to be adjusted, and hence must be changed. */ + section, and the symbol will not be adjusted below, we + must check the addend to see it will put the value in + range to be adjusted, and hence must be changed. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { isym = isymbuf + ELF32_R_SYM (irel->r_info); @@ -2572,8 +2581,8 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) continue; /* We always cache the relocs. Perhaps, if info->keep_memory is - false, we should free them, if we are permitted to, when we - leave sh_coff_relax_section. */ + false, we should free them, if we are permitted to, when we + leave sh_coff_relax_section. */ internal_relocs = (_bfd_elf32_link_read_relocs (abfd, o, (PTR) NULL, (Elf_Internal_Rela *) NULL, true)); @@ -2597,9 +2606,9 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) else { /* We always cache the section contents. - Perhaps, if info->keep_memory is false, we - should free them, if we are permitted to, - when we leave sh_coff_relax_section. */ + Perhaps, if info->keep_memory is false, we + should free them, if we are permitted to, + when we leave sh_coff_relax_section. */ ocontents = (bfd_byte *) bfd_malloc (o->_raw_size); if (ocontents == NULL) return false; @@ -2655,9 +2664,9 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) else { /* We always cache the section contents. - Perhaps, if info->keep_memory is false, we - should free them, if we are permitted to, - when we leave sh_coff_relax_section. */ + Perhaps, if info->keep_memory is false, we + should free them, if we are permitted to, + when we leave sh_coff_relax_section. */ ocontents = (bfd_byte *) bfd_malloc (o->_raw_size); if (ocontents == NULL) return false; @@ -2829,8 +2838,8 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr) int add; /* There are a few special types of relocs that we don't want to - adjust. These relocs do not apply to the instruction itself, - but are only associated with the address. */ + adjust. These relocs do not apply to the instruction itself, + but are only associated with the address. */ type = (enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info); if (type == R_SH_ALIGN || type == R_SH_CODE @@ -2839,11 +2848,11 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr) continue; /* If an R_SH_USES reloc points to one of the addresses being - swapped, we must adjust it. It would be incorrect to do this - for a jump, though, since we want to execute both - instructions after the jump. (We have avoided swapping - around a label, so the jump will not wind up executing an - instruction it shouldn't). */ + swapped, we must adjust it. It would be incorrect to do this + for a jump, though, since we want to execute both + instructions after the jump. (We have avoided swapping + around a label, so the jump will not wind up executing an + instruction it shouldn't). */ if (type == R_SH_USES) { bfd_vma off; @@ -2902,11 +2911,11 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr) case R_SH_DIR8WPL: /* This reloc ignores the least significant 3 bits of - the program counter before adding in the offset. - This means that if ADDR is at an even address, the - swap will not affect the offset. If ADDR is an at an - odd address, then the instruction will be crossing a - four byte boundary, and must be adjusted. */ + the program counter before adding in the offset. + This means that if ADDR is at an even address, the + swap will not affect the offset. If ADDR is an at an + odd address, then the instruction will be crossing a + four byte boundary, and must be adjusted. */ if ((addr & 3) != 0) { insn = bfd_get_16 (abfd, loc); @@ -3348,22 +3357,23 @@ static const bfd_byte *elf_sh_pic_plt_entry; #endif /* The sh linker needs to keep track of the number of relocs that it - decides to copy in check_relocs for each symbol. This is so that - it can discard PC relative relocs if it doesn't need them when - linking with -Bsymbolic. We store the information in a field - extending the regular ELF linker hash table. */ - -/* This structure keeps track of the number of PC relative relocs we - have copied for a given symbol. */ + decides to copy as dynamic relocs in check_relocs for each symbol. + This is so that it can later discard them if they are found to be + unnecessary. We store the information in a field extending the + regular ELF linker hash table. */ -struct elf_sh_pcrel_relocs_copied +struct elf_sh_dyn_relocs { - /* Next section. */ - struct elf_sh_pcrel_relocs_copied *next; - /* A section in dynobj. */ - asection *section; - /* Number of relocs copied in this section. */ + struct elf_sh_dyn_relocs *next; + + /* The input section of the reloc. */ + asection *sec; + + /* Total number of relocs copied for the input section. */ bfd_size_type count; + + /* Number of pc-relative relocs copied for the input section. */ + bfd_size_type pc_count; }; /* sh ELF linker hash entry. */ @@ -3376,8 +3386,8 @@ struct elf_sh_link_hash_entry bfd_vma datalabel_got_offset; #endif - /* Number of PC relative relocs copied for this symbol. */ - struct elf_sh_pcrel_relocs_copied *pcrel_relocs_copied; + /* Track dynamic relocs copied for this symbol. */ + struct elf_sh_dyn_relocs *dyn_relocs; }; /* sh ELF linker hash table. */ @@ -3385,12 +3395,19 @@ struct elf_sh_link_hash_entry struct elf_sh_link_hash_table { struct elf_link_hash_table root; -}; -/* Declare this now that the above structures are defined. */ + /* Short-cuts to get to dynamic linker sections. */ + asection *sgot; + asection *sgotplt; + asection *srelgot; + asection *splt; + asection *srelplt; + asection *sdynbss; + asection *srelbss; -static boolean sh_elf_discard_copies - PARAMS ((struct elf_sh_link_hash_entry *, PTR)); + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; +}; /* Traverse an sh ELF linker hash table. */ @@ -3431,7 +3448,10 @@ sh_elf_link_hash_newfunc (entry, table, string) table, string)); if (ret != (struct elf_sh_link_hash_entry *) NULL) { - ret->pcrel_relocs_copied = NULL; + struct elf_sh_link_hash_entry *eh; + + eh = (struct elf_sh_link_hash_entry *) ret; + eh->dyn_relocs = NULL; #ifdef INCLUDE_SHMEDIA ret->datalabel_got_offset = (bfd_vma) -1; #endif @@ -3460,9 +3480,51 @@ sh_elf_link_hash_table_create (abfd) return NULL; } + ret->sgot = NULL; + ret->sgotplt = NULL; + ret->srelgot = NULL; + ret->splt = NULL; + ret->srelplt = NULL; + ret->sdynbss = NULL; + ret->srelbss = NULL; + ret->sym_sec.abfd = NULL; + return &ret->root.root; } +/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up + shortcuts to them in our hash table. */ + +static boolean +create_got_section (dynobj, info) + bfd *dynobj; + struct bfd_link_info *info; +{ + struct elf_sh_link_hash_table *htab; + + if (! _bfd_elf_create_got_section (dynobj, info)) + return false; + + htab = sh_elf_hash_table (info); + htab->sgot = bfd_get_section_by_name (dynobj, ".got"); + htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); + if (! htab->sgot || ! htab->sgotplt) + abort (); + + htab->srelgot = bfd_make_section (dynobj, ".rela.got"); + if (htab->srelgot == NULL + || ! bfd_set_section_flags (dynobj, htab->srelgot, + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)) + || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) + return false; + return true; +} + /* Create dynamic sections when linking against a dynamic object. */ static boolean @@ -3470,6 +3532,7 @@ sh_elf_create_dynamic_sections (abfd, info) bfd *abfd; struct bfd_link_info *info; { + struct elf_sh_link_hash_table *htab; flagword flags, pltflags; register asection *s; struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -3490,6 +3553,8 @@ sh_elf_create_dynamic_sections (abfd, info) return false; } + htab = sh_elf_hash_table (info); + /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and .rel[a].bss sections. */ @@ -3504,6 +3569,7 @@ sh_elf_create_dynamic_sections (abfd, info) pltflags |= SEC_READONLY; s = bfd_make_section (abfd, ".plt"); + htab->splt = s; if (s == NULL || ! bfd_set_section_flags (abfd, s, pltflags) || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) @@ -3530,12 +3596,13 @@ sh_elf_create_dynamic_sections (abfd, info) s = bfd_make_section (abfd, bed->default_use_rela_p ? ".rela.plt" : ".rel.plt"); + htab->srelplt = s; if (s == NULL || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, ptralign)) return false; - if (! _bfd_elf_create_got_section (abfd, info)) + if (! create_got_section (abfd, info)) return false; { @@ -3571,6 +3638,7 @@ sh_elf_create_dynamic_sections (abfd, info) initialize them at run time. The linker script puts the .dynbss section into the .bss section of the final image. */ s = bfd_make_section (abfd, ".dynbss"); + htab->sdynbss = s; if (s == NULL || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) return false; @@ -3591,6 +3659,7 @@ sh_elf_create_dynamic_sections (abfd, info) s = bfd_make_section (abfd, (bed->default_use_rela_p ? ".rela.bss" : ".rel.bss")); + htab->srelbss = s; if (s == NULL || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, ptralign)) @@ -3612,6 +3681,9 @@ sh_elf_adjust_dynamic_symbol (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h; { + struct elf_sh_link_hash_table *htab; + struct elf_sh_link_hash_entry *eh; + struct elf_sh_dyn_relocs *p; bfd *dynobj; asection *s; unsigned int power_of_two; @@ -3635,66 +3707,26 @@ sh_elf_adjust_dynamic_symbol (info, h) if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) + if (h->plt.refcount <= 0 + || (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 + && h->root.type != bfd_link_hash_undefweak + && h->root.type != bfd_link_hash_undefined)) { /* This case can occur if we saw a PLT reloc in an input file, but the symbol was never referred to by a dynamic object. In such a case, we don't actually need to build a procedure linkage table, and we can just do a REL32 reloc instead. */ - BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); - return true; + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; - } - - s = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (s != NULL); - - /* If this is the first .plt entry, make room for the special - first entry. */ - if (s->_raw_size == 0) - s->_raw_size += PLT_ENTRY_SIZE; - - /* If this symbol is not defined in a regular file, and we are - not generating a shared library, then set the symbol to this - location in the .plt. This is required to make function - pointers compare as equal between the normal executable and - the shared library. */ - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - { - h->root.u.def.section = s; - h->root.u.def.value = s->_raw_size; - } - - h->plt.offset = s->_raw_size; - - /* Make room for this entry. */ - s->_raw_size += elf_sh_sizeof_plt (info); - - /* We also need to make an entry in the .got.plt section, which - will be placed in the .got section by the linker script. */ - - s = bfd_get_section_by_name (dynobj, ".got.plt"); - BFD_ASSERT (s != NULL); - s->_raw_size += 4; - - /* We also need to make an entry in the .rela.plt section. */ - - s = bfd_get_section_by_name (dynobj, ".rela.plt"); - BFD_ASSERT (s != NULL); - s->_raw_size += sizeof (Elf32_External_Rela); - return true; } + else + h->plt.offset = (bfd_vma) -1; /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the @@ -3723,6 +3755,30 @@ sh_elf_adjust_dynamic_symbol (info, h) if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) return true; + /* If -z nocopyreloc was given, we won't generate them either. */ + if (info->nocopyreloc) + { + h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + return true; + } + + eh = (struct elf_sh_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + s = p->sec->output_section; + if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0) + break; + } + + /* If we didn't find any dynamic relocs in sections which needs the + copy reloc, then we'll be keeping the dynamic relocs and avoiding + the copy reloc. */ + if (p == NULL) + { + h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + return true; + } + /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be an entry for this symbol in the .dynsym section. The dynamic @@ -3733,7 +3789,8 @@ sh_elf_adjust_dynamic_symbol (info, h) both the dynamic object and the regular object will refer to the same memory location for the variable. */ - s = bfd_get_section_by_name (dynobj, ".dynbss"); + htab = sh_elf_hash_table (info); + s = htab->sdynbss; BFD_ASSERT (s != NULL); /* We must generate a R_SH_COPY reloc to tell the dynamic linker to @@ -3744,7 +3801,7 @@ sh_elf_adjust_dynamic_symbol (info, h) { asection *srel; - srel = bfd_get_section_by_name (dynobj, ".rela.bss"); + srel = htab->srelbss; BFD_ASSERT (srel != NULL); srel->_raw_size += sizeof (Elf32_External_Rela); h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; @@ -3757,8 +3814,7 @@ sh_elf_adjust_dynamic_symbol (info, h) power_of_two = 3; /* Apply the required alignment. */ - s->_raw_size = BFD_ALIGN (s->_raw_size, - (bfd_size_type) (1 << power_of_two)); + s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); if (power_of_two > bfd_get_section_alignment (dynobj, s)) { if (! bfd_set_section_alignment (dynobj, s, power_of_two)) @@ -3775,6 +3831,239 @@ sh_elf_adjust_dynamic_symbol (info, h) return true; } +/* This is the condition under which sh_elf_finish_dynamic_symbol + will be called from elflink.h. If elflink.h doesn't call our + finish_dynamic_symbol routine, we'll need to do something about + initializing any .plt and .got entries in sh_elf_relocate_section. */ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ + ((DYN) \ + && ((INFO)->shared \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ + && ((H)->dynindx != -1 \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) + +/* Allocate space in .plt, .got and associated reloc sections for + dynamic relocs. */ + +static boolean +allocate_dynrelocs (h, inf) + struct elf_link_hash_entry *h; + PTR inf; +{ + struct bfd_link_info *info; + struct elf_sh_link_hash_table *htab; + struct elf_sh_link_hash_entry *eh; + struct elf_sh_dyn_relocs *p; + + if (h->root.type == bfd_link_hash_indirect) + return true; + + if (h->root.type == bfd_link_hash_warning) + /* When warning symbols are created, they **replace** the "real" + entry in the hash table, thus we never get to see the real + symbol in a hash traversal. So look at it now. */ + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + info = (struct bfd_link_info *) inf; + htab = sh_elf_hash_table (info); + + if (htab->root.dynamic_sections_created + && h->plt.refcount > 0) + { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) + { + asection *s = htab->splt; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (s->_raw_size == 0) + s->_raw_size += PLT_ENTRY_SIZE; + + h->plt.offset = s->_raw_size; + + /* If this symbol is not defined in a regular file, and we are + not generating a shared library, then set the symbol to this + location in the .plt. This is required to make function + pointers compare as equal between the normal executable and + the shared library. */ + if (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + { + h->root.u.def.section = s; + h->root.u.def.value = h->plt.offset; + } + + /* Make room for this entry. */ + s->_raw_size += PLT_ENTRY_SIZE; + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ + htab->sgotplt->_raw_size += 4; + + /* We also need to make an entry in the .rel.plt section. */ + htab->srelplt->_raw_size += sizeof (Elf32_External_Rela); + } + else + { + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + } + } + else + { + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + } + + if (h->got.refcount > 0) + { + asection *s; + boolean dyn; + + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + + s = htab->sgot; +#ifdef INCLUDE_SHMEDIA + if (h->type == STT_DATALABEL) + { + struct elf_sh_link_hash_entry *hsh; + + h = (struct elf_link_hash_entry *) h->root.u.i.link; + hsh = (struct elf_sh_link_hash_entry *)h; + hsh->datalabel_got_offset = s->_raw_size; + } + else + h->got.offset = s->_raw_size; +#else + h->got.offset = s->_raw_size; +#endif + s->_raw_size += 4; + dyn = htab->root.dynamic_sections_created; + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) + htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); + } + else + h->got.offset = (bfd_vma) -1; + + eh = (struct elf_sh_link_hash_entry *) h; + if (eh->dyn_relocs == NULL) + return true; + + /* In the shared -Bsymbolic case, discard space allocated for + dynamic pc-relative relocs against symbols which turn out to be + defined in regular objects. For the normal shared case, discard + space for pc-relative relocs that have become local due to symbol + visibility changes. */ + + if (info->shared) + { + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 + && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 + || info->symbolic)) + { + struct elf_sh_dyn_relocs **pp; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + p->count -= p->pc_count; + p->pc_count = 0; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + } + } + else + { + /* For the non-shared case, discard space for relocs against + symbols which turn out to need copy relocs or are not + dynamic. */ + + if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + || (htab->root.dynamic_sections_created + && (h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_undefined)))) + { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + + /* If that succeeded, we know we'll be keeping all the + relocs. */ + if (h->dynindx != -1) + goto keep; + } + + eh->dyn_relocs = NULL; + + keep: ; + } + + /* Finally, allocate space. */ + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + asection *sreloc = elf_section_data (p->sec)->sreloc; + sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela); + } + + return true; +} + +/* Find any dynamic relocs that apply to read-only sections. */ + +static boolean +readonly_dynrelocs (h, inf) + struct elf_link_hash_entry *h; + PTR inf; +{ + struct elf_sh_link_hash_entry *eh; + struct elf_sh_dyn_relocs *p; + + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + eh = (struct elf_sh_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec->output_section; + + if (s != NULL && (s->flags & SEC_READONLY) != 0) + { + struct bfd_link_info *info = (struct bfd_link_info *) inf; + + info->flags |= DF_TEXTREL; + + /* Not an error, just cut short the traversal. */ + return false; + } + } + return true; +} + /* Set the sizes of the dynamic sections. */ static boolean @@ -3782,15 +4071,17 @@ sh_elf_size_dynamic_sections (output_bfd, info) bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; { + struct elf_sh_link_hash_table *htab; bfd *dynobj; asection *s; - boolean plt; boolean relocs; + bfd *ibfd; - dynobj = elf_hash_table (info)->dynobj; + htab = sh_elf_hash_table (info); + dynobj = htab->root.dynobj; BFD_ASSERT (dynobj != NULL); - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ if (! info->shared) @@ -3801,106 +4092,135 @@ sh_elf_size_dynamic_sections (output_bfd, info) s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } - else - { - /* We may have created entries in the .rela.got section. - However, if we are not creating the dynamic sections, we will - not actually use these entries. Reset the size of .rela.got, - which will cause it to get stripped from the output file - below. */ - s = bfd_get_section_by_name (dynobj, ".rela.got"); - if (s != NULL) - s->_raw_size = 0; - } - /* If this is a -Bsymbolic shared link, then we need to discard all - PC relative relocs against symbols defined in a regular object. - We allocated space for them in the check_relocs routine, but we - will not fill them in in the relocate_section routine. */ - if (info->shared && info->symbolic) - sh_elf_link_hash_traverse (sh_elf_hash_table (info), - sh_elf_discard_copies, - (PTR) NULL); - - /* The check_relocs and adjust_dynamic_symbol entry points have - determined the sizes of the various dynamic sections. Allocate - memory for them. */ - plt = false; - relocs = false; - for (s = dynobj->sections; s != NULL; s = s->next) + /* Set up .got offsets for local syms, and space for local dynamic + relocs. */ + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { - const char *name; - boolean strip; + bfd_signed_vma *local_got; + bfd_signed_vma *end_local_got; + bfd_size_type locsymcount; + Elf_Internal_Shdr *symtab_hdr; + asection *srel; - if ((s->flags & SEC_LINKER_CREATED) == 0) + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) continue; - /* It's OK to base decisions on the section name, because none - of the dynobj section names depend upon the input files. */ - name = bfd_get_section_name (dynobj, s); - - strip = false; - - if (strcmp (name, ".plt") == 0) + for (s = ibfd->sections; s != NULL; s = s->next) { - if (s->_raw_size == 0) - { - /* Strip this section if we don't need it; see the - comment below. */ - strip = true; - } - else + struct elf_sh_dyn_relocs *p; + + for (p = ((struct elf_sh_dyn_relocs *) + elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - /* Remember whether there is a PLT. */ - plt = true; + if (! bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else if (p->count != 0) + { + srel = elf_section_data (p->sec)->sreloc; + srel->_raw_size += p->count * sizeof (Elf32_External_Rela); + if ((p->sec->output_section->flags & SEC_READONLY) != 0) + info->flags |= DF_TEXTREL; + } } } - else if (strncmp (name, ".rela", 5) == 0) + + local_got = elf_local_got_refcounts (ibfd); + if (!local_got) + continue; + + symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + locsymcount = symtab_hdr->sh_info; +#ifdef INCLUDE_SHMEDIA + /* Count datalabel local GOT. */ + locsymcount *= 2; +#endif + end_local_got = local_got + locsymcount; + s = htab->sgot; + srel = htab->srelgot; + for (; local_got < end_local_got; ++local_got) { - if (s->_raw_size == 0) + if (*local_got > 0) { - /* If we don't need this section, strip it from the - output file. This is mostly to handle .rela.bss and - .rela.plt. We must create both sections in - create_dynamic_sections, because they must be created - before the linker maps input sections to output - sections. The linker does that before - adjust_dynamic_symbol is called, and it is that - function which decides whether anything needs to go - into these sections. */ - strip = true; + *local_got = s->_raw_size; + s->_raw_size += 4; + if (info->shared) + srel->_raw_size += sizeof (Elf32_External_Rela); } else - { - /* Remember whether there are any reloc sections other - than .rela.plt. */ - if (strcmp (name, ".rela.plt") != 0) - relocs = true; - - /* We use the reloc_count field as a counter if we need - to copy relocs into the output file. */ - s->reloc_count = 0; - } + *local_got = (bfd_vma) -1; } - else if (strncmp (name, ".got", 4) != 0) + } + + /* Allocate global sym .plt and .got entries, and space for global + sym dynamic relocs. */ + elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info); + + /* We now have determined the sizes of the various dynamic sections. + Allocate memory for them. */ + relocs = false; + for (s = dynobj->sections; s != NULL; s = s->next) + { + if ((s->flags & SEC_LINKER_CREATED) == 0) + continue; + + if (s == htab->splt + || s == htab->sgot + || s == htab->sgotplt) + { + /* Strip this section if we don't need it; see the + comment below. */ + } + else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) + { + if (s->_raw_size != 0 && s != htab->srelplt) + relocs = true; + + /* We use the reloc_count field as a counter if we need + to copy relocs into the output file. */ + s->reloc_count = 0; + } + else { /* It's not one of our sections, so don't allocate space. */ continue; } - if (strip) + if (s->_raw_size == 0) { + /* If we don't need this section, strip it from the + output file. This is mostly to handle .rela.bss and + .rela.plt. We must create both sections in + create_dynamic_sections, because they must be created + before the linker maps input sections to output + sections. The linker does that before + adjust_dynamic_symbol is called, and it is that + function which decides whether anything needs to go + into these sections. */ + _bfd_strip_section_from_output (info, s); continue; } - /* Allocate memory for the section contents. */ + /* Allocate memory for the section contents. We use bfd_zalloc + here in case unused entries are not reclaimed before the + section's contents are written out. This should not happen, + but this way if it does, we get a R_SH_NONE reloc instead + of garbage. */ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); - if (s->contents == NULL && s->_raw_size != 0) + if (s->contents == NULL) return false; } - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the values later, in sh_elf_finish_dynamic_sections, but we @@ -3912,64 +4232,44 @@ sh_elf_size_dynamic_sections (output_bfd, info) if (! info->shared) { - if (!add_dynamic_entry (DT_DEBUG, 0)) + if (! add_dynamic_entry (DT_DEBUG, 0)) return false; } - if (plt) + if (htab->splt->_raw_size != 0) { - if (!add_dynamic_entry (DT_PLTGOT, 0) - || !add_dynamic_entry (DT_PLTRELSZ, 0) - || !add_dynamic_entry (DT_PLTREL, DT_RELA) - || !add_dynamic_entry (DT_JMPREL, 0)) + if (! add_dynamic_entry (DT_PLTGOT, 0) + || ! add_dynamic_entry (DT_PLTRELSZ, 0) + || ! add_dynamic_entry (DT_PLTREL, DT_RELA) + || ! add_dynamic_entry (DT_JMPREL, 0)) return false; } if (relocs) { - if (!add_dynamic_entry (DT_RELA, 0) - || !add_dynamic_entry (DT_RELASZ, 0) - || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) + if (! add_dynamic_entry (DT_RELA, 0) + || ! add_dynamic_entry (DT_RELASZ, 0) + || ! add_dynamic_entry (DT_RELAENT, + sizeof (Elf32_External_Rela))) return false; - } - if ((info->flags & DF_TEXTREL) != 0) - { - if (!add_dynamic_entry (DT_TEXTREL, 0)) - return false; + /* If any dynamic relocs apply to a read-only section, + then we need a DT_TEXTREL entry. */ + if ((info->flags & DF_TEXTREL) == 0) + elf_link_hash_traverse (&htab->root, readonly_dynrelocs, + (PTR) info); + + if ((info->flags & DF_TEXTREL) != 0) + { + if (! add_dynamic_entry (DT_TEXTREL, 0)) + return false; + } } } #undef add_dynamic_entry return true; } - -/* This function is called via sh_elf_link_hash_traverse if we are - creating a shared object with -Bsymbolic. It discards the space - allocated to copy PC relative relocs against symbols which are - defined in regular objects. We allocated space for them in the - check_relocs routine, but we won't fill them in in the - relocate_section routine. */ - -static boolean -sh_elf_discard_copies (h, ignore) - struct elf_sh_link_hash_entry *h; - PTR ignore ATTRIBUTE_UNUSED; -{ - struct elf_sh_pcrel_relocs_copied *s; - - if (h->root.root.type == bfd_link_hash_warning) - h = (struct elf_sh_link_hash_entry *) h->root.root.u.i.link; - - /* We only discard relocs for symbols defined in a regular object. */ - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - return true; - - for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) - s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); - - return true; -} /* Relocate an SH ELF section. */ @@ -3985,6 +4285,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Sym *local_syms; asection **local_sections; { + struct elf_sh_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; Elf_Internal_Rela *rel, *relend; @@ -3995,14 +4296,15 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, asection *splt; asection *sreloc; + htab = sh_elf_hash_table (info); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); - dynobj = elf_hash_table (info)->dynobj; + dynobj = htab->root.dynobj; local_got_offsets = elf_local_got_offsets (input_bfd); - sgot = NULL; - sgotplt = NULL; - splt = NULL; + sgot = htab->sgot; + sgotplt = htab->sgotplt; + splt = htab->splt; sreloc = NULL; rel = relocs; @@ -4025,7 +4327,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, r_type = ELF32_R_TYPE (rel->r_info); /* Many of the relocs are only used for relaxing, and are - handled entirely by the relaxation code. */ + handled entirely by the relaxation code. */ if (r_type > (int) R_SH_LAST_INVALID_RELOC && r_type < (int) R_SH_LOOP_START) continue; @@ -4050,7 +4352,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, howto = sh_elf_howto_table + r_type; /* For relocs that aren't partial_inplace, we get the addend from - the relocation. */ + the relocation. */ if (! howto->partial_inplace) addend = rel->r_addend; @@ -4129,9 +4431,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, return false; } - addend = bfd_get_32 (input_bfd, contents + rel->r_offset); - msec = sec; - addend = + addend = bfd_get_32 (input_bfd, contents + rel->r_offset); + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; addend += msec->output_section->vma + msec->output_offset; @@ -4162,6 +4464,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { + boolean dyn; + + dyn = htab->root.dynamic_sections_created; sec = h->root.u.def.section; /* In these cases, we don't need the relocation value. We check specially because in some obscure cases @@ -4182,7 +4487,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, || r_type == R_SH_GOT_MEDLOW16 || r_type == R_SH_GOT_MEDHI16 || r_type == R_SH_GOT_HI16) - && elf_hash_table (info)->dynamic_sections_created + && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) && (! info->shared || (! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags @@ -4197,15 +4502,17 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) && ((r_type == R_SH_DIR32 - && !(ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)) + && (h->elf_link_hash_flags + & ELF_LINK_FORCED_LOCAL) == 0) || r_type == R_SH_REL32) && ((input_section->flags & SEC_ALLOC) != 0 /* DWARF will emit R_SH_DIR32 relocations in its sections against symbols defined externally in shared libraries. We can't do anything with them here. */ - || (input_section->flags & SEC_DEBUGGING) != 0))) + || ((input_section->flags & SEC_DEBUGGING) != 0 + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))) relocation = 0; else if (sec->output_section == NULL) { @@ -4228,14 +4535,17 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) - && !info->no_undefined) + && (! info->symbolic || info->allow_shlib_undefined) + && ! info->no_undefined + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, true))) + input_section, rel->r_offset, + (!info->shared || info->no_undefined + || ELF_ST_VISIBILITY (h->other))))) return false; relocation = 0; } @@ -4416,8 +4726,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, procedure linkage table. */ if (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) || ! info->shared || info->symbolic || h->dynindx == -1 @@ -4427,12 +4736,8 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Relocation is to the entry for this symbol in the global offset table extension for the procedure linkage table. */ - if (sgotplt == NULL) - { - sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); - BFD_ASSERT (sgotplt != NULL); - } + BFD_ASSERT (sgotplt != NULL); relocation = (sgotplt->output_offset + ((h->plt.offset / elf_sh_sizeof_plt (info) - 1 + 3) * 4)); @@ -4455,15 +4760,13 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, #endif /* Relocation is to the entry for this symbol in the global offset table. */ - if (sgot == NULL) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (sgot != NULL); - } + + BFD_ASSERT (sgot != NULL); if (h != NULL) { bfd_vma off; + boolean dyn; off = h->got.offset; #ifdef INCLUDE_SHMEDIA @@ -4477,11 +4780,11 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, #endif BFD_ASSERT (off != (bfd_vma) -1); - if (! elf_hash_table (info)->dynamic_sections_created + dyn = htab->root.dynamic_sections_created; + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) || (info->shared && (info->symbolic || h->dynindx == -1 - || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This is actually a static link, or it is a @@ -4585,7 +4888,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, } #ifdef GOT_BIAS - relocation -= GOT_BIAS; + relocation -= GOT_BIAS; #endif goto final_link_relocate; @@ -4600,11 +4903,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Relocation is relative to the start of the global offset table. */ - if (sgot == NULL) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (sgot != NULL); - } + BFD_ASSERT (sgot != NULL); /* Note that sgot->output_offset is not involved in this calculation. We always want the start of .got. If we @@ -4630,12 +4929,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, #endif /* Use global offset table as symbol value. */ - if (sgot == NULL) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (sgot != NULL); - } - + BFD_ASSERT (sgot != NULL); relocation = sgot->output_section->vma; #ifdef GOT_BIAS @@ -4661,8 +4955,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h == NULL) goto final_link_relocate; - if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) goto final_link_relocate; if (h->plt.offset == (bfd_vma) -1) @@ -4673,12 +4966,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, goto final_link_relocate; } - if (splt == NULL) - { - splt = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (splt != NULL); - } - + BFD_ASSERT (splt != NULL); relocation = (splt->output_section->vma + splt->output_offset + h->plt.offset); @@ -4901,18 +5189,186 @@ sh_elf_gc_mark_hook (sec, info, rel, h, sym) static boolean sh_elf_gc_sweep_hook (abfd, info, sec, relocs) - bfd *abfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; + bfd *abfd; + struct bfd_link_info *info; + asection *sec; + const Elf_Internal_Rela *relocs; { - /* We use got and plt entries for sh, but it would seem that the - existing SH code does no sort of reference counting or whatnot on - its GOT and PLT entries, so it is not possible to garbage collect - them at this time. */ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + bfd_signed_vma *local_got_refcounts; + const Elf_Internal_Rela *rel, *relend; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + + elf_section_data (sec)->local_dynrel = NULL; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + local_got_refcounts = elf_local_got_refcounts (abfd); + + relend = relocs + sec->reloc_count; + for (rel = relocs; rel < relend; rel++) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_SH_GOT32: + case R_SH_GOTOFF: + case R_SH_GOTPC: +#ifdef INCLUDE_SHMEDIA + case R_SH_GOT_LOW16: + case R_SH_GOT_MEDLOW16: + case R_SH_GOT_MEDHI16: + case R_SH_GOT_HI16: + case R_SH_GOT10BY4: + case R_SH_GOT10BY8: + case R_SH_GOTOFF_LOW16: + case R_SH_GOTOFF_MEDLOW16: + case R_SH_GOTOFF_MEDHI16: + case R_SH_GOTOFF_HI16: + case R_SH_GOTPC_LOW16: + case R_SH_GOTPC_MEDLOW16: + case R_SH_GOTPC_MEDHI16: + case R_SH_GOTPC_HI16: +#endif + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (h->got.refcount > 0) + h->got.refcount -= 1; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + } + break; + + case R_SH_DIR32: + case R_SH_REL32: + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_sh_link_hash_entry *eh; + struct elf_sh_dyn_relocs **pp; + struct elf_sh_dyn_relocs *p; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + + if (!info->shared && h->plt.refcount > 0) + h->plt.refcount -= 1; + + eh = (struct elf_sh_link_hash_entry *) h; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32) + p->pc_count -= 1; + p->count -= 1; + if (p->count == 0) + *pp = p->next; + break; + } + } + break; + + case R_SH_PLT32: +#ifdef INCLUDE_SHMEDIA + case R_SH_PLT_LOW16: + case R_SH_PLT_MEDLOW16: + case R_SH_PLT_MEDHI16: + case R_SH_PLT_HI16: +#endif + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + break; + + case R_SH_GOTPLT32: +#ifdef INCLUDE_SHMEDIA + case R_SH_GOTPLT_LOW16: + case R_SH_GOTPLT_MEDLOW16: + case R_SH_GOTPLT_MEDHI16: + case R_SH_GOTPLT_HI16: + case R_SH_GOTPLT10BY4: + case R_SH_GOTPLT10BY8: +#endif + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (h->got.refcount > 0) + h->got.refcount -= 1; + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + } + break; + + default: + break; + } + return true; } +/* Copy the extra info we tack onto an elf_link_hash_entry. */ + +static void +sh_elf_copy_indirect_symbol (bed, dir, ind) + struct elf_backend_data *bed; + struct elf_link_hash_entry *dir, *ind; +{ + struct elf_sh_link_hash_entry *edir, *eind; + + edir = (struct elf_sh_link_hash_entry *) dir; + eind = (struct elf_sh_link_hash_entry *) ind; + + if (eind->dyn_relocs != NULL) + { + if (edir->dyn_relocs != NULL) + { + struct elf_sh_dyn_relocs **pp; + struct elf_sh_dyn_relocs *p; + + BFD_ASSERT (ind->root.type != bfd_link_hash_indirect); + + /* Add reloc counts against the weak sym to the strong sym + list. Merge any entries against the same section. */ + for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) + { + struct elf_sh_dyn_relocs *q; + + for (q = edir->dyn_relocs; q != NULL; q = q->next) + if (q->sec == p->sec) + { + q->pc_count += p->pc_count; + q->count += p->count; + *pp = p->next; + break; + } + if (q == NULL) + pp = &p->next; + } + *pp = edir->dyn_relocs; + } + + edir->dyn_relocs = eind->dyn_relocs; + eind->dyn_relocs = NULL; + } + + _bfd_elf_link_hash_copy_indirect (bed, dir, ind); +} + /* Look through the relocs for a section during the first phase. Since we don't do .gots or .plts, we just need to consider the virtual table relocs for gc. */ @@ -4926,6 +5382,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs) { Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + struct elf_sh_link_hash_table *htab; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; bfd *dynobj; @@ -4947,7 +5404,8 @@ sh_elf_check_relocs (abfd, info, sec, relocs) if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; - dynobj = elf_hash_table (info)->dynobj; + htab = sh_elf_hash_table (info); + dynobj = htab->root.dynobj; local_got_offsets = elf_local_got_offsets (abfd); rel_end = relocs + sec->reloc_count; @@ -4963,7 +5421,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs) h = sym_hashes[r_symndx - symtab_hdr->sh_info]; /* Some relocs require a global offset table. */ - if (dynobj == NULL) + if (htab->sgot == NULL) { switch (ELF32_R_TYPE (rel->r_info)) { @@ -4993,8 +5451,9 @@ sh_elf_check_relocs (abfd, info, sec, relocs) case R_SH_GOTPC_MEDHI16: case R_SH_GOTPC_HI16: #endif - elf_hash_table (info)->dynobj = dynobj = abfd; - if (! _bfd_elf_create_got_section (dynobj, info)) + if (dynobj == NULL) + htab->root.dynobj = dynobj = abfd; + if (! create_got_section (dynobj, info)) return false; break; @@ -5004,16 +5463,16 @@ sh_elf_check_relocs (abfd, info, sec, relocs) } switch (ELF32_R_TYPE (rel->r_info)) - { - /* This relocation describes the C++ object vtable hierarchy. - Reconstruct it for later use during GC. */ + { + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ case R_SH_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; - /* This relocation describes which C++ vtable entries are actually - used. Record for later use during GC. */ + /* This relocation describes which C++ vtable entries are actually + used. Record for later use during GC. */ case R_SH_GNU_VTENTRY: if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return false; @@ -5029,133 +5488,34 @@ sh_elf_check_relocs (abfd, info, sec, relocs) case R_SH_GOT10BY4: case R_SH_GOT10BY8: #endif - /* This symbol requires a global offset table entry. */ - - if (sgot == NULL) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (sgot != NULL); - } - - if (srelgot == NULL - && (h != NULL || info->shared)) - { - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - if (srelgot == NULL) - { - srelgot = bfd_make_section (dynobj, ".rela.got"); - if (srelgot == NULL - || ! bfd_set_section_flags (dynobj, srelgot, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) - || ! bfd_set_section_alignment (dynobj, srelgot, 2)) - return false; - } - } - if (h != NULL) - { -#ifdef INCLUDE_SHMEDIA - if (h->type == STT_DATALABEL) - { - struct elf_sh_link_hash_entry *hsh; - - h = (struct elf_link_hash_entry *) h->root.u.i.link; - hsh = (struct elf_sh_link_hash_entry *)h; - if (hsh->datalabel_got_offset != (bfd_vma) -1) - break; - - hsh->datalabel_got_offset = sgot->_raw_size; - } - else - { -#endif - if (h->got.offset != (bfd_vma) -1) - { - /* We have already allocated space in the .got. */ - break; - } - h->got.offset = sgot->_raw_size; -#ifdef INCLUDE_SHMEDIA - } -#endif - - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; - } - - srelgot->_raw_size += sizeof (Elf32_External_Rela); - } + h->got.refcount += 1; else { + bfd_signed_vma *local_got_refcounts; + /* This is a global offset table entry for a local - symbol. */ - if (local_got_offsets == NULL) + symbol. */ + local_got_refcounts = elf_local_got_refcounts (abfd); + if (local_got_refcounts == NULL) { bfd_size_type size; - register unsigned int i; size = symtab_hdr->sh_info; - size *= sizeof (bfd_vma); + size *= sizeof (bfd_signed_vma); #ifdef INCLUDE_SHMEDIA /* Reserve space for both the datalabel and codelabel local GOT offsets. */ size *= 2; #endif - local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size); - if (local_got_offsets == NULL) + local_got_refcounts = ((bfd_signed_vma *) + bfd_zalloc (abfd, size)); + if (local_got_refcounts == NULL) return false; - elf_local_got_offsets (abfd) = local_got_offsets; - for (i = 0; i < symtab_hdr->sh_info; i++) - local_got_offsets[i] = (bfd_vma) -1; -#ifdef INCLUDE_SHMEDIA - for (; i < 2 * symtab_hdr->sh_info; i++) - local_got_offsets[i] = (bfd_vma) -1; -#endif - } -#ifdef INCLUDE_SHMEDIA - if ((rel->r_addend & 1) != 0) - { - if (local_got_offsets[symtab_hdr->sh_info - + r_symndx] != (bfd_vma) -1) - { - /* We have already allocated space in the .got. */ - break; - } - local_got_offsets[symtab_hdr->sh_info - + r_symndx] = sgot->_raw_size; - } - else - { -#endif - if (local_got_offsets[r_symndx] != (bfd_vma) -1) - { - /* We have already allocated space in the .got. */ - break; - } - local_got_offsets[r_symndx] = sgot->_raw_size; -#ifdef INCLUDE_SHMEDIA - } -#endif - - if (info->shared) - { - /* If we are generating a shared object, we need to - output a R_SH_RELATIVE reloc so that the dynamic - linker can adjust this GOT entry. */ - srelgot->_raw_size += sizeof (Elf32_External_Rela); + elf_local_got_refcounts (abfd) = local_got_refcounts; } + local_got_refcounts[r_symndx] += 1; } - - sgot->_raw_size += 4; - break; case R_SH_GOTPLT32: @@ -5171,22 +5531,14 @@ sh_elf_check_relocs (abfd, info, sec, relocs) creating a procedure linkage table entry. */ if (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) || ! info->shared || info->symbolic - || h->dynindx == -1 - || h->got.offset != (bfd_vma) -1) + || h->dynindx == -1) goto force_got; - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; - } - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount += 1; break; @@ -5209,18 +5561,20 @@ sh_elf_check_relocs (abfd, info, sec, relocs) if (h == NULL) continue; - if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) break; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - + h->plt.refcount += 1; break; case R_SH_DIR32: case R_SH_REL32: - if (h != NULL) - h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + if (h != NULL && ! info->shared) + { + h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + h->plt.refcount += 1; + } /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc @@ -5233,15 +5587,35 @@ sh_elf_check_relocs (abfd, info, sec, relocs) possible that DEF_REGULAR is not set now but will be set later (it is never cleared). We account for that possibility below by storing information in the - pcrel_relocs_copied field of the hash table entry. */ - if (info->shared - && (sec->flags & SEC_ALLOC) != 0 - && (ELF32_R_TYPE (rel->r_info) != R_SH_REL32 - || (h != NULL - && (! info->symbolic - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + dyn_relocs field of the hash table entry. A similar + situation occurs when creating shared libraries and symbol + visibility changes render the symbol local. + + If on the other hand, we are creating an executable, we + may need to keep relocations for symbols satisfied by a + dynamic library if we manage to avoid copy relocs for the + symbol. */ + if ((info->shared + && (sec->flags & SEC_ALLOC) != 0 + && (ELF32_R_TYPE (rel->r_info) != R_SH_REL32 + || (h != NULL + && (! info->symbolic + || h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (! info->shared + && (sec->flags & SEC_ALLOC) != 0 + && h != NULL + && (h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct elf_sh_dyn_relocs *p; + struct elf_sh_dyn_relocs **head; + + if (dynobj == NULL) + htab->root.dynobj = dynobj = abfd; + /* When creating a shared object, we must copy these reloc types into the output file. We create a reloc section in dynobj and make room for this reloc. */ @@ -5277,44 +5651,44 @@ sh_elf_check_relocs (abfd, info, sec, relocs) } if (sec->flags & SEC_READONLY) info->flags |= DF_TEXTREL; + elf_section_data (sec)->sreloc = sreloc; } - sreloc->_raw_size += sizeof (Elf32_External_Rela); - - /* If we are linking with -Bsymbolic, and this is a - global symbol, we count the number of PC relative - relocations we have entered for this symbol, so that - we can discard them again if the symbol is later - defined by a regular object. Note that this function - is only called if we are using an elf_sh linker - hash table, which means that h is really a pointer to - an elf_sh_link_hash_entry. */ - if (h != NULL && info->symbolic - && ELF32_R_TYPE (rel->r_info) == R_SH_REL32) + /* If this is a global symbol, we count the number of + relocations we need for this symbol. */ + if (h != NULL) + head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs; + else { - struct elf_sh_link_hash_entry *eh; - struct elf_sh_pcrel_relocs_copied *p; + asection *s; - eh = (struct elf_sh_link_hash_entry *) h; + /* Track dynamic relocs needed for local syms too. */ + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; - for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) - if (p->section == sreloc) - break; + head = ((struct elf_sh_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + } + p = *head; + if (p == NULL || p->sec != sec) + { + bfd_size_type amt = sizeof (*p); + p = ((struct elf_sh_dyn_relocs *) bfd_alloc (dynobj, amt)); if (p == NULL) - { - p = ((struct elf_sh_pcrel_relocs_copied *) - bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); - if (p == NULL) - return false; - p->next = eh->pcrel_relocs_copied; - eh->pcrel_relocs_copied = p; - p->section = sreloc; - p->count = 0; - } - - ++p->count; + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; } + + p->count += 1; + if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32) + p->pc_count += 1; } break; @@ -5448,9 +5822,11 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym) struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; { + struct elf_sh_link_hash_table *htab; bfd *dynobj; - dynobj = elf_hash_table (info)->dynobj; + htab = sh_elf_hash_table (info); + dynobj = htab->root.dynobj; if (h->plt.offset != (bfd_vma) -1) { @@ -5467,9 +5843,9 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym) BFD_ASSERT (h->dynindx != -1); - splt = bfd_get_section_by_name (dynobj, ".plt"); - sgot = bfd_get_section_by_name (dynobj, ".got.plt"); - srel = bfd_get_section_by_name (dynobj, ".rela.plt"); + splt = htab->splt; + sgot = htab->sgotplt; + srel = htab->srelplt; BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); /* Get the index in the procedure linkage table which @@ -5601,21 +5977,23 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the global offset table. Set it up. */ - sgot = bfd_get_section_by_name (dynobj, ".got"); - srel = bfd_get_section_by_name (dynobj, ".rela.got"); + sgot = htab->sgot; + srel = htab->srelgot; BFD_ASSERT (sgot != NULL && srel != NULL); rel.r_offset = (sgot->output_section->vma + sgot->output_offset + (h->got.offset &~ (bfd_vma) 1)); - /* If this is a -Bsymbolic link, and the symbol is defined - locally, we just want to emit a RELATIVE reloc. Likewise if - the symbol was forced to be local because of a version file. + /* If this is a static link, or it is a -Bsymbolic link and the + symbol is defined locally or was forced to be local because + of a version file, we just want to emit a RELATIVE reloc. The entry in the global offset table will already have been initialized in the relocate_section function. */ if (info->shared - && (info->symbolic || h->dynindx == -1) + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) { rel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE); @@ -5677,31 +6055,33 @@ sh_elf_finish_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info; { + struct elf_sh_link_hash_table *htab; bfd *dynobj; asection *sgot; asection *sdyn; - dynobj = elf_hash_table (info)->dynobj; + htab = sh_elf_hash_table (info); + dynobj = htab->root.dynobj; - sgot = bfd_get_section_by_name (dynobj, ".got.plt"); - BFD_ASSERT (sgot != NULL); + sgot = htab->sgotplt; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { asection *splt; Elf32_External_Dyn *dyncon, *dynconend; - BFD_ASSERT (sdyn != NULL); + BFD_ASSERT (sgot != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; - const char *name; asection *s; - struct elf_link_hash_entry *h; +#ifdef INCLUDE_SHMEDIA + const char *name; +#endif bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); @@ -5720,7 +6100,9 @@ sh_elf_finish_dynamic_sections (output_bfd, info) get_sym: if (dyn.d_un.d_val != 0) { - h = elf_link_hash_lookup (elf_hash_table (info), name, + struct elf_link_hash_entry *h; + + h = elf_link_hash_lookup (&htab->root, name, false, false, true); if (h != NULL && (h->other & STO_SH5_ISA32)) { @@ -5732,20 +6114,19 @@ sh_elf_finish_dynamic_sections (output_bfd, info) #endif case DT_PLTGOT: - name = ".got"; + s = htab->sgot->output_section; goto get_vma; case DT_JMPREL: - name = ".rela.plt"; + s = htab->srelplt->output_section; get_vma: - s = bfd_get_section_by_name (output_bfd, name); BFD_ASSERT (s != NULL); dyn.d_un.d_ptr = s->vma; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; case DT_PLTRELSZ: - s = bfd_get_section_by_name (output_bfd, ".rela.plt"); + s = htab->srelplt->output_section; BFD_ASSERT (s != NULL); if (s->_cooked_size != 0) dyn.d_un.d_val = s->_cooked_size; @@ -5764,9 +6145,9 @@ sh_elf_finish_dynamic_sections (output_bfd, info) the linker script arranges for .rela.plt to follow all other relocation sections, we don't have to worry about changing the DT_RELA entry. */ - s = bfd_get_section_by_name (output_bfd, ".rela.plt"); - if (s != NULL) + if (htab->srelplt != NULL) { + s = htab->srelplt->output_section; if (s->_cooked_size != 0) dyn.d_un.d_val -= s->_cooked_size; else @@ -5778,7 +6159,7 @@ sh_elf_finish_dynamic_sections (output_bfd, info) } /* Fill in the first entry in the procedure linkage table. */ - splt = bfd_get_section_by_name (dynobj, ".plt"); + splt = htab->splt; if (splt && splt->_raw_size > 0) { if (info->shared) @@ -5824,7 +6205,7 @@ sh_elf_finish_dynamic_sections (output_bfd, info) } /* Fill in the first three entries in the global offset table. */ - if (sgot->_raw_size > 0) + if (sgot && sgot->_raw_size > 0) { if (sdyn == NULL) bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); @@ -5834,9 +6215,9 @@ sh_elf_finish_dynamic_sections (output_bfd, info) sgot->contents); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); - } - elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + } return true; } @@ -5884,11 +6265,11 @@ sh_elf_reloc_type_class (rela) #define bfd_elf32_bfd_merge_private_bfd_data \ sh_elf_merge_private_data -#define elf_backend_gc_mark_hook sh_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook sh_elf_gc_sweep_hook -#define elf_backend_check_relocs sh_elf_check_relocs - -#define elf_backend_can_gc_sections 1 +#define elf_backend_gc_mark_hook sh_elf_gc_mark_hook +#define elf_backend_gc_sweep_hook sh_elf_gc_sweep_hook +#define elf_backend_check_relocs sh_elf_check_relocs +#define elf_backend_copy_indirect_symbol \ + sh_elf_copy_indirect_symbol #define elf_backend_create_dynamic_sections \ sh_elf_create_dynamic_sections #define bfd_elf32_bfd_link_hash_table_create \ @@ -5903,6 +6284,8 @@ sh_elf_reloc_type_class (rela) sh_elf_finish_dynamic_sections #define elf_backend_reloc_type_class sh_elf_reloc_type_class +#define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/version.h b/bfd/version.h index da65221..99eb582 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -1 +1 @@ -#define BFD_VERSION_DATE 20020824 +#define BFD_VERSION_DATE 20020825 diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 25a0285..3d9bb66 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,53 @@ +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.h (register_offset_hack): Declare. + (regcache_cooked_read_using_offset_hack): Declare. + (regcache_cooked_write_using_offset_hack): Declare. + + * regcache.c (register_offset_hack): New function. + (regcache_cooked_read_using_offset_hack): New function. + (regcache_cooked_write_using_offset_hack): New function. + (regcache_dump): Check that the registers, according to their + offset, are packed hard against each other. + (cooked_xfer_using_offset_hack): New function. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (struct regcache_descr): Add field register_type. + (init_legacy_regcache_descr): Pass a pre-allocated regcache_descr + in as a parameter + (init_regcache_descr): Initialize register_type. Pass the descr + to init_legacy_regcache_descr. Use register_type instead of + REGISTER_VIRTUAL_TYPE. + (register_type): New function. + (regcache_dump): Replace REGISTER_VIRTUAL_TYPE with register_type. + * regcache.h (register_type): Declare. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Set store_struct_return + instead of deprecated_store_return_value. Fix fallout from + 2002-08-23 Andrew Cagney <cagney@redhat.com>. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * regcache.c (max_register_size): New function. + (init_legacy_regcache_descr): Ensure that max_register_size is + large enough for REGISTER_VIRTUAL_SIZE. + * regcache.h (max_register_size): Declare. + +2002-08-24 Andrew Cagney <ac131313@redhat.com> + + * rs6000-tdep.c (rs6000_gdbarch_init): Use deprecated version of + store_return_value. + (e500_extract_return_value): Change type of valbuf pointer to + void. + 2002-08-24 Mark Kettenis <kettenis@gnu.org> + * PROBLEMS: Clarify problems with FreeBSD's compiler and suggest + workaround. + * valprint.c (print_longest) [CC_HAS_LONG_LONG && PRINTF_HAS_LONG_LONG]: Cast val_long to (long long) or (unsigned long long) to prevent compiler warning on 64-bit systems. diff --git a/gdb/PROBLEMS b/gdb/PROBLEMS index 9ffea60..4c460d6 100644 --- a/gdb/PROBLEMS +++ b/gdb/PROBLEMS @@ -17,8 +17,11 @@ i386-*-freebsd[34]* There is a bug (bin/41671) in FreeBSD's gcc that causes it to emit bad debug information when using the stabs format (which is the default). -In earlier versions of GDB the effects were rather limited, but -starting with GDB 5.3 the influence is much more prominent. +As a result GDB tends to place breakpoints on functions before the +function prologue, and information about function parameters and local +variables is lost. In earlier versions of GDB the effects were rather +limited, but starting with GDB 5.3 the influence is much more +prominent. As a workaround, compile your code with -gdwarf-2. hppa2.0-hp-hpux10.20 diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4693072..37a5e3a 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,44 @@ +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * gdb.texinfo (Examples): Use ``->'' for a packet send and ``<-'' + for a packet receive. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (clean): Move to end of file. + (distclean, maintainer-clean, realclean): Ditto. + (mostlyclean): Move rule to end of file. Use GDB_TEX_TMPS, + GDBINT_TEX_TMPS, STABS_TEX_TMPS. + (gdb.dvi, gdb.pdf): Do not cleanup TeX temp files after texi2dvi. + (gdbint.dvi, gdbint.pdf, stabs.dvi, stabs.pdf): Ditto. + +2002-08-24 Andrew Cagney <ac131313@redhat.com> + + * Makefile.in (GDBINT_TEX_TMPS): Define. + (gdbint.dvi, gdbint.pdf): Use + (GDB_TEX_TMPS): Define. + (gdb.dvi, gdb.pdf): Use. + (STABS_TEX_TMPS): Define. + (stabs.dvi, stabs.pdf): Use. + (GDB_DOC_SOURCE_INCLUDES): New macros. + (GDB_DOC_BUILD_INCLUDES, GDB_DOC_FILES): New macros. + (GDBINT_DOC_FILES_INCLUDES): New macros. + (GDBINT_DOC_BUILD_INCLUDES): New macros. + (GDBINT_DOC_FILES, STABS_DOC_SOURCE_INCLUDES): New macros. + (STABS_DOC_BUILD_INCLUDES, STABS_DOC_FILES): New macros. + (SFILES_DOC, SFILES_INCLUDED, SFILES_LOCAL): Delete macros. + (links2roff): Replace SFILES_INCLUDED with + GDB_DOC_SOURCE_INCLUDES. + (gdb.dvi, gdb_toc.html, gdb.pdf, gdb.info): Update dependencies. + (gdb.me, gdb.mm, gdb.ms): Update dependencies. + (gdbint.dvi, gdbint_toc.html, gdbint.pdf, gdbint.info): Update + dependencies. + (stabs.info, stabs_toc.html, stabs.pdf, stabs.dvi): Update + dependencies. + (gdbmi.texinfo): Delete rule. + (inc-hist.texinfo): Delete rule. + (rluser.texinfo): Delete rule. + 2002-08-23 Andrew Cagney <cagney@redhat.com> * gdbint.texinfo (Target Architecture Definition): Update diff --git a/gdb/doc/Makefile.in b/gdb/doc/Makefile.in index 3b549b8..ba0031a 100644 --- a/gdb/doc/Makefile.in +++ b/gdb/doc/Makefile.in @@ -96,16 +96,40 @@ TEX = tex # Program to generate Postscript files from DVI files. DVIPS = dvips -# Main GDB manual's source files -SFILES_INCLUDED = gdb-cfg.texi \ +# Main GDB manual +GDB_DOC_SOURCE_INCLUDES = \ $(srcdir)/annotate.texi \ $(srcdir)/fdl.texi \ - $(srcdir)/gpl.texi - -SFILES_LOCAL = $(srcdir)/gdb.texinfo GDBvn.texi $(SFILES_INCLUDED) - -SFILES_DOC = $(SFILES_LOCAL) $(GDBMI_DIR)/gdbmi.texinfo \ - $(READLINE_DIR)/rluser.texinfo $(READLINE_DIR)/inc-hist.texinfo + $(srcdir)/gpl.texi \ + $(GDBMI_DIR)/gdbmi.texinfo \ + $(READLINE_DIR)/rluser.texinfo \ + $(READLINE_DIR)/inc-hist.texinfo +GDB_DOC_BUILD_INCLUDES = \ + gdb-cfg.texi \ + GDBvn.texi +GDB_DOC_FILES = \ + $(srcdir)/gdb.texinfo \ + $(GDB_DOC_SOURCE_INCLUDES) \ + $(GDB_DOC_BUILD_INCLUDES) + +# Internals Manual +GDBINT_DOC_SOURCE_INCLUDES = \ + $(srcdir)/fdl.texi +GDBINT_DOC_BUILD_INCLUDES = \ + gdb-cfg.texi \ + GDBvn.texi +GDBINT_DOC_FILES = \ + $(srcdir)/gdbint.texinfo \ + $(GDBINT_DOC_SOURCE_INCLUDES) \ + $(GDBINT_DOC_BUILD_INCLUDES) + +# Stabs manual: All files +STABS_DOC_SOURCE_INCLUDES = +STABS_DOC_BUILD_INCLUDES = +STABS_DOC_FILES = \ + $(srcdir)/stabs.texinfo \ + $(STABS_DOC_SOURCE_INCLUDES) \ + $(STABS_DOC_BUILD_INCLUDES) #### Host, target, and site specific Makefile fragments come in here. ### @@ -177,27 +201,6 @@ de-stage3: force -(cd stage3 ; mv -f * ..) -rmdir stage3 -# The "least clean" level of cleaning. Get rid of files which are -# automatically generated files that are just intermediate files, -# -mostlyclean: - rm -f gdb.mm gdb.ms gdb.me links2roff - rm -f *.aux *.cp* *.fn* *.ky* *.log *.pg* *.toc *.tp* *.vr* - rm -f sedref.dvi sedref.tex tmp.sed - -clean: mostlyclean - rm -f rluser.texinfo inc-hist.texinfo gdb-cfg.texi - -distclean: clean - rm -f Makefile config.status - -# GDBvn.texi, the dvi files, the info files, and the postscript files, -# are all part of the distribution, so it should not be removed by -# "clean" or "distclean". Use maintainer-clean to remove them. - -maintainer-clean realclean: distclean - rm -f GDBvn.texi *.info* *.dvi *.ps *.html *.pdf - # GDB QUICK REFERENCE (dvi output) refcard.dvi : refcard.tex $(REFEDITS) echo > tmp.sed @@ -240,30 +243,34 @@ gdb-cfg.texi: ${srcdir}/${DOC_CONFIG}-cfg.texi # VPATH will often tell make not to bother building it, because the one # in the srcdir is up to date. (if not, then make should build one here). +# Clean these up before each run. Avoids a catch 22 with not being +# able to re-generate these files (to fix a corruption) because these +# files contain a corruption. +GDB_TEX_TMPS = gdb.aux gdb.cp* gdb.fn* gdb.ky* gdb.log gdb.pg* gdb.toc \ + gdb.tp* gdb.vr* + # GDB MANUAL: TeX dvi file -gdb.dvi: ${SFILES_DOC} +gdb.dvi: ${GDB_DOC_FILES} if [ ! -f ./GDBvn.texi ]; then \ (test "$$LN_S" = "ln -s" && ln -s $(srcdir)/GDBvn.texi .) || \ ln $(srcdir)/GDBvn.texi . || \ cp $(srcdir)/GDBvn.texi . ; else true; fi + rm -f $(GDB_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) $(srcdir)/gdb.texinfo - rm -f gdb.aux gdb.cp* gdb.fn* gdb.ky* gdb.log gdb.pg* gdb.toc \ - gdb.tp* gdb.vr* gdb.ps: gdb.dvi $(DVIPS) -o $@ $? -gdb.pdf: ${SFILES_DOC} +gdb.pdf: ${GDB_DOC_FILES} if [ ! -f ./GDBvn.texi ]; then \ (test "$$LN_S" = "ln -s" && ln -s $(srcdir)/GDBvn.texi .) || \ ln $(srcdir)/GDBvn.texi . || \ cp $(srcdir)/GDBvn.texi . ; else true; fi + rm -f $(GDB_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) --pdf $(srcdir)/gdb.texinfo - rm -f gdb.aux gdb.cp* gdb.fn* gdb.ky* gdb.log gdb.pg* gdb.toc \ - gdb.tp* gdb.vr* # GDB MANUAL: info file -gdb.info: ${SFILES_DOC} +gdb.info: ${GDB_DOC_FILES} $(MAKEINFO) -I ${READLINE_DIR} -I ${GDBMI_DIR} -I $(srcdir) \ -o gdb.info $(srcdir)/gdb.texinfo @@ -281,37 +288,16 @@ gdb.info: ${SFILES_DOC} # texi2roff doesn't have a notion of include dirs, so we have to fake # it out for gdb manual's include files---but only if not configured # in main sourcedir. -links2roff: $(SFILES_INCLUDED) +links2roff: $(GDB_DOC_SOURCE_INCLUDES) if [ ! -f gdb.texinfo ]; then \ - (test "$$LN_S" = "ln -s" && ln -s $(SFILES_INCLUDED) .) || \ - ln $(SFILES_INCLUDED) . || \ - cp $(SFILES_INCLUDED) . ; \ + (test "$$LN_S" = "ln -s" && ln -s $(GDB_DOC_SOURCE_INCLUDES) .) || \ + ln $(GDB_DOC_SOURCE_INCLUDES) . || \ + cp $(GDB_DOC_SOURCE_INCLUDES) . ; \ fi touch links2roff -# "Readline" appendices. Get them also due to lack of includes, -# regardless of whether or not configuring in main sourcedir. -# @ftable removed due to bug in texi2roff-2; if your texi2roff -# is newer, try just ln or cp -rluser.texinfo: ${READLINE_DIR}/rluser.texinfo - sed -e 's/^@ftable/@table/g' \ - -e 's/^@end ftable/@end table/g' \ - ${READLINE_DIR}/rluser.texinfo > ./rluser.texinfo - -inc-hist.texinfo: ${READLINE_DIR}/inc-hist.texinfo - (test "$$LN_S" = "ln -s" && \ - ln -s ${READLINE_DIR}/inc-hist.texinfo .) || \ - ln ${READLINE_DIR}/inc-hist.texinfo . || \ - cp ${READLINE_DIR}/inc-hist.texinfo . - -gdbmi.texinfo: ${GDBMI_DIR}/gdbmi.texinfo - (test "$$LN_S" = "ln -s" && \ - ln -s ${GDBMI_DIR}/gdbmi.texinfo .) || \ - ln ${GDBMI_DIR}/gdbmi.texinfo . || \ - cp ${GDBMI_DIR}/gdbmi.texinfo . - # gdb manual suitable for [gtn]roff -me -gdb.me: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo +gdb.me: $(GDB_DOC_FILES) links2roff sed -e '/\\input texinfo/d' \ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ -e '/^@ifinfo/,/^@end ifinfo/d' \ @@ -326,7 +312,7 @@ gdb.me: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo >gdb.me # gdb manual suitable for [gtn]roff -ms -gdb.ms: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo +gdb.ms: $(GDB_DOC_FILES) links2roff sed -e '/\\input texinfo/d' \ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ -e '/^@ifinfo/,/^@end ifinfo/d' \ @@ -343,7 +329,7 @@ gdb.ms: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo # gdb manual suitable for [tn]roff -mm # '@noindent's removed due to texi2roff-2 mm bug; if yours is newer, # try leaving them in -gdb.mm: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo +gdb.mm: $(GDB_DOC_FILES) links2roff sed -e '/\\input texinfo/d' \ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ -e '/^@ifinfo/,/^@end ifinfo/d' \ @@ -360,56 +346,89 @@ gdb.mm: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texinfo gdbmi.texinfo # GDB MANUAL: HTML file -gdb_toc.html: ${SFILES_DOC} +gdb_toc.html: ${GDB_DOC_FILES} $(MAKEHTML) $(MAKEHTMLFLAGS) -I ${READLINE_DIR} -I ${GDBMI_DIR} -I $(srcdir) $(srcdir)/gdb.texinfo +# Clean these up before each run. Avoids a catch 22 with not being +# able to re-generate these files (to fix a corruption) because these +# files contain a corruption. +GDBINT_TEX_TMPS = gdbint.aux gdbint.cp* gdbint.fn* gdbint.ky* \ + gdbint.log gdbint.pg* gdbint.toc gdbint.tp* gdbint.vr* + # GDB INTERNALS MANUAL: TeX dvi file -gdbint.dvi: gdbint.texinfo gdb-cfg.texi fdl.texi +gdbint.dvi: $(GDBINT_DOC_FILES) + rm -f $(GDBINT_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) $(srcdir)/gdbint.texinfo - rm -f gdbint.aux gdbint.cp* gdbint.fn* gdbint.ky* \ - gdbint.log gdbint.pg* gdbint.toc gdbint.tp* gdbint.vr* gdbint.ps : gdbint.dvi $(DVIPS) -o $@ $? -gdbint.pdf: gdbint.texinfo gdb-cfg.texi fdl.texi +gdbint.pdf: $(GDBINT_DOC_FILES) + rm -f $(GDBINT_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) --pdf $(srcdir)/gdbint.texinfo - rm -f gdbint.aux gdbint.cp* gdbint.fn* gdbint.ky* \ - gdbint.log gdbint.pg* gdbint.toc gdbint.tp* gdbint.vr* # GDB INTERNALS MANUAL: info file -gdbint.info: gdbint.texinfo fdl.texi +gdbint.info: $(GDBINT_DOC_FILES) $(MAKEINFO) -I $(srcdir) -o gdbint.info $(srcdir)/gdbint.texinfo # GDB INTERNALS MANUAL: HTML file -gdbint_toc.html: gdbint.texinfo gdb-cfg.texi fdl.texi +gdbint_toc.html: $(GDBINT_DOC_FILES) $(MAKEHTML) $(MAKEHTMLFLAGS) $(srcdir)/gdbint.texinfo -stabs.info: stabs.texinfo +stabs.info: $(STABS_DOC_FILES) $(MAKEINFO) -o stabs.info $(srcdir)/stabs.texinfo # STABS DOCUMENTATION: HTML file -stabs_toc.html: stabs.texinfo +stabs_toc.html: $(STABS_DOC_FILES) $(MAKEHTML) $(MAKEHTMLFLAGS) $(srcdir)/stabs.texinfo +# Clean these up before each run. Avoids a catch 22 with not being +# able to re-generate these files (to fix a corruption) because these +# files contain a corruption. +STABS_TEX_TMPS = stabs.aux stabs.cp* stabs.fn* stabs.ky* \ + stabs.log stabs.pg* stabs.toc stabs.tp* stabs.vr* + # STABS DOCUMENTATION: TeX dvi file -stabs.dvi : stabs.texinfo +stabs.dvi : $(STABS_DOC_FILES) + rm -f $(STABS_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) $(srcdir)/stabs.texinfo - rm -f stabs.aux stabs.cp* stabs.fn* stabs.ky* \ - stabs.log stabs.pg* stabs.toc stabs.tp* stabs.vr* stabs.ps: stabs.dvi $(DVIPS) -o $@ $? -stabs.pdf: stabs.dvi +stabs.pdf: $(STABS_DOC_FILES) + rm -f $(STABS_TEX_TMPS) $(SET_TEXINPUTS) $(TEXI2DVI) --pdf $(srcdir)/stabs.texinfo - rm -f stabs.aux stabs.cp* stabs.fn* stabs.ky* \ - stabs.log stabs.pg* stabs.toc stabs.tp* stabs.vr* force: Makefile: Makefile.in $(host_makefile_frag) $(target_makefile_frag) config.status $(SHELL) ./config.status + + +# The "least clean" level of cleaning. Get rid of files which are +# automatically generated files that are just intermediate files, + +mostlyclean: + rm -f gdb.mm gdb.ms gdb.me links2roff + rm -f $(GDB_TEX_TMPS) + rm -f $(GDBINT_TEX_TMPS) + rm -f $(STABS_TEX_TMPS) + rm -f sedref.dvi sedref.tex tmp.sed + +clean: mostlyclean + rm -f gdb-cfg.texi + +distclean: clean + rm -f Makefile config.status + +# GDBvn.texi, the dvi files, the info files, and the postscript files, +# are all part of the distribution, so it should not be removed by +# "clean" or "distclean". Use maintainer-clean to remove them. + +maintainer-clean realclean: distclean + rm -f GDBvn.texi *.info* *.dvi *.ps *.html *.pdf + diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 84ed89e..c88c17d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -14248,7 +14248,7 @@ protocol---for example, if there is only one serial port to your target machine, you might want your program to do something special if it recognizes a packet meant for @value{GDBN}. -In the examples below, @samp{<-} and @samp{->} are used to indicate +In the examples below, @samp{->} and @samp{<-} are used to indicate transmitted and received data respectfully. @cindex protocol, @value{GDBN} remote serial @@ -14290,8 +14290,8 @@ the package was received correctly) or @samp{-} (to request retransmission): @smallexample -<- @code{$}@var{packet-data}@code{#}@var{checksum} --> @code{+} +-> @code{$}@var{packet-data}@code{#}@var{checksum} +<- @code{+} @end smallexample @noindent @@ -15082,29 +15082,29 @@ Example sequence of a target being re-started. Notice how the restart does not get any direct output: @smallexample -<- @code{R00} --> @code{+} +-> @code{R00} +<- @code{+} @emph{target restarts} -<- @code{?} --> @code{+} --> @code{T001:1234123412341234} +-> @code{?} <- @code{+} +<- @code{T001:1234123412341234} +-> @code{+} @end smallexample Example sequence of a target being stepped by a single instruction: @smallexample -<- @code{G1445@dots{}} --> @code{+} -<- @code{s} --> @code{+} -@emph{time passes} --> @code{T001:1234123412341234} +-> @code{G1445@dots{}} <- @code{+} -<- @code{g} +-> @code{s} +<- @code{+} +@emph{time passes} +<- @code{T001:1234123412341234} -> @code{+} --> @code{1455@dots{}} +-> @code{g} <- @code{+} +<- @code{1455@dots{}} +-> @code{+} @end smallexample @include gpl.texi diff --git a/gdb/regcache.c b/gdb/regcache.c index e483de0..6c86ba9 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -77,24 +77,22 @@ struct regcache_descr /* Useful constant. Largest of all the registers. */ long max_register_size; + + /* Cached table containing the type of each register. */ + struct type **register_type; }; -static void * -init_legacy_regcache_descr (struct gdbarch *gdbarch) +void +init_legacy_regcache_descr (struct gdbarch *gdbarch, + struct regcache_descr *descr) { int i; - struct regcache_descr *descr; /* FIXME: cagney/2002-05-11: gdbarch_data() should take that ``gdbarch'' as a parameter. */ gdb_assert (gdbarch != NULL); - descr = XMALLOC (struct regcache_descr); - descr->gdbarch = gdbarch; - descr->legacy_p = 1; - /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers in the register buffer. Unfortunatly some architectures do. */ - descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS; descr->nr_raw_registers = descr->nr_cooked_registers; descr->sizeof_raw_register_valid_p = descr->nr_cooked_registers; @@ -112,6 +110,8 @@ init_legacy_regcache_descr (struct gdbarch *gdbarch) descr->sizeof_register[i] = REGISTER_RAW_SIZE (i); if (descr->max_register_size < REGISTER_RAW_SIZE (i)) descr->max_register_size = REGISTER_RAW_SIZE (i); + if (descr->max_register_size < REGISTER_VIRTUAL_SIZE (i)) + descr->max_register_size = REGISTER_VIRTUAL_SIZE (i); } /* Come up with the real size of the registers buffer. */ @@ -133,7 +133,6 @@ init_legacy_regcache_descr (struct gdbarch *gdbarch) if (descr->sizeof_raw_registers < regend) descr->sizeof_raw_registers = regend; } - return descr; } static void * @@ -143,21 +142,33 @@ init_regcache_descr (struct gdbarch *gdbarch) struct regcache_descr *descr; gdb_assert (gdbarch != NULL); - /* If an old style architecture, construct the register cache - description using all the register macros. */ - if (!gdbarch_pseudo_register_read_p (gdbarch) - && !gdbarch_pseudo_register_write_p (gdbarch)) - return init_legacy_regcache_descr (gdbarch); - - descr = XMALLOC (struct regcache_descr); + /* Create an initial, zero filled, table. */ + descr = XCALLOC (1, struct regcache_descr); descr->gdbarch = gdbarch; - descr->legacy_p = 0; /* Total size of the register space. The raw registers are mapped directly onto the raw register cache while the pseudo's are either mapped onto raw-registers or memory. */ descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS; + /* Fill in a table of register types. */ + descr->register_type = XCALLOC (descr->nr_cooked_registers, + struct type *); + for (i = 0; i < descr->nr_cooked_registers; i++) + { + descr->register_type[i] = REGISTER_VIRTUAL_TYPE (i); + } + + /* If an old style architecture, fill in the remainder of the + register cache descriptor using the register macros. */ + if (!gdbarch_pseudo_register_read_p (gdbarch) + && !gdbarch_pseudo_register_write_p (gdbarch)) + { + descr->legacy_p = 1; + init_legacy_regcache_descr (gdbarch, descr); + return descr; + } + /* Construct a strictly RAW register cache. Don't allow pseudo's into the register cache. */ descr->nr_raw_registers = NUM_REGS; @@ -173,10 +184,10 @@ init_regcache_descr (struct gdbarch *gdbarch) cache. Some code, via read_register_bytes() access a register using an offset/length rather than a register number. - NOTE: cagney/2002-05-22: Only REGISTER_VIRTUAL_TYPE() needs to be - used when constructing the register cache. It is assumed that - register raw size, virtual size and type length of the type are - all the same. */ + NOTE: cagney/2002-05-22: Only register_type() is used when + constructing the register cache. It is assumed that the + register's raw size, virtual size and type length are all the + same. */ { long offset = 0; @@ -185,7 +196,7 @@ init_regcache_descr (struct gdbarch *gdbarch) descr->max_register_size = 0; for (i = 0; i < descr->nr_cooked_registers; i++) { - descr->sizeof_register[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i)); + descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]); descr->register_offset[i] = offset; offset += descr->sizeof_register[i]; if (descr->max_register_size < descr->sizeof_register[i]) @@ -239,6 +250,27 @@ xfree_regcache_descr (struct gdbarch *gdbarch, void *ptr) xfree (descr); } +/* Utility functions returning useful register attributes stored in + the regcache descr. */ + +struct type * +register_type (struct gdbarch *gdbarch, int regnum) +{ + struct regcache_descr *descr = regcache_descr (gdbarch); + gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers); + return descr->register_type[regnum]; +} + +/* Utility functions returning useful register attributes stored in + the regcache descr. */ + +int +max_register_size (struct gdbarch *gdbarch) +{ + struct regcache_descr *descr = regcache_descr (gdbarch); + return descr->max_register_size; +} + /* The register cache for storing raw register values. */ struct regcache @@ -997,6 +1029,95 @@ regcache_cooked_write_part (struct regcache *regcache, int regnum, regcache_cooked_read, regcache_cooked_write); } +/* Hack to keep code that view the register buffer as raw bytes + working. */ + +int +register_offset_hack (struct gdbarch *gdbarch, int regnum) +{ + struct regcache_descr *descr = regcache_descr (gdbarch); + gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers); + return descr->register_offset[regnum]; +} + +static void +cooked_xfer_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, void *in_b, + const void *out_b) +{ + struct regcache_descr *descr = regcache->descr; + struct gdbarch *gdbarch = descr->gdbarch; + bfd_byte *in_buf = in_b; + const bfd_byte *out_buf = out_b; + int buf_end = buf_start + buf_len; + int regnum; + char *reg_buf = alloca (descr->max_register_size); + + /* NOTE: cagney/2002-08-17: This code assumes that the register + offsets are strictly increasing and do not overlap. If this + isn't the case then the bug is in the target architecture and NOT + this code. */ + + /* NOTE: cagney/2002-08-17: This code assumes that only the + registers covered by BUF_START:BUF_LEN should be transfered. If, + for some reason, there is a gap between two registers, then that + gap isn't transfered. (The gap shouldn't be there but that is + another story.) */ + + /* Iterate through all registers looking for those that lie within + BUF_START:BUF_LEN. */ + + for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++) + { + /* The register's location. */ + int reg_start = descr->register_offset[regnum]; + int reg_len = descr->sizeof_register[regnum]; + int reg_end = reg_start + reg_len; + + /* The START, END and LEN that falls within the current + register. */ + int xfer_start; + int xfer_end; + int xfer_len; + + /* start = max (reg_start, buf_start) */ + if (reg_start > buf_start) + xfer_start = reg_start; + else + xfer_start = buf_start; + + /* end = min (reg_end, buf_end) */ + if (reg_end < buf_end) + xfer_end = reg_end; + else + xfer_end = buf_end; + + /* The number of bytes to transfer. If there isn't anything to + transfer (the end is before the start) this will be -ve. */ + xfer_len = xfer_end - xfer_start; + + if (xfer_len > 0) + regcache_xfer_part (regcache, regnum, xfer_start - reg_start, + xfer_len, in_b, out_b, regcache_cooked_read, + regcache_cooked_write); + } +} + +void +regcache_cooked_read_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, void *b) +{ + cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, b, NULL); +} + +void +regcache_cooked_write_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, + const void *b) +{ + cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, NULL, b); +} + /* Return the contents of register REGNUM as an unsigned integer. */ ULONGEST @@ -1407,7 +1528,12 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, fprintf_unfiltered (file, " %6ld", regcache->descr->register_offset[regnum]); if (register_offset != regcache->descr->register_offset[regnum] - || register_offset != REGISTER_BYTE (regnum)) + || register_offset != REGISTER_BYTE (regnum) + || (regnum > 0 + && (regcache->descr->register_offset[regnum] + != (regcache->descr->register_offset[regnum - 1] + + regcache->descr->sizeof_register[regnum - 1]))) + ) { if (!footnote_register_offset) footnote_register_offset = ++footnote_nr; @@ -1431,7 +1557,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, || (regcache->descr->sizeof_register[regnum] != REGISTER_VIRTUAL_SIZE (regnum)) || (regcache->descr->sizeof_register[regnum] - != TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum))) + != TYPE_LENGTH (register_type (regcache->descr->gdbarch, + regnum))) ) { if (!footnote_register_size) @@ -1448,7 +1575,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, else { static const char blt[] = "builtin_type"; - const char *t = TYPE_NAME (REGISTER_VIRTUAL_TYPE (regnum)); + const char *t = TYPE_NAME (register_type (regcache->descr->gdbarch, + regnum)); if (t == NULL) { char *n; diff --git a/gdb/regcache.h b/gdb/regcache.h index da91fd6..1db42e3 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -88,6 +88,58 @@ extern void supply_register (int regnum, const void *val); extern void regcache_collect (int regnum, void *buf); +/* The register's ``offset''. + + NOTE: cagney/2002-08-17: The ``struct value'' and expression + evaluator treat the register cache as a large liner buffer. + Instead of reading/writing a register using its register number, + the code read/writes registers by specifying their offset into the + buffer and a number of bytes. The code also assumes that these + byte read/writes can cross register boundaries, adjacent registers + treated as a contiguous set of bytes. + + The below map that model onto the real register cache. New code + should go out of their way to avoid using these interfaces. + + FIXME: cagney/2002-08-17: The ``struct value'' and expression + evaluator should be fixed. Instead of using the { offset, length } + pair to describe a value within one or more registers, the code + should use a chain of { regnum, offset, len } tripples. */ + +extern int register_offset_hack (struct gdbarch *gdbarch, int regnum); +extern void regcache_cooked_read_using_offset_hack (struct regcache *regcache, + int offset, int len, + void *buf); +extern void regcache_cooked_write_using_offset_hack (struct regcache *regcache, + int offset, int len, + const void *buf); + + +/* The type of a register. This function is slightly more efficient + then its gdbarch vector counterpart since it returns a precomputed + value stored in a table. + + NOTE: cagney/2002-08-17: The original macro was called + REGISTER_VIRTUAL_TYPE. This was because the register could have + different raw and cooked (nee virtual) representations. The + CONVERTABLE methods being used to convert between the two + representations. Current code does not do this. Instead, the + first [0..NUM_REGS) registers are 1:1 raw:cooked, and the type + exactly describes the register's representation. Consequently, the + ``virtual'' has been dropped. + + FIXME: cagney/2002-08-17: A number of architectures, including the + MIPS, are currently broken in this regard. */ + +extern struct type *register_type (struct gdbarch *gdbarch, int regnum); + + +/* Return the size of the largest register. Used when allocating + space for an aribtrary register value. */ + +extern int max_register_size (struct gdbarch *gdbarch); + + /* DEPRECATED: Character array containing an image of the inferior programs' registers for the most recently referenced thread. */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index c73f92d..398b0e0 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1250,7 +1250,7 @@ ppc_push_return_address (CORE_ADDR pc, CORE_ADDR sp) /* Extract a function return value of type TYPE from raw register array REGBUF, and copy that return value into VALBUF in virtual format. */ static void -e500_extract_return_value (struct type *valtype, struct regcache *regbuf, char *valbuf) +e500_extract_return_value (struct type *valtype, struct regcache *regbuf, void *valbuf) { int offset = 0; int vallen = TYPE_LENGTH (valtype); @@ -2759,7 +2759,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_fp_regnum (gdbarch, 1); set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value); - set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); + set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value); if (v->arch == bfd_arch_powerpc) switch (v->mach) @@ -2794,7 +2794,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write); set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value); - set_gdbarch_store_return_value (gdbarch, e500_store_return_value); + set_gdbarch_deprecated_store_return_value (gdbarch, e500_store_return_value); break; default: tdep->ppc_vr0_regnum = -1; @@ -2888,7 +2888,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments); - set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value); + set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame); diff --git a/gdb/tui/ChangeLog b/gdb/tui/ChangeLog index 16d4835..ac71eee 100644 --- a/gdb/tui/ChangeLog +++ b/gdb/tui/ChangeLog @@ -1,3 +1,184 @@ +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiDisassem.c (tuiGetBeginAsmAddress): Use lookup_minimal_symbol + to find symbol address. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.c (tui_display_main): Rename from tuiDisplayMainFunction + and use tuiGetBeginAsmAddress. + * tuiSourceWin.h (tui_display_main): Declare. + * tui.h (tuiDisplayMainFunction): Remove. + * tui-hooks.c (tui_new_objfile_hook): Update. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSource.h (m_tuiShowSourceAsIs): Remove macro. + (tuiShowSourceAsIs): Don't declare. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tui-hooks.c (tui_selected_frame_level_changed_hook): Always update + the frame position. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiStack.c (tuiSetLocatorContent): Remove. + (tuiUpdateLocatorInfoFromFrame): Remove. + (tui_set_locator_info): Allocate the content buffer if necessary. + (tui_set_locator_filename): Call tui_set_locator_info directly. + (tuiShowFrameInfo): Likewise and use find_pc_line instead of + find_pc_symtab. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.c (tuiDisplayMainFunction): Update to use + tuiUpdateLocatorFilename. + * tuiStack.c (tuiSetLocatorInfo): Make it static. + (tuiSetLocatorContent): Likewise. + (tuiUpdateLocatorInfoFromFrame): Likewise. + (tuiSwitchFilename): Remove. + (tui_set_locator_filename): New function + (tui_set_locator_info): Rename from tuiSetLocatorInfo to GNU-ify; + use tui_set_locator_filename to record the filename. + (tuiUpdateLocatorFilename): Likewise. + (tuiUpdateLocatorInfoFromFrame): Update. + (tuiSetLocatorContent): Likewise. + * tuiStack.h (tuiClearLocatorContent): Don't declare. + (tuiSetLocatorInfo, tuiSetLocatorContent): Likewise. + (tuiUpdateLocatorInfoFromFrame, tuiSwitchFilename): Likewise. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.c (tuiSetHasBreakAt): Use filename for breakpoint + comparison; cleanup. + * tuiSource.c (tuiSetSourceContent): Set window title and filename. + * tuiGeneralWin.c (boxWin): Print optional title on top of window. + * tuiData.h (TuiSourceInfo): Add filename member. + (TuiGenWinInfo): Add title member. + * tuiData.c (initGenericPart): Clear title. + (freeWindow): Free title and filename; remove unused locals. + (initWinInfo): Clear filename. + (tuiDelWindow): Free it; remove unused locals. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiStack.h (tuiGetLocatorFilename): Don't declare. + (tuiUpdateLocatorDisplay): Likewise. + * tuiStack.c (tuiGetLocatorFilename): Remove. + (tuiShowFrameInfo): Use tuiSetLocatorContent and tuiShowLocatorContent + instead of tuiUpdateLocatorDisplay. + (tuiUpdateLocatorDisplay): Remove. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiStack.h (tuiClearLocatorDisplay): Don't declare. + * tuiStack.c (tuiClearLocatorDisplay): Remove. + (tuiShowLocatorContent): Use wclrtoeol to clear end of status line. + (tuiUpdateLocatorDisplay): Don't call tuiClearLocatorDisplay. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiStack.c (tui_get_function_from_frame): Rename from + _getFuncNameFromFrame; use print_address_symbolic to get symbolic + name of address. + (tuiUpdateLocatorInfoFromFrame): Update. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiRegs.c (tuiDisplayRegistersFrom): Remove unused locals. + (_tuiRegisterFormat, _tuiSetSpecialRegsContent): Likewise. + (_tuiSetGeneralAndSpecialRegsContent): Likewise. + (_tuiSetFloatRegsContent): Likewise. + (_tuiRegisterName): Return a const char*. + * tuiData.h (_TuiDataElement): Use const char* for name. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.h (tuiEraseAllSourceContent): Don't declare. + (tuiShowAllExecInfosContent): Likewise. + * tuiSourceWin.c (tuiEraseAllSourceContent): Remove. + (tuiShowAllExecInfosContent): Remove. + (tuiAllocSourceBuffer): Remove unused locals. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiStack.c (tui_update_command): Rename _tuiUpdateLocation_command + to follow other gdb's command names; use execute_command; cleanup. + (_initialize_tuiStack): Update. + +2002-08-25 Stephane Carrez <stcarrez@nerim.fr> + + * tuiWin.h (tui_update_gdb_sizes): Declare. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tui.c (strcat_to_buf): Use const char* for source item. + (tui_enable): Update the windows if there is a selected frame. + * tui.h (strcat_to_buf): Update prototype. + (strcat_to_buf_with_fmt): Remove. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tuiWin.c (tui_update_gdb_sizes): New function to tell gdb what + is the size of command window. + (tuiResizeAll): Call it instead of init_page_info. + * tui.c (tui_enable): Call it to resize to TUI command window. + (tui_disable): Likewise for plain screen. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tui.c (tui_enable): Use tuiSetLayout instead of showLayout and + use tuiShowFrameInfo instead of tuiSetLocatorContent. + * tuiLayout.h (showLayout): Remove. + * tuiLayout.c (_showSourceOrDisassemAndCommand): Remove unused locals. + (_showSourceDisassemCommand): Likewise. + (showLayout): Make it static. + (lastLayout): Remove. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.c (tui_show_source_line): New function. + (tuiShowSourceContent): Call it and avoid clearing the window before + redrawing it. + (tuiClearAllSourceWinsContent): Remove. + * tuiSourceWin.h (tuiClearAllSourceWinsContent): Don't declare. + * tuiWin.h (tuiClearWinFocus, tuiClearWinFocusFrom): Don't declare. + * tuiWin.c (tuiClearWinFocus, tuiClearWinFocusFrom): Remove. + (tuiRefreshAll): Don't clear the window. + (_makeVisibleWithNewHeight): Don't clear locator line. + (tuiResizeAll): Remove unused locals. + (_tuiAdjustWinHeights): Likewise. + (_makeInvisibleAndSetNewHeight): Likewise. + (_newHeightOk): Likewise. + * tuiLayout.c (showLayout): Don't clear source windows. + (tuiSetLayout): Don't clear the window. + (_initAndMakeWin): Likewise for status line. + * tuiGeneralWin.c (makeVisible): Don't clear or refresh the window. + (makeWindow): Likewise. + (tuiClearWin): Remove. + * tuiGeneralWin.h (tuiClearWin): Don't declare. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tuiSourceWin.c (tuiSrcWinIsDisplayed): Remove. + (tuiAsmWinIsDisplayed): Remove. + (tuiShowAllSourceWinsContent): Remove. + (tuiUpdateOnEnd): Remove. + * tuiGeneralWin.c (scrollWinForward): Remove. + (scrollWinBackward): Remove. + (_winResize): Don't declare. + * tui.h (tuiUpdateOnEnd): Don't declare. + (vcatch_errors, va_catch_errors): Likewise. + * tuiSourceWin.h (tuiUpdateOnEnd): Likewise. + (tuiShowAllSourceWinsContent): Likewise. + * tuiGeneralWin.h (scrollWinForward): Likewise. + (scrollWinBackward): Likewise. + +2002-08-24 Stephane Carrez <stcarrez@nerim.fr> + + * tuiRegs.c (_tuiRegisterFormat): Use gdbarch_print_registers_info. + 2002-08-18 Daniel Jacobowitz <drow@mvista.com> Fix PR gdb/655 diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c index 27556ac..d605194 100644 --- a/gdb/tui/tui-hooks.c +++ b/gdb/tui/tui-hooks.c @@ -71,9 +71,7 @@ static void tui_new_objfile_hook (struct objfile* objfile) { if (tui_active) - { - tuiDisplayMainFunction (); - } + tui_display_main (); if (tui_target_new_objfile_chain) tui_target_new_objfile_chain (objfile); @@ -309,10 +307,10 @@ tui_selected_frame_level_changed_hook (int level) would be 0 here, and select_source_symtab would abort the command by calling the 'error' function */ if (s) - { - select_source_symtab (s); - tuiShowFrameInfo (fi); - } + select_source_symtab (s); + + /* Display the frame position (even if there is no symbols). */ + tuiShowFrameInfo (fi); /* Refresh the register window if it's visible. */ if (tui_is_window_visible (DATA_WIN)) diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index 6b132b7..8bf4776 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -237,8 +237,8 @@ tui_enable (void) setTermWidthTo (COLS); def_prog_mode (); - tuiSetLocatorContent (0); - showLayout (SRC_COMMAND); + tuiShowFrameInfo (0); + tuiSetLayout (SRC_COMMAND, TUI_UNDEFINED_REGS); tuiSetWinFocusTo (srcWin); keypad (cmdWin->generic.handle, TRUE); wrefresh (cmdWin->generic.handle); @@ -261,7 +261,11 @@ tui_enable (void) tui_version = 1; tui_active = 1; + if (selected_frame) + tuiShowFrameInfo (selected_frame); + refresh (); + tui_update_gdb_sizes (); } /* Leave the tui mode. @@ -286,6 +290,7 @@ tui_disable (void) tui_version = 0; tui_active = 0; + tui_update_gdb_sizes (); } /* Wrapper on top of free() to ensure that input address @@ -325,7 +330,7 @@ tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc) } void -strcat_to_buf (char *buf, int buflen, char *itemToAdd) +strcat_to_buf (char *buf, int buflen, const char *itemToAdd) { if (itemToAdd != (char *) NULL && buf != (char *) NULL) { diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h index fcea91a..9cc538d 100644 --- a/gdb/tui/tui.h +++ b/gdb/tui/tui.h @@ -48,11 +48,7 @@ Opaque (*OpaqueFuncPtr) (va_list); */ typedef OpaqueFuncPtr TuiOpaqueFuncPtr; -extern Opaque vcatch_errors (OpaqueFuncPtr, ...); -extern Opaque va_catch_errors (OpaqueFuncPtr, va_list); - -extern void strcat_to_buf (char *, int, char *); -extern void strcat_to_buf_with_fmt (char *, int, char *, ...); +extern void strcat_to_buf (char *, int, const char *); /* Types of error returns */ typedef enum @@ -129,9 +125,7 @@ extern void tui_vStartNewLines (va_list); extern TuiStatus tui_set_layout (const char *); /* tuiSourceWin.c */ -extern void tuiDisplayMainFunction (void); extern void tuiUpdateAllExecInfos (void); -extern void tuiUpdateOnEnd (void); extern void tui_vAllSetHasBreakAt (va_list); extern void tui_vUpdateSourceWindowsWithAddr (va_list); diff --git a/gdb/tui/tuiData.c b/gdb/tui/tuiData.c index 30efba8..45508e0 100644 --- a/gdb/tui/tuiData.c +++ b/gdb/tui/tuiData.c @@ -843,9 +843,8 @@ initGenericPart (TuiGenWinInfoPtr win) win->content = (OpaquePtr) NULL; win->contentInUse = win->isVisible = FALSE; - - return; -} /* initGenericPart */ + win->title = 0; +} /* @@ -914,6 +913,7 @@ initWinInfo (TuiWinInfoPtr winInfo) winInfo->detail.sourceInfo.hasLocator = FALSE; winInfo->detail.sourceInfo.horizontalOffset = 0; winInfo->detail.sourceInfo.startLineOrAddr.addr = 0; + winInfo->detail.sourceInfo.filename = 0; break; case DATA_WIN: winInfo->detail.dataDisplayInfo.dataContent = (TuiWinContent) NULL; @@ -1040,19 +1040,13 @@ addContentElements (TuiGenWinInfoPtr winInfo, int numElements) } /* addContentElements */ -/* - ** tuiDelWindow(). - ** Delete all curses windows associated with winInfo, leaving everything - ** else in tact. - */ +/* Delete all curses windows associated with winInfo, leaving everything + else intact. */ void tuiDelWindow (TuiWinInfoPtr winInfo) { - Opaque detail; - int i; TuiGenWinInfoPtr genericWin; - switch (winInfo->generic.type) { case SRC_WIN: @@ -1064,6 +1058,11 @@ tuiDelWindow (TuiWinInfoPtr winInfo) genericWin->handle = (WINDOW *) NULL; genericWin->isVisible = FALSE; } + if (winInfo->detail.sourceInfo.filename) + { + xfree (winInfo->detail.sourceInfo.filename); + winInfo->detail.sourceInfo.filename = 0; + } genericWin = winInfo->detail.sourceInfo.executionInfo; if (genericWin != (TuiGenWinInfoPtr) NULL) { @@ -1075,14 +1074,10 @@ tuiDelWindow (TuiWinInfoPtr winInfo) case DATA_WIN: if (winInfo->generic.content != (OpaquePtr) NULL) { - int i; - - tuiDelDataWindows ( - winInfo->detail.dataDisplayInfo.regsContent, - winInfo->detail.dataDisplayInfo.regsContentCount); - tuiDelDataWindows ( - winInfo->detail.dataDisplayInfo.dataContent, - winInfo->detail.dataDisplayInfo.dataContentCount); + tuiDelDataWindows (winInfo->detail.dataDisplayInfo.regsContent, + winInfo->detail.dataDisplayInfo.regsContentCount); + tuiDelDataWindows (winInfo->detail.dataDisplayInfo.dataContent, + winInfo->detail.dataDisplayInfo.dataContentCount); } break; default: @@ -1094,9 +1089,7 @@ tuiDelWindow (TuiWinInfoPtr winInfo) winInfo->generic.handle = (WINDOW *) NULL; winInfo->generic.isVisible = FALSE; } - - return; -} /* tuiDelWindow */ +} /* @@ -1105,11 +1098,8 @@ tuiDelWindow (TuiWinInfoPtr winInfo) void freeWindow (TuiWinInfoPtr winInfo) { - Opaque detail; - int i; TuiGenWinInfoPtr genericWin; - switch (winInfo->generic.type) { case SRC_WIN: @@ -1121,6 +1111,11 @@ freeWindow (TuiWinInfoPtr winInfo) genericWin->handle = (WINDOW *) NULL; } freeWinContent (genericWin); + if (winInfo->detail.sourceInfo.filename) + { + xfree (winInfo->detail.sourceInfo.filename); + winInfo->detail.sourceInfo.filename = 0; + } genericWin = winInfo->detail.sourceInfo.executionInfo; if (genericWin != (TuiGenWinInfoPtr) NULL) { @@ -1161,10 +1156,10 @@ freeWindow (TuiWinInfoPtr winInfo) winInfo->generic.handle = (WINDOW *) NULL; freeWinContent (&winInfo->generic); } + if (winInfo->generic.title) + xfree (winInfo->generic.title); xfree (winInfo); - - return; -} /* freeWindow */ +} /* diff --git a/gdb/tui/tuiData.h b/gdb/tui/tuiData.h index 9edf000..36d7853 100644 --- a/gdb/tui/tuiData.h +++ b/gdb/tui/tuiData.h @@ -1,5 +1,5 @@ /* TUI data manipulation routines. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -42,6 +42,7 @@ int viewportHeight; /* viewport height */ int lastVisibleLine; /* index of last visible line */ int isVisible; /* whether the window is visible or not */ + char* title; /* Window title to display. */ } TuiGenWinInfo, *TuiGenWinInfoPtr; @@ -170,7 +171,7 @@ TuiSourceElement, *TuiSourceElementPtr; /* Elements in the data display window content */ typedef struct _TuiDataElement { - char *name; + const char *name; int itemNo; /* the register number, or data display number */ TuiDataType type; Opaque value; @@ -244,6 +245,7 @@ typedef struct _TuiSourceInfo TuiGenWinInfoPtr executionInfo; /* execution information window */ int horizontalOffset; /* used for horizontal scroll */ TuiLineOrAddress startLineOrAddr; + char* filename; } TuiSourceInfo, *TuiSourceInfoPtr; diff --git a/gdb/tui/tuiDisassem.c b/gdb/tui/tuiDisassem.c index 8e59e68..e3a19b3 100644 --- a/gdb/tui/tuiDisassem.c +++ b/gdb/tui/tuiDisassem.c @@ -231,19 +231,25 @@ tuiGetBeginAsmAddress (void) if (element->addr == 0) { - /*the target is not executing, because the pc is 0 */ - - addr = parse_and_eval_address ("main"); - - if (addr == 0) - addr = parse_and_eval_address ("MAIN"); - + struct minimal_symbol *main_symbol; + + /* Find address of the start of program. + Note: this should be language specific. */ + main_symbol = lookup_minimal_symbol ("main", NULL, NULL); + if (main_symbol == 0) + main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL); + if (main_symbol == 0) + main_symbol = lookup_minimal_symbol ("_start", NULL, NULL); + if (main_symbol) + addr = SYMBOL_VALUE_ADDRESS (main_symbol); + else + addr = 0; } else /* the target is executing */ addr = element->addr; return addr; -} /* tuiGetBeginAsmAddress */ +} /* diff --git a/gdb/tui/tuiGeneralWin.c b/gdb/tui/tuiGeneralWin.c index b3f8b91..e250ca2 100644 --- a/gdb/tui/tuiGeneralWin.c +++ b/gdb/tui/tuiGeneralWin.c @@ -45,12 +45,6 @@ #include "tuiGeneralWin.h" #include "tuiWin.h" -/* - ** local support functions - */ -static void _winResize (void); - - /*********************** ** PUBLIC FUNCTIONS ***********************/ @@ -124,6 +118,8 @@ boxWin (TuiGenWinInfoPtr winInfo, int highlightFlag) tui_border_hline, tui_border_hline, tui_border_ulcorner, tui_border_urcorner, tui_border_llcorner, tui_border_lrcorner); + if (winInfo->title) + mvwaddstr (win, 0, 3, winInfo->title); wattroff (win, attrs); } } @@ -197,43 +193,8 @@ makeWindow (TuiGenWinInfoPtr winInfo, int boxIt) boxWin (winInfo, NO_HILITE); winInfo->isVisible = TRUE; scrollok (handle, TRUE); - tuiRefreshWin (winInfo); - -#ifndef FOR_TEST - if ( /*!m_WinIsAuxillary(winInfo->type) && */ - (winInfo->type != CMD_WIN) && - (winInfo->content == (OpaquePtr) NULL)) - { - mvwaddstr (handle, 1, 1, winName (winInfo)); - tuiRefreshWin (winInfo); - } -#endif /*FOR_TEST */ } - - return; -} /* makeWindow */ - - -/* - ** tuiClearWin(). - ** Clear the window of all contents without calling wclear. - */ -void -tuiClearWin (TuiGenWinInfoPtr winInfo) -{ - if (m_genWinPtrNotNull (winInfo) && winInfo->handle != (WINDOW *) NULL) - { - int curRow, curCol; - - for (curRow = 0; (curRow < winInfo->height); curRow++) - for (curCol = 0; (curCol < winInfo->width); curCol++) - mvwaddch (winInfo->handle, curRow, curCol, ' '); - - tuiRefreshWin (winInfo); - } - - return; -} /* tuiClearWin */ +} /* @@ -258,13 +219,11 @@ makeVisible (TuiGenWinInfoPtr winInfo, int visible) (winInfo->type != CMD_WIN && !m_winIsAuxillary (winInfo->type))); winInfo->isVisible = TRUE; } - tuiRefreshWin (winInfo); } else if (!visible && winInfo->isVisible && winInfo->handle != (WINDOW *) NULL) { winInfo->isVisible = FALSE; - tuiClearWin (winInfo); tuiDelwin (winInfo->handle); winInfo->handle = (WINDOW *) NULL; } @@ -297,90 +256,6 @@ makeAllVisible (int visible) return; } /* makeAllVisible */ - -/* - ** scrollWinForward - */ -void -scrollWinForward (TuiGenWinInfoPtr winInfo, int numLines) -{ - if (winInfo->content != (OpaquePtr) NULL && - winInfo->lastVisibleLine < winInfo->contentSize - 1) - { - int i, firstLine, newLastLine; - - firstLine = winInfo->lastVisibleLine - winInfo->viewportHeight + 1; - if (winInfo->lastVisibleLine + numLines > winInfo->contentSize) - newLastLine = winInfo->contentSize - 1; - else - newLastLine = winInfo->lastVisibleLine + numLines - 1; - - for (i = (newLastLine - winInfo->viewportHeight); - (i <= newLastLine); i++) - { - TuiWinElementPtr line; - int lineHeight; - - line = (TuiWinElementPtr) winInfo->content[i]; - if (line->highlight) - wstandout (winInfo->handle); - mvwaddstr (winInfo->handle, - i - (newLastLine - winInfo->viewportHeight), - 1, - displayableWinContentOf (winInfo, line)); - if (line->highlight) - wstandend (winInfo->handle); - lineHeight = winElementHeight (winInfo, line); - newLastLine += (lineHeight - 1); - } - winInfo->lastVisibleLine = newLastLine; - } - - return; -} /* scrollWinForward */ - - -/* - ** scrollWinBackward - */ -void -scrollWinBackward (TuiGenWinInfoPtr winInfo, int numLines) -{ - if (winInfo->content != (OpaquePtr) NULL && - (winInfo->lastVisibleLine - winInfo->viewportHeight) > 0) - { - int i, newLastLine, firstLine; - - firstLine = winInfo->lastVisibleLine - winInfo->viewportHeight + 1; - if ((firstLine - numLines) < 0) - newLastLine = winInfo->viewportHeight - 1; - else - newLastLine = winInfo->lastVisibleLine - numLines + 1; - - for (i = newLastLine - winInfo->viewportHeight; (i <= newLastLine); i++) - { - TuiWinElementPtr line; - int lineHeight; - - line = (TuiWinElementPtr) winInfo->content[i]; - if (line->highlight) - wstandout (winInfo->handle); - mvwaddstr (winInfo->handle, - i - (newLastLine - winInfo->viewportHeight), - 1, - displayableWinContentOf (winInfo, line)); - if (line->highlight) - wstandend (winInfo->handle); - lineHeight = winElementHeight (winInfo, line); - newLastLine += (lineHeight - 1); - } - winInfo->lastVisibleLine = newLastLine; - } - - return; -} /* scrollWinBackward */ - - /* ** refreshAll(). ** Function to refresh all the windows currently displayed diff --git a/gdb/tui/tuiGeneralWin.h b/gdb/tui/tuiGeneralWin.h index 60c54f1..42d1ce4 100644 --- a/gdb/tui/tuiGeneralWin.h +++ b/gdb/tui/tuiGeneralWin.h @@ -1,5 +1,5 @@ /* General window behavior. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -25,12 +25,9 @@ /* ** Functions */ -extern void tuiClearWin (TuiGenWinInfoPtr); extern void unhighlightWin (TuiWinInfoPtr); extern void makeVisible (TuiGenWinInfoPtr, int); extern void makeAllVisible (int); -extern void scrollWinForward (TuiGenWinInfoPtr, int); -extern void scrollWinBackward (TuiGenWinInfoPtr, int); extern void makeWindow (TuiGenWinInfoPtr, int); extern TuiWinInfoPtr copyWin (TuiWinInfoPtr); extern void boxWin (TuiGenWinInfoPtr, int); diff --git a/gdb/tui/tuiLayout.c b/gdb/tui/tuiLayout.c index aa98882..c3eae72 100644 --- a/gdb/tui/tuiLayout.c +++ b/gdb/tui/tuiLayout.c @@ -58,7 +58,7 @@ /******************************* ** Static Local Decls ********************************/ - +static void showLayout (TuiLayoutType); static void _initGenWinInfo (TuiGenWinInfoPtr, TuiWinType, int, int, int, int); static void _initAndMakeWin (Opaque *, TuiWinType, int, int, int, int, int); static void _showSourceOrDisassemAndCommand (TuiLayoutType); @@ -86,20 +86,8 @@ static void _tuiHandleXDBLayout (TuiLayoutDefPtr); #define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n" -/*************************************** -** Static Local Data -***************************************/ -static TuiLayoutType lastLayout = UNDEFINED_LAYOUT; - -/*************************************** -** PUBLIC FUNCTIONS -***************************************/ - -/* - ** showLayout(). - ** Show the screen layout defined - */ -void +/* Show the screen layout defined. */ +static void showLayout (TuiLayoutType layout) { TuiLayoutType curLayout = currentLayout (); @@ -111,7 +99,6 @@ showLayout (TuiLayoutType layout) ** should free the content and reallocate on next display of ** source/asm */ - tuiClearAllSourceWinsContent (NO_EMPTY_SOURCE_PROMPT); freeAllSourceWinsContent (); clearSourceWindows (); if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND) @@ -146,9 +133,7 @@ showLayout (TuiLayoutType layout) } } } - - return; -} /* showLayout */ +} /* @@ -195,8 +180,6 @@ tuiSetLayout (TuiLayoutType layoutType, { if (newLayout != curLayout) { - if (winWithFocus != cmdWin) - tuiClearWinFocus (); showLayout (newLayout); /* ** Now determine where focus should be @@ -291,7 +274,7 @@ tuiSetLayout (TuiLayoutType layoutType, status = TUI_FAILURE; return status; -} /* tuiSetLayout */ +} /* ** tuiAddWinToLayout(). @@ -794,8 +777,6 @@ _showDisassemCommand (void) static void _showSourceDisassemCommand (void) { - TuiGenWinInfoPtr locator = locatorWinInfoPtr (); - if (currentLayout () != SRC_DISASSEM_COMMAND) { int cmdHeight, srcHeight, asmHeight; @@ -1033,13 +1014,9 @@ _initAndMakeWin (Opaque * winInfoPtr, TuiWinType winType, ((TuiWinInfoPtr) opaqueWinInfo)->canHighlight = TRUE; } makeWindow (generic, boxIt); - if (winType == LOCATOR_WIN) - tuiClearLocatorDisplay (); } *winInfoPtr = opaqueWinInfo; - - return; -} /* _initAndMakeWin */ +} /* @@ -1092,7 +1069,6 @@ _showSourceOrDisassemAndCommand (TuiLayoutType layoutType) if (currentLayout () != layoutType) { TuiWinInfoPtr *winInfoPtr; - int areaLeft; int srcHeight, cmdHeight; TuiGenWinInfoPtr locator = locatorWinInfoPtr (); diff --git a/gdb/tui/tuiLayout.h b/gdb/tui/tuiLayout.h index 8646318..f6b0ed7 100644 --- a/gdb/tui/tuiLayout.h +++ b/gdb/tui/tuiLayout.h @@ -1,5 +1,5 @@ /* TUI layout window management. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -22,7 +22,6 @@ #ifndef TUI_LAYOUT_H #define TUI_LAYOUT_H -extern void showLayout (TuiLayoutType); extern void tuiAddWinToLayout (TuiWinType); extern int tuiDefaultWinHeight (TuiWinType, TuiLayoutType); extern int tuiDefaultWinViewportHeight (TuiWinType, TuiLayoutType); diff --git a/gdb/tui/tuiRegs.c b/gdb/tui/tuiRegs.c index d76c67e..928eb41 100644 --- a/gdb/tui/tuiRegs.c +++ b/gdb/tui/tuiRegs.c @@ -46,6 +46,7 @@ #include "gdbtypes.h" #include "gdbcmd.h" #include "frame.h" +#include "regcache.h" #include "inferior.h" #include "target.h" #include "tuiLayout.h" @@ -86,7 +87,7 @@ ******************************************/ static TuiStatus _tuiSetRegsContent (int, int, struct frame_info *, TuiRegisterDisplayType, int); -static char *_tuiRegisterName (int); +static const char *_tuiRegisterName (int); static TuiStatus _tuiGetRegisterRawValue (int, char *, struct frame_info *); static void _tuiSetRegisterElement (int, struct frame_info *, TuiDataElementPtr, int); @@ -311,7 +312,7 @@ tuiDisplayRegistersFrom (int startElementNo) dataWin->detail.dataDisplayInfo.regsContentCount > 0) { register int i = startElementNo; - int j, valueCharsWide, charsWide, itemWinWidth, curY, labelWidth; + int j, valueCharsWide, itemWinWidth, curY, labelWidth; enum precision_type precision; precision = (dataWin->detail.dataDisplayInfo.regsDisplayType @@ -435,8 +436,6 @@ tuiDisplayRegElementAtLine (int startElementNo, int startLineNo) int tuiDisplayRegistersFromLine (int lineNo, int forceDisplay) { - int elementNo; - if (dataWin->detail.dataDisplayInfo.regsContentCount > 0) { int line, elementNo; @@ -595,7 +594,7 @@ registers.\n", ** _tuiRegisterName(). ** Return the register name. */ -static char * +static const char * _tuiRegisterName (int regNum) { return REGISTER_NAME (regNum); @@ -622,7 +621,7 @@ _tuiRegisterFormat (char *buf, int bufLen, int regNum, { struct ui_file *stream; struct ui_file *old_stdout; - char *name; + const char *name; struct cleanup *cleanups; char *p; int pos; @@ -639,7 +638,8 @@ _tuiRegisterFormat (char *buf, int bufLen, int regNum, stream = tui_sfileopen (bufLen); gdb_stdout = stream; cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); - do_registers_info (regNum, 0); + gdbarch_print_registers_info (current_gdbarch, stream, selected_frame, + regNum, 1); /* Save formatted output in the buffer. */ p = tui_file_get_strbuf (stream); @@ -700,15 +700,9 @@ static TuiStatus _tuiSetSpecialRegsContent (int refreshValuesOnly) { TuiStatus ret = TUI_FAILURE; - int i, endRegNum; + int endRegNum; endRegNum = FP0_REGNUM - 1; -#if 0 - endRegNum = (-1); - for (i = START_SPECIAL_REGS; (i < NUM_REGS && endRegNum < 0); i++) - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT) - endRegNum = i - 1; -#endif ret = _tuiSetRegsContent (START_SPECIAL_REGS, endRegNum, selected_frame, @@ -727,15 +721,9 @@ static TuiStatus _tuiSetGeneralAndSpecialRegsContent (int refreshValuesOnly) { TuiStatus ret = TUI_FAILURE; - int i, endRegNum = (-1); + int endRegNum = (-1); endRegNum = FP0_REGNUM - 1; -#if 0 - endRegNum = (-1); - for (i = 0; (i < NUM_REGS && endRegNum < 0); i++) - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT) - endRegNum = i - 1; -#endif ret = _tuiSetRegsContent ( 0, endRegNum, selected_frame, TUI_SPECIAL_REGS, refreshValuesOnly); @@ -750,15 +738,9 @@ static TuiStatus _tuiSetFloatRegsContent (TuiRegisterDisplayType dpyType, int refreshValuesOnly) { TuiStatus ret = TUI_FAILURE; - int i, startRegNum; + int startRegNum; startRegNum = FP0_REGNUM; -#if 0 - startRegNum = (-1); - for (i = NUM_REGS - 1; (i >= 0 && startRegNum < 0); i--) - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) != TYPE_CODE_FLT) - startRegNum = i + 1; -#endif ret = _tuiSetRegsContent (startRegNum, NUM_REGS - 1, selected_frame, diff --git a/gdb/tui/tuiSource.c b/gdb/tui/tuiSource.c index 1552ac7..f844b36 100644 --- a/gdb/tui/tuiSource.c +++ b/gdb/tui/tuiSource.c @@ -55,32 +55,12 @@ /***************************************** -** EXTERNAL DATA DECLS ** -******************************************/ -extern int current_source_line; -extern struct symtab *current_source_symtab; - - -/***************************************** ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** ******************************************/ static struct breakpoint *_hasBreak (char *, int); -/***************************************** -** STATIC LOCAL DATA ** -******************************************/ - - -/***************************************** -** PUBLIC FUNCTIONS ** -******************************************/ - -/********************************* -** SOURCE/DISASSEM FUNCTIONS ** -*********************************/ - /* ** tuiSetSourceContent(). ** Function to display source in the source window. @@ -94,7 +74,7 @@ tuiSetSourceContent (struct symtab *s, int lineNo, int noerror) { register FILE *stream; register int i, desc, c, lineWidth, nlines; - register char *srcLine; + register char *srcLine = 0; if ((ret = tuiAllocSourceBuffer (srcWin)) == TUI_SUCCESS) { @@ -136,17 +116,24 @@ tuiSetSourceContent (struct symtab *s, int lineNo, int noerror) { register int offset, curLineNo, curLine, curLen, threshold; TuiGenWinInfoPtr locator = locatorWinInfoPtr (); - /* - ** Determine the threshold for the length of the line - ** and the offset to start the display - */ - offset = srcWin->detail.sourceInfo.horizontalOffset; + TuiSourceInfoPtr src = &srcWin->detail.sourceInfo; + + if (srcWin->generic.title) + xfree (srcWin->generic.title); + srcWin->generic.title = xstrdup (s->filename); + + if (src->filename) + xfree (src->filename); + src->filename = xstrdup (s->filename); + + /* Determine the threshold for the length of the line + and the offset to start the display. */ + offset = src->horizontalOffset; threshold = (lineWidth - 1) + offset; stream = fdopen (desc, FOPEN_RT); clearerr (stream); curLine = 0; - curLineNo = - srcWin->detail.sourceInfo.startLineOrAddr.lineNo = lineNo; + curLineNo = src->startLineOrAddr.lineNo = lineNo; if (offset > 0) srcLine = (char *) xmalloc ( (threshold + 1) * sizeof (char)); diff --git a/gdb/tui/tuiSource.h b/gdb/tui/tuiSource.h index 2c04988..96cf865 100644 --- a/gdb/tui/tuiSource.h +++ b/gdb/tui/tuiSource.h @@ -1,5 +1,5 @@ /* TUI display source window. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -26,16 +26,8 @@ extern TuiStatus tuiSetSourceContent (struct symtab *, int, int); extern void tuiShowSource (struct symtab *, TuiLineOrAddress, int); -extern void tuiShowSourceAsIs (struct symtab *, Opaque, int); extern int tuiSourceIsDisplayed (char *); extern void tuiVerticalSourceScroll (TuiScrollDirection, int); - -/******************* -** MACROS ** -*******************/ -#define m_tuiShowSourceAsIs(s, line, noerror) tuiUpdateSourceWindowAsIs(srcWin, s, line, noerror) - - #endif /*_TUI_SOURCE_H*/ diff --git a/gdb/tui/tuiSourceWin.c b/gdb/tui/tuiSourceWin.c index 7563c94..95b6cdf 100644 --- a/gdb/tui/tuiSourceWin.c +++ b/gdb/tui/tuiSourceWin.c @@ -56,80 +56,28 @@ #include "tuiDisassem.h" -/***************************************** -** EXTERNAL FUNCTION DECLS ** -******************************************/ - -/***************************************** -** EXTERNAL DATA DECLS ** -******************************************/ -extern int current_source_line; -extern struct symtab *current_source_symtab; - - -/***************************************** -** STATIC LOCAL FUNCTIONS FORWARD DECLS ** -******************************************/ - -/***************************************** -** STATIC LOCAL DATA ** -******************************************/ - - -/***************************************** -** PUBLIC FUNCTIONS ** -******************************************/ - -/********************************* -** SOURCE/DISASSEM FUNCTIONS ** -*********************************/ - -/* - ** tuiSrcWinIsDisplayed(). - */ -int -tuiSrcWinIsDisplayed (void) -{ - return (m_winPtrNotNull (srcWin) && srcWin->generic.isVisible); -} /* tuiSrcWinIsDisplayed */ - - -/* - ** tuiAsmWinIsDisplayed(). - */ -int -tuiAsmWinIsDisplayed (void) -{ - return (m_winPtrNotNull (disassemWin) && disassemWin->generic.isVisible); -} /* tuiAsmWinIsDisplayed */ - - -/* - ** tuiDisplayMainFunction(). - ** Function to display the "main" routine" - */ +/* Function to display the "main" routine. */ void -tuiDisplayMainFunction (void) +tui_display_main (void) { if ((sourceWindows ())->count > 0) { CORE_ADDR addr; - addr = parse_and_eval_address ("main"); - if (addr == (CORE_ADDR) 0) - addr = parse_and_eval_address ("MAIN"); + addr = tuiGetBeginAsmAddress (); if (addr != (CORE_ADDR) 0) { struct symtab_and_line sal; tuiUpdateSourceWindowsWithAddr (addr); sal = find_pc_line (addr, 0); - tuiSwitchFilename (sal.symtab->filename); + if (sal.symtab) + tuiUpdateLocatorFilename (sal.symtab->filename); + else + tuiUpdateLocatorFilename ("??"); } } - - return; -} /* tuiDisplayMainFunction */ +} @@ -298,22 +246,6 @@ tuiClearSourceContent (TuiWinInfoPtr winInfo, int displayPrompt) /* - ** tuiClearAllSourceWinsContent(). - */ -void -tuiClearAllSourceWinsContent (int displayPrompt) -{ - int i; - - for (i = 0; i < (sourceWindows ())->count; i++) - tuiClearSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i], - displayPrompt); - - return; -} /* tuiClearAllSourceWinsContent */ - - -/* ** tuiEraseSourceContent(). */ void @@ -356,21 +288,30 @@ tuiEraseSourceContent (TuiWinInfoPtr winInfo, int displayPrompt) } /* tuiEraseSourceContent */ -/* - ** tuiEraseAllSourceContent(). - */ -void -tuiEraseAllSourceWinsContent (int displayPrompt) +/* Redraw the complete line of a source or disassembly window. */ +static void +tui_show_source_line (TuiWinInfoPtr winInfo, int lineno) { - int i; + TuiWinElementPtr line; + int x, y; - for (i = 0; i < (sourceWindows ())->count; i++) - tuiEraseSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i], - displayPrompt); + line = (TuiWinElementPtr) winInfo->generic.content[lineno - 1]; + if (line->whichElement.source.isExecPoint) + wattron (winInfo->generic.handle, A_STANDOUT); - return; -} /* tuiEraseAllSourceWinsContent */ + mvwaddstr (winInfo->generic.handle, lineno, 1, + line->whichElement.source.line); + if (line->whichElement.source.isExecPoint) + wattroff (winInfo->generic.handle, A_STANDOUT); + /* Clear to end of line but stop before the border. */ + getyx (winInfo->generic.handle, y, x); + while (x + 1 < winInfo->generic.width) + { + waddch (winInfo->generic.handle, ' '); + getyx (winInfo->generic.handle, y, x); + } +} /* ** tuiShowSourceContent(). @@ -378,42 +319,20 @@ tuiEraseAllSourceWinsContent (int displayPrompt) void tuiShowSourceContent (TuiWinInfoPtr winInfo) { - int curLine, i, curX; - - tuiEraseSourceContent (winInfo, (winInfo->generic.contentSize <= 0)); if (winInfo->generic.contentSize > 0) { - char *line; - - for (curLine = 1; (curLine <= winInfo->generic.contentSize); curLine++) - mvwaddstr ( - winInfo->generic.handle, - curLine, - 1, - ((TuiWinElementPtr) - winInfo->generic.content[curLine - 1])->whichElement.source.line); + int lineno; + + for (lineno = 1; lineno <= winInfo->generic.contentSize; lineno++) + tui_show_source_line (winInfo, lineno); } + else + tuiEraseSourceContent (winInfo, TRUE); + checkAndDisplayHighlightIfNeeded (winInfo); tuiRefreshWin (&winInfo->generic); winInfo->generic.contentInUse = TRUE; - - return; -} /* tuiShowSourceContent */ - - -/* - ** tuiShowAllSourceWinsContent() - */ -void -tuiShowAllSourceWinsContent (void) -{ - int i; - - for (i = 0; i < (sourceWindows ())->count; i++) - tuiShowSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]); - - return; -} /* tuiShowAllSourceWinsContent */ +} /* @@ -497,19 +416,11 @@ tuiSetHasBreakAt (struct breakpoint *bp, TuiWinInfoPtr winInfo, int hasBreak) if (winInfo == srcWin) { - char *fileNameDisplayed = (char *) NULL; - - if (((TuiWinElementPtr) - locator->content[0])->whichElement.locator.fileName != - (char *) NULL) - fileNameDisplayed = ((TuiWinElementPtr) - locator->content[0])->whichElement.locator.fileName; - else if (current_source_symtab != (struct symtab *) NULL) - fileNameDisplayed = current_source_symtab->filename; + TuiSourceInfoPtr src = &winInfo->detail.sourceInfo; - gotIt = (fileNameDisplayed != (char *) NULL && + gotIt = (src->filename != (char *) NULL && bp->source_file != NULL && - (strcmp (bp->source_file, fileNameDisplayed) == 0) && + (strcmp (bp->source_file, src->filename) == 0) && content[i]->whichElement.source.lineOrAddr.lineNo == bp->line_number); } @@ -658,21 +569,6 @@ tuiShowExecInfoContent (TuiWinInfoPtr winInfo) /* - ** tuiShowAllExecInfosContent() - */ -void -tuiShowAllExecInfosContent (void) -{ - int i; - - for (i = 0; i < (sourceWindows ())->count; i++) - tuiShowExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]); - - return; -} /* tuiShowAllExecInfosContent */ - - -/* ** tuiEraseExecInfoContent(). */ void @@ -686,22 +582,6 @@ tuiEraseExecInfoContent (TuiWinInfoPtr winInfo) return; } /* tuiEraseExecInfoContent */ - -/* - ** tuiEraseAllExecInfosContent() - */ -void -tuiEraseAllExecInfosContent (void) -{ - int i; - - for (i = 0; i < (sourceWindows ())->count; i++) - tuiEraseExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]); - - return; -} /* tuiEraseAllExecInfosContent */ - - /* ** tuiClearExecInfoContent(). */ @@ -714,22 +594,6 @@ tuiClearExecInfoContent (TuiWinInfoPtr winInfo) return; } /* tuiClearExecInfoContent */ - -/* - ** tuiClearAllExecInfosContent() - */ -void -tuiClearAllExecInfosContent (void) -{ - int i; - - for (i = 0; i < (sourceWindows ())->count; i++) - tuiClearExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]); - - return; -} /* tuiClearAllExecInfosContent */ - - /* ** tuiUpdateExecInfo(). ** Function to update the execution info window @@ -756,60 +620,11 @@ tuiUpdateAllExecInfos (void) return; } /* tuiUpdateAllExecInfos */ - - -/* tuiUpdateOnEnd() - ** elz: This function clears the execution info from the source windows - ** and resets the locator to display no line info, procedure info, pc - ** info. It is called by stack_publish_stopped_with_no_frame, which - ** is called then the target terminates execution - */ -void -tuiUpdateOnEnd (void) -{ - int i; - TuiGenWinInfoPtr locator; - char *filename; - TuiWinInfoPtr winInfo; - - locator = locatorWinInfoPtr (); - - /* for all the windows (src, asm) */ - for (i = 0; i < (sourceWindows ())->count; i++) - { - TuiLineOrAddress l; - - winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i]; - - l.addr = -1; - l.lineNo = -1; - tuiSetIsExecPointAt (l, winInfo); /* the target is'n running */ - /* -1 should not match any line number or pc */ - tuiSetExecInfoContent (winInfo); /*set winInfo so that > is'n displayed */ - tuiShowExecInfoContent (winInfo); /* display the new contents */ - } - - /*now update the locator */ - tuiClearLocatorDisplay (); - tuiGetLocatorFilename (locator, &filename); - tuiSetLocatorInfo ( - filename, - (char *) NULL, - 0, - (CORE_ADDR) 0, - &((TuiWinElementPtr) locator->content[0])->whichElement.locator); - tuiShowLocatorContent (); - - return; -} /* tuiUpdateOnEnd */ - - - TuiStatus tuiAllocSourceBuffer (TuiWinInfoPtr winInfo) { - register char *srcLine, *srcLineBuf; - register int i, lineWidth, c, maxLines; + register char *srcLineBuf; + register int i, lineWidth, maxLines; TuiStatus ret = TUI_FAILURE; maxLines = winInfo->generic.height; /* less the highlight box */ diff --git a/gdb/tui/tuiSourceWin.h b/gdb/tui/tuiSourceWin.h index ced01f7..803cb90 100644 --- a/gdb/tui/tuiSourceWin.h +++ b/gdb/tui/tuiSourceWin.h @@ -1,5 +1,5 @@ /* TUI display source/assembly window. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -22,7 +22,8 @@ #ifndef _TUI_SOURCEWIN_H #define _TUI_SOURCEWIN_H -extern void tuiDisplayMainFunction (void); +/* Function to display the "main" routine. */ +extern void tui_display_main (void); extern void tuiUpdateSourceWindow (TuiWinInfoPtr, struct symtab *, TuiLineOrAddress, int); extern void tuiUpdateSourceWindowAsIs (TuiWinInfoPtr, struct symtab *, TuiLineOrAddress, @@ -31,19 +32,13 @@ extern void tuiUpdateSourceWindowsWithAddr (CORE_ADDR); extern void tuiUpdateSourceWindowsWithLine (struct symtab *, int); extern void tuiUpdateSourceWindowsFromLocator (void); extern void tuiClearSourceContent (TuiWinInfoPtr, int); -extern void tuiClearAllSourceWinsContent (int); extern void tuiEraseSourceContent (TuiWinInfoPtr, int); -extern void tuiEraseAllSourceWinsContent (int); extern void tuiSetSourceContentNil (TuiWinInfoPtr, char *); extern void tuiShowSourceContent (TuiWinInfoPtr); -extern void tuiShowAllSourceWinsContent (void); extern void tuiHorizontalSourceScroll (TuiWinInfoPtr, TuiScrollDirection, int); -extern void tuiUpdateOnEnd (void); - extern TuiStatus tuiSetExecInfoContent (TuiWinInfoPtr); extern void tuiShowExecInfoContent (TuiWinInfoPtr); -extern void tuiShowAllExecInfosContent (void); extern void tuiEraseExecInfoContent (TuiWinInfoPtr); extern void tuiEraseAllExecInfosContent (void); extern void tuiClearExecInfoContent (TuiWinInfoPtr); diff --git a/gdb/tui/tuiStack.c b/gdb/tui/tuiStack.c index 43d0229..d3f0404 100644 --- a/gdb/tui/tuiStack.c +++ b/gdb/tui/tuiStack.c @@ -44,6 +44,7 @@ #include "breakpoint.h" #include "frame.h" #include "command.h" +#include "top.h" #include "tui.h" #include "tuiData.h" @@ -51,49 +52,54 @@ #include "tuiGeneralWin.h" #include "tuiSource.h" #include "tuiSourceWin.h" +#include "tui-file.h" -/***************************************** -** STATIC LOCAL FUNCTIONS FORWARD DECLS ** -******************************************/ - -static char *_getFuncNameFromFrame (struct frame_info *); -static void _tuiUpdateLocation_command (char *, int); +/* Get a printable name for the function at the address. + The symbol name is demangled if demangling is turned on. + Returns a pointer to a static area holding the result. */ +static char* tui_get_function_from_frame (struct frame_info *fi); +/* Set the filename portion of the locator. */ +static void tui_set_locator_filename (const char *filename); +/* Update the locator, with the provided arguments. */ +static void tui_set_locator_info (const char *filename, const char *procname, + int lineno, CORE_ADDR addr); -/***************************************** -** PUBLIC FUNCTION ** -******************************************/ +static void tui_update_command (char *, int); + -/* - ** tuiClearLocatorDisplay() - */ -void -tuiClearLocatorDisplay (void) +/* Get a printable name for the function at the address. + The symbol name is demangled if demangling is turned on. + Returns a pointer to a static area holding the result. */ +static char* +tui_get_function_from_frame (struct frame_info *fi) { - TuiGenWinInfoPtr locator = locatorWinInfoPtr (); - int i; - - if (locator->handle != (WINDOW *) NULL) - { - /* No need to werase, since writing a line of - * blanks which we do below, is equivalent. - */ - /* werase(locator->handle); */ - wmove (locator->handle, 0, 0); - wstandout (locator->handle); - for (i = 0; i < locator->width; i++) - waddch (locator->handle, ' '); - wstandend (locator->handle); - tuiRefreshWin (locator); - wmove (locator->handle, 0, 0); - locator->contentInUse = FALSE; - } - - return; -} /* tuiClearLocatorDisplay */ - + static char name[256]; + struct ui_file *stream = tui_sfileopen (256); + char *p; + + print_address_symbolic (fi->pc, stream, demangle, ""); + p = tui_file_get_strbuf (stream); + + /* Use simple heuristics to isolate the function name. The symbol can + be demangled and we can have function parameters. Remove them because + the status line is too short to display them. */ + if (*p == '<') + p++; + strncpy (name, p, sizeof (name)); + p = strchr (name, '('); + if (!p) + p = strchr (name, '>'); + if (p) + *p = 0; + p = strchr (name, '+'); + if (p) + *p = 0; + ui_file_delete (stream); + return name; +} /* ** tuiShowLocatorContent() @@ -114,6 +120,7 @@ tuiShowLocatorContent (void) wmove (locator->handle, 0, 0); wstandout (locator->handle); waddstr (locator->handle, string); + wclrtoeol (locator->handle); wstandend (locator->handle); tuiRefreshWin (locator); wmove (locator->handle, 0, 0); @@ -126,178 +133,56 @@ tuiShowLocatorContent (void) return; } /* tuiShowLocatorContent */ - -/* Update the locator, with the provided arguments. */ -void -tuiSetLocatorInfo (char *fname, char *procname, int lineNo, - CORE_ADDR addr, TuiLocatorElementPtr element) -{ - element->fileName[0] = (char) 0; - element->procName[0] = (char) 0; - strcat_to_buf (element->fileName, MAX_LOCATOR_ELEMENT_LEN, fname); - strcat_to_buf (element->procName, MAX_LOCATOR_ELEMENT_LEN, procname); - element->lineNo = lineNo; - element->addr = addr; -} - - -/* - ** tuiUpdateLocatorFilename(). - ** Update only the filename portion of the locator. - */ -void -tuiUpdateLocatorFilename (const char *fileName) -{ - TuiGenWinInfoPtr locator = locatorWinInfoPtr (); - - if (locator->content[0] == (Opaque) NULL) - tuiSetLocatorContent ((struct frame_info *) NULL); - ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName[0] = (char) 0; - strcat_to_buf (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName, - MAX_LOCATOR_ELEMENT_LEN, - fileName); - - tuiShowLocatorContent (); - - return; -} /* tuiUpdateLocatorFilename */ - -/* - ** tuiSwitchFilename(). - ** Update the filename portion of the locator. Clear the other info in locator. - ** (elz) - */ -void -tuiSwitchFilename (char *fileName) +/* Set the filename portion of the locator. */ +static void +tui_set_locator_filename (const char *filename) { TuiGenWinInfoPtr locator = locatorWinInfoPtr (); + TuiLocatorElementPtr element; if (locator->content[0] == (Opaque) NULL) - tuiSetLocatorContent ((struct frame_info *) NULL); - ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName[0] = (char) 0; - - tuiSetLocatorInfo (fileName, - (char *) NULL, - 0, - (CORE_ADDR) 0, - &((TuiWinElementPtr) locator->content[0])->whichElement.locator); - - tuiShowLocatorContent (); - - return; -} /* tuiSwitchFilename */ - - -/* - ** tuiGetLocatorFilename(). - ** Get the filename portion of the locator. - ** (elz) - */ -void -tuiGetLocatorFilename (TuiGenWinInfoPtr locator, char **filename) -{ - - /* the current filename could be non known, in which case the xmalloc would - allocate no memory, because the length would be 0 */ - if (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName) { - int name_length = - strlen (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName); - - (*filename) = (char *) xmalloc (name_length + 1); - strcpy ((*filename), - ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName); + tui_set_locator_info (filename, NULL, 0, 0); + return; } - return; -} /* tuiGetLocatorFilename */ - - -/* - ** tuiUpdateLocatorInfoFromFrame(). - ** Function to update the locator, with the information extracted from frameInfo - */ -void -tuiUpdateLocatorInfoFromFrame (struct frame_info *frameInfo, - TuiLocatorElementPtr element) -{ - struct symtab_and_line symtabAndLine; - - /* now get the new info */ - symtabAndLine = find_pc_line (frameInfo->pc, - (frameInfo->next != (struct frame_info *) NULL && - !frameInfo->next->signal_handler_caller && - !frame_in_dummy (frameInfo->next))); - if (symtabAndLine.symtab && symtabAndLine.symtab->filename) - tuiSetLocatorInfo (symtabAndLine.symtab->filename, - _getFuncNameFromFrame (frameInfo), - symtabAndLine.line, - frameInfo->pc, - element); - else - tuiSetLocatorInfo ((char *) NULL, - _getFuncNameFromFrame (frameInfo), - 0, - frameInfo->pc, - element); - - return; -} /* tuiUpdateLocatorInfoFromFrame */ - + element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator; + element->fileName[0] = 0; + strcat_to_buf (element->fileName, MAX_LOCATOR_ELEMENT_LEN, filename); +} -/* - ** tuiSetLocatorContent(). - ** Function to set the content of the locator - */ -void -tuiSetLocatorContent (struct frame_info *frameInfo) +/* Update the locator, with the provided arguments. */ +static void +tui_set_locator_info (const char *filename, const char *procname, int lineno, + CORE_ADDR addr) { TuiGenWinInfoPtr locator = locatorWinInfoPtr (); - TuiWinElementPtr element; - struct symtab_and_line symtabAndLine; + TuiLocatorElementPtr element; - /* Allocate the element if necessary */ + /* Allocate the locator content if necessary. */ if (locator->contentSize <= 0) { - TuiWinContent contentPtr; - - if ((locator->content = (OpaquePtr) allocContent (1, locator->type)) == (OpaquePtr) NULL) - error ("Unable to Allocate Memory to Display Location."); + locator->content = (OpaquePtr) allocContent (1, locator->type); locator->contentSize = 1; } - if (frameInfo != (struct frame_info *) NULL) - tuiUpdateLocatorInfoFromFrame (frameInfo, - &((TuiWinElementPtr) locator->content[0])->whichElement.locator); - else - tuiSetLocatorInfo ((char *) NULL, - (char *) NULL, - 0, - (CORE_ADDR) 0, - &((TuiWinElementPtr) locator->content[0])->whichElement.locator); - return; -} /* tuiSetLocatorContent */ - + element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator; + element->procName[0] = (char) 0; + strcat_to_buf (element->procName, MAX_LOCATOR_ELEMENT_LEN, procname); + element->lineNo = lineno; + element->addr = addr; + tui_set_locator_filename (filename); +} -/* - ** tuiUpdateLocatorDisplay(). - ** Function to update the locator display - */ +/* Update only the filename portion of the locator. */ void -tuiUpdateLocatorDisplay (struct frame_info *frameInfo) +tuiUpdateLocatorFilename (const char *filename) { - tuiClearLocatorDisplay (); - tuiSetLocatorContent (frameInfo); + tui_set_locator_filename (filename); tuiShowLocatorContent (); +} - return; -} /* tuiUpdateLocatorDisplay */ - - -/* - ** tuiShowFrameInfo(). - ** Function to print the frame inforrmation for the TUI. - */ +/* Function to print the frame information for the TUI. */ void tuiShowFrameInfo (struct frame_info *fi) { @@ -307,19 +192,24 @@ tuiShowFrameInfo (struct frame_info *fi) if (fi) { register int startLine, i; - register struct symtab *s; CORE_ADDR low; TuiGenWinInfoPtr locator = locatorWinInfoPtr (); int sourceAlreadyDisplayed; - - - s = find_pc_symtab (fi->pc); - if (s == 0) - return; - + struct symtab_and_line sal; + + sal = find_pc_line (fi->pc, + (fi->next != (struct frame_info *) NULL && + !fi->next->signal_handler_caller && + !frame_in_dummy (fi->next))); + + sourceAlreadyDisplayed = sal.symtab != 0 + && tuiSourceIsDisplayed (sal.symtab->filename); + tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename, + tui_get_function_from_frame (fi), + sal.line, + fi->pc); + tuiShowLocatorContent (); startLine = 0; - sourceAlreadyDisplayed = tuiSourceIsDisplayed (s->filename); - tuiUpdateLocatorDisplay (fi); for (i = 0; i < (sourceWindows ())->count; i++) { TuiWhichElement *item; @@ -347,7 +237,7 @@ tuiShowFrameInfo (struct frame_info *fi) l.lineNo = startLine; if (!(sourceAlreadyDisplayed && tuiLineIsDisplayed (item->locator.lineNo, winInfo, TRUE))) - tuiUpdateSourceWindow (winInfo, s, l, TRUE); + tuiUpdateSourceWindow (winInfo, sal.symtab, l, TRUE); else { l.lineNo = item->locator.lineNo; @@ -361,7 +251,7 @@ tuiShowFrameInfo (struct frame_info *fi) TuiLineOrAddress a; a.addr = low; if (!tuiAddrIsDisplayed (item->locator.addr, winInfo, TRUE)) - tuiUpdateSourceWindow (winInfo, s, a, TRUE); + tuiUpdateSourceWindow (winInfo, sal.symtab, a, TRUE); else { a.addr = item->locator.addr; @@ -374,7 +264,8 @@ tuiShowFrameInfo (struct frame_info *fi) } else { - tuiUpdateLocatorDisplay (fi); + tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0); + tuiShowLocatorContent (); for (i = 0; i < (sourceWindows ())->count; i++) { winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i]; @@ -382,70 +273,23 @@ tuiShowFrameInfo (struct frame_info *fi) tuiUpdateExecInfo (winInfo); } } +} - return; -} /* tuiShowFrameInfo */ - -/* - ** _initialize_tuiStack(). - ** Function to initialize gdb commands, for tui window stack manipulation. - */ +/* Function to initialize gdb commands, for tui window stack manipulation. */ void _initialize_tuiStack (void) { - add_com ("update", class_tui, _tuiUpdateLocation_command, - "Update the source window and locator to display the current execution point.\n"); + add_com ("update", class_tui, tui_update_command, + "Update the source window and locator to display the current " + "execution point.\n"); } - -/***************************************** -** STATIC LOCAL FUNCTIONS ** -******************************************/ - -/* - ** _getFuncNameFromFrame(). - */ -static char * -_getFuncNameFromFrame (struct frame_info *frameInfo) -{ - char *funcName = (char *) NULL; - - find_pc_partial_function (frameInfo->pc, - &funcName, - (CORE_ADDR *) NULL, - (CORE_ADDR *) NULL); - return funcName; -} /* _getFuncNameFromFrame */ - - -/* - ** _tuiUpdateLocation_command(). - ** Command to update the display with the current execution point - */ +/* Command to update the display with the current execution point. */ static void -_tuiUpdateLocation_command (char *arg, int fromTTY) +tui_update_command (char *arg, int from_tty) { -#ifndef TRY -extern void frame_command (char *, int); - frame_command ("0", FALSE); -#else - struct frame_info *curFrame; - - /* Obtain the current execution point */ - if ((curFrame = get_current_frame ()) != (struct frame_info *) NULL) - { - struct frame_info *frame; - int curLevel = 0; - - for (frame = get_prev_frame (curLevel); - (frame != (struct frame_info *) NULL && (frame != curFrame)); - frame = get_prev_frame (frame)) - curLevel++; + char cmd[sizeof("frame 0")]; - if (curFrame != (struct frame_info *) NULL) - print_frame_info (frame, curLevel, 0, 1); - } -#endif - - return; -} /* _tuiUpdateLocation_command */ + strcpy (cmd, "frame 0"); + execute_command (cmd, from_tty); +} diff --git a/gdb/tui/tuiStack.h b/gdb/tui/tuiStack.h index 90aab5a..14be497 100644 --- a/gdb/tui/tuiStack.h +++ b/gdb/tui/tuiStack.h @@ -1,5 +1,5 @@ /* TUI display locator. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -25,20 +25,9 @@ ** This header file supports */ -extern void tuiSetLocatorInfo (char *, char *, int, CORE_ADDR, - TuiLocatorElementPtr); extern void tuiUpdateLocatorFilename (const char *); -extern void tuiUpdateLocatorInfoFromFrame - (struct frame_info *, TuiLocatorElementPtr); -extern void tuiUpdateLocatorDisplay (struct frame_info *); -extern void tuiSetLocatorContent (struct frame_info *); extern void tuiShowLocatorContent (void); -extern void tuiClearLocatorContent (void); -extern void tuiClearLocatorDisplay (void); -extern void tuiSwitchFilename (char *); extern void tuiShowFrameInfo (struct frame_info *); -extern void tuiGetLocatorFilename (TuiGenWinInfoPtr, char **); - #endif /*_TUI_STACK_H*/ diff --git a/gdb/tui/tuiWin.c b/gdb/tui/tuiWin.c index a33f661..82c3d49 100644 --- a/gdb/tui/tuiWin.c +++ b/gdb/tui/tuiWin.c @@ -52,6 +52,7 @@ #include "breakpoint.h" #include "frame.h" #include "cli/cli-cmds.h" +#include "top.h" #include "tui.h" #include "tuiData.h" @@ -64,11 +65,6 @@ #include "tuiDataWin.h" /******************************* -** External Declarations -********************************/ -extern void init_page_info (); - -/******************************* ** Static Local Decls ********************************/ static void _makeVisibleWithNewHeight (TuiWinInfoPtr); @@ -396,36 +392,21 @@ Usage: w <#lines>\n"); add_show_from_set (c, &tui_showlist); } - -/* - ** tuiClearWinFocusFrom - ** Clear the logical focus from winInfo - */ +/* Update gdb's knowledge of the terminal size. */ void -tuiClearWinFocusFrom (TuiWinInfoPtr winInfo) +tui_update_gdb_sizes () { - if (m_winPtrNotNull (winInfo)) - { - if (winInfo->generic.type != CMD_WIN) - unhighlightWin (winInfo); - tuiSetWinWithFocus ((TuiWinInfoPtr) NULL); - } - - return; -} /* tuiClearWinFocusFrom */ - - -/* - ** tuiClearWinFocus(). - ** Clear the window that has focus. - */ -void -tuiClearWinFocus (void) -{ - tuiClearWinFocusFrom (tuiWinWithFocus ()); + char cmd[50]; + extern int screenheight, screenwidth; /* in readline */ - return; -} /* tuiClearWinFocus */ + /* Set to TUI command window dimension or use readline values. */ + sprintf (cmd, "set width %d", + tui_active ? cmdWin->generic.width : screenwidth); + execute_command (cmd, 0); + sprintf (cmd, "set height %d", + tui_active ? cmdWin->generic.height : screenheight); + execute_command (cmd, 0); +} /* @@ -607,9 +588,6 @@ tuiRefreshAll (void) { case SRC_WIN: case DISASSEM_WIN: - tuiClearWin (&winList[type]->generic); - if (winList[type]->detail.sourceInfo.hasLocator) - tuiClearLocatorDisplay (); tuiShowSourceContent (winList[type]); checkAndDisplayHighlightIfNeeded (winList[type]); tuiEraseExecInfoContent (winList[type]); @@ -623,11 +601,8 @@ tuiRefreshAll (void) } } } - tuiClearLocatorDisplay (); tuiShowLocatorContent (); - - return; -} /* tuiRefreshAll */ +} /* @@ -650,12 +625,12 @@ tuiResizeAll (void) TuiWinInfoPtr firstWin, secondWin; TuiGenWinInfoPtr locator = locatorWinInfoPtr (); TuiWinType winType; - int i, newHeight, splitDiff, cmdSplitDiff, numWinsDisplayed = 2; + int newHeight, splitDiff, cmdSplitDiff, numWinsDisplayed = 2; /* turn keypad off while we resize */ if (winWithFocus != cmdWin) keypad (cmdWin->generic.handle, FALSE); - init_page_info (); + tui_update_gdb_sizes (); setTermHeightTo (screenheight); setTermWidthTo (screenwidth); if (curLayout == SRC_DISASSEM_COMMAND || @@ -1076,7 +1051,7 @@ The window name specified must be valid and visible.\n"); warning ("Invalid window height specified.\n%s", WIN_HEIGHT_USAGE); else - init_page_info (); + tui_update_gdb_sizes (); } else warning ("Invalid window height specified.\n%s", @@ -1168,7 +1143,7 @@ _tuiAdjustWinHeights (TuiWinInfoPtr primaryWinInfo, int newHeight) status = TUI_SUCCESS; if (newHeight != primaryWinInfo->generic.height) { - int i, diff; + int diff; TuiWinInfoPtr winInfo; TuiGenWinInfoPtr locator = locatorWinInfoPtr (); TuiLayoutType curLayout = currentLayout (); @@ -1316,7 +1291,6 @@ static void _makeInvisibleAndSetNewHeight (TuiWinInfoPtr winInfo, int height) { int i; - struct symtab *s; TuiGenWinInfoPtr genWinInfo; @@ -1365,9 +1339,7 @@ _makeInvisibleAndSetNewHeight (TuiWinInfoPtr winInfo, int height) default: break; } - - return; -} /* _makeInvisibleAndSetNewHeight */ +} /* @@ -1379,7 +1351,6 @@ _makeInvisibleAndSetNewHeight (TuiWinInfoPtr winInfo, int height) static void _makeVisibleWithNewHeight (TuiWinInfoPtr winInfo) { - int i; struct symtab *s; m_beVisible (&winInfo->generic); @@ -1421,7 +1392,6 @@ _makeVisibleWithNewHeight (TuiWinInfoPtr winInfo) if (m_hasLocator (winInfo)) { m_beVisible (locatorWinInfoPtr ()); - tuiClearLocatorDisplay (); tuiShowLocatorContent (); } break; @@ -1450,7 +1420,7 @@ _newHeightOk (TuiWinInfoPtr primaryWinInfo, int newHeight) if (ok) { - int diff, curHeight; + int diff; TuiLayoutType curLayout = currentLayout (); diff = (newHeight - primaryWinInfo->generic.height) * (-1); diff --git a/gdb/tui/tuiWin.h b/gdb/tui/tuiWin.h index ac21042..bc26080 100644 --- a/gdb/tui/tuiWin.h +++ b/gdb/tui/tuiWin.h @@ -1,5 +1,5 @@ /* TUI window generic functions. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. This file is part of GDB. @@ -37,8 +37,6 @@ extern void tuiScrollLeft (TuiWinInfoPtr, int); extern void tuiScrollRight (TuiWinInfoPtr, int); extern void tui_scroll (TuiScrollDirection, TuiWinInfoPtr, int); extern void tuiSetWinFocusTo (TuiWinInfoPtr); -extern void tuiClearWinFocusFrom (TuiWinInfoPtr); -extern void tuiClearWinFocus (void); extern void tuiResizeAll (void); extern void tuiRefreshAll (void); extern void tuiSigwinchHandler (int); @@ -54,5 +52,8 @@ extern int tui_active_border_attrs; extern int tui_update_variables (); +/* Update gdb's knowledge of the terminal size. */ +extern void tui_update_gdb_sizes (void); + #endif /*_TUI_WIN_H*/ diff --git a/gdb/version.in b/gdb/version.in index 5e82357..8ea94ca 100644 --- a/gdb/version.in +++ b/gdb/version.in @@ -1 +1 @@ -2002-08-24-cvs +2002-08-25-cvs diff --git a/sim/ChangeLog b/sim/ChangeLog index 4d6c1ad..35bcfb5 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,7 @@ +2002-08-24 Geoffrey Keating <geoffk@redhat.com> + + * MAINTAINERS: Update my email address. + 2002-07-17 Andrew Cagney <ac131313@redhat.com> * w65/: Delete directory. diff --git a/sim/MAINTAINERS b/sim/MAINTAINERS index 9615a13..e54adb5 100644 --- a/sim/MAINTAINERS +++ b/sim/MAINTAINERS @@ -11,7 +11,7 @@ gdb-patches@sources.redhat.com arm Nick Clifton <nickc@redhat.com> ppc Andrew Cagney <ac131313@redhat.com> -ppc Geoff Keating <geoffk@redhat.com> +ppc Geoff Keating <geoffk@geoffk.org> m68hc11 Stephane Carrez <stcarrez@nerim.fr> mips Andrew Cagney <ac131313@redhat.com> mips Chris Demetriou <cgd@broadcom.com> |