From: John Marino Date: Wed, 31 Aug 2011 21:22:16 +0000 (+0200) Subject: Import gdb 7.3 into vendor branch X-Git-Tag: v2.12.0~90^2 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/c50c785cb49e9377ca78104c5540c7b33f768771 Import gdb 7.3 into vendor branch --- diff --git a/contrib/gdb-7/bfd/archive.c b/contrib/gdb-7/bfd/archive.c index fbe555b03f..86d07e9f4a 100644 --- a/contrib/gdb-7/bfd/archive.c +++ b/contrib/gdb-7/bfd/archive.c @@ -1,6 +1,6 @@ /* BFD back-end for archive files (libraries). Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault. @@ -348,7 +348,7 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename) abfd != NULL; abfd = abfd->archive_next) { - if (strcmp (filename, abfd->filename) == 0) + if (filename_cmp (filename, abfd->filename) == 0) return abfd; } abfd = bfd_openr (filename, NULL); @@ -655,6 +655,9 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) n_nfd->arelt_data = new_areldata; + /* Copy BFD_COMPRESS and BFD_DECOMPRESS flags. */ + n_nfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS); + if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) return n_nfd; @@ -1106,6 +1109,7 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd) struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int stringsize; + unsigned int left; bfd_size_type amt; carsym *set; int i = bfd_bread (nextname, 16, abfd); @@ -1133,43 +1137,46 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd) if (mapdata == NULL) return FALSE; - amt = mapdata->parsed_size; - raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt); - if (raw_armap == NULL) + if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE) { + wrong_format: + bfd_set_error (bfd_error_wrong_format); byebye: bfd_release (abfd, mapdata); return FALSE; } + left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE; + + amt = mapdata->parsed_size; + raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt); + if (raw_armap == NULL) + goto byebye; if (bfd_bread (raw_armap, amt, abfd) != amt) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); - byebyebye: - bfd_release (abfd, raw_armap); goto byebye; } ardata->symdef_count = H_GET_16 (abfd, raw_armap); - if (ardata->symdef_count * BSD_SYMDEF_SIZE - > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE) - { - /* Probably we're using the wrong byte ordering. */ - bfd_set_error (bfd_error_wrong_format); - goto byebyebye; - } - ardata->cache = 0; stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE); + if (stringsize > left) + goto wrong_format; + left -= stringsize; + /* Skip sym count and string sz. */ stringbase = ((char *) raw_armap + HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE); rbase = (bfd_byte *) stringbase + stringsize; amt = ardata->symdef_count * BSD_SYMDEF_SIZE; + if (amt > left) + goto wrong_format; + ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt); if (!ardata->symdefs) return FALSE; @@ -1213,7 +1220,9 @@ _bfd_slurp_extended_name_table (bfd *abfd) /* FIXME: Formatting sucks here, and in case of failure of BFD_READ, we probably don't want to return TRUE. */ - bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET); + if (bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET) != 0) + return FALSE; + if (bfd_bread (nextname, 16, abfd) == 16) { if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) @@ -1352,7 +1361,7 @@ adjust_relative_path (const char * path, const char * ref_path) while (*e2 && ! IS_DIR_SEPARATOR (*e2)) ++e2; if (*e1 == '\0' || *e2 == '\0' || e1 - pathp != e2 - refp - || strncmp (pathp, refp, e1 - pathp) != 0) + || filename_ncmp (pathp, refp, e1 - pathp) != 0) break; pathp = e1 + 1; refp = e2 + 1; @@ -1457,7 +1466,7 @@ _bfd_construct_extended_name_table (bfd *abfd, /* If the path is the same as the previous path seen, reuse it. This can happen when flattening a thin archive that contains other archives. */ - if (last_filename && strcmp (last_filename, filename) == 0) + if (last_filename && filename_cmp (last_filename, filename) == 0) continue; last_filename = filename; @@ -1503,7 +1512,7 @@ _bfd_construct_extended_name_table (bfd *abfd, else { struct ar_hdr *hdr = arch_hdr (current); - if (strncmp (normal, hdr->ar_name, thislen) != 0 + if (filename_ncmp (normal, hdr->ar_name, thislen) != 0 || (thislen < sizeof hdr->ar_name && hdr->ar_name[thislen] != ar_padchar (current))) { @@ -1551,7 +1560,7 @@ _bfd_construct_extended_name_table (bfd *abfd, archive that contains other archives. If the path is relative, adjust it relative to the containing archive. */ - if (last_filename && strcmp (last_filename, filename) == 0) + if (last_filename && filename_cmp (last_filename, filename) == 0) normal = last_filename; else if (! IS_ABSOLUTE_PATH (filename) && ! IS_ABSOLUTE_PATH (abfd->filename)) @@ -1649,7 +1658,7 @@ _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd, len = (len + 3) & ~3; arch_eltdata (current)->extra_size = len; - _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%u", len); + _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%lu", len); } } @@ -2292,31 +2301,28 @@ bsd_write_armap (bfd *arch, bfd_byte temp[4]; unsigned int count; struct ar_hdr hdr; - struct stat statbuf; long uid, gid; firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; - stat (arch->filename, &statbuf); + /* If deterministic, we use 0 as the timestamp in the map. + Some linkers may require that the archive filesystem modification + time is less than (or near to) the archive map timestamp. Those + linkers should not be used with deterministic mode. (GNU ld and + Gold do not have this restriction.) */ + bfd_ardata (arch)->armap_timestamp = 0; + uid = 0; + gid = 0; if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0) { - /* Remember the timestamp, to keep it holy. But fudge it a little. */ - bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime - + ARMAP_TIME_OFFSET); + struct stat statbuf; + + if (stat (arch->filename, &statbuf) == 0) + bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime + + ARMAP_TIME_OFFSET); uid = getuid(); gid = getgid(); } - else - { - /* If deterministic, we use 0 as the timestamp in the map. - Some linkers may require that the archive filesystem modification - time is less than (or near to) the archive map timestamp. Those - linkers should not be used with deterministic mode. (GNU ld and - Gold do not have this restriction.) */ - bfd_ardata (arch)->armap_timestamp = 0; - uid = 0; - gid = 0; - } memset (&hdr, ' ', sizeof (struct ar_hdr)); memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG)); diff --git a/contrib/gdb-7/bfd/archures.c b/contrib/gdb-7/bfd/archures.c index 0e085713b8..cd8500f779 100644 --- a/contrib/gdb-7/bfd/archures.c +++ b/contrib/gdb-7/bfd/archures.c @@ -173,6 +173,7 @@ DESCRIPTION .#define bfd_mach_mips5 5 .#define bfd_mach_mips_loongson_2e 3001 .#define bfd_mach_mips_loongson_2f 3002 +.#define bfd_mach_mips_loongson_3a 3003 .#define bfd_mach_mips_sb1 12310201 {* octal 'SB', 01 *} .#define bfd_mach_mips_octeon 6501 .#define bfd_mach_mips_xlr 887682 {* decimal 'XLR' *} @@ -184,6 +185,8 @@ DESCRIPTION .#define bfd_mach_i386_i386 1 .#define bfd_mach_i386_i8086 2 .#define bfd_mach_i386_i386_intel_syntax 3 +.#define bfd_mach_x64_32 32 +.#define bfd_mach_x64_32_intel_syntax 33 .#define bfd_mach_x86_64 64 .#define bfd_mach_x86_64_intel_syntax 65 . bfd_arch_l1om, {* Intel L1OM *} @@ -310,7 +313,9 @@ DESCRIPTION . bfd_arch_v850, {* NEC V850 *} .#define bfd_mach_v850 1 .#define bfd_mach_v850e 'E' -.#define bfd_mach_v850e1 '1' +.#define bfd_mach_v850e1 '1' +.#define bfd_mach_v850e2 0x4532 +.#define bfd_mach_v850e2v3 0x45325633 . bfd_arch_arc, {* ARC Cores *} .#define bfd_mach_arc_5 5 .#define bfd_mach_arc_6 6 @@ -371,6 +376,13 @@ DESCRIPTION .#define bfd_mach_avr5 5 .#define bfd_mach_avr51 51 .#define bfd_mach_avr6 6 +.#define bfd_mach_avrxmega1 101 +.#define bfd_mach_avrxmega2 102 +.#define bfd_mach_avrxmega3 103 +.#define bfd_mach_avrxmega4 104 +.#define bfd_mach_avrxmega5 105 +.#define bfd_mach_avrxmega6 106 +.#define bfd_mach_avrxmega7 107 . bfd_arch_bfin, {* ADI Blackfin *} .#define bfd_mach_bfin 1 . bfd_arch_cr16, {* National Semiconductor CompactRISC (ie CR16). *} diff --git a/contrib/gdb-7/bfd/bfd-in.h b/contrib/gdb-7/bfd/bfd-in.h index cfa5225325..63fcdc9bb4 100644 --- a/contrib/gdb-7/bfd/bfd-in.h +++ b/contrib/gdb-7/bfd/bfd-in.h @@ -404,6 +404,10 @@ extern struct bfd_hash_entry *bfd_hash_lookup extern struct bfd_hash_entry *bfd_hash_insert (struct bfd_hash_table *, const char *, unsigned long); +/* Rename an entry in a hash table. */ +extern void bfd_hash_rename + (struct bfd_hash_table *, const char *, struct bfd_hash_entry *); + /* Replace an entry in a hash table. */ extern void bfd_hash_replace (struct bfd_hash_table *, struct bfd_hash_entry *old, diff --git a/contrib/gdb-7/bfd/bfd-in2.h b/contrib/gdb-7/bfd/bfd-in2.h index f97c67fd13..a1ef1c1ef3 100644 --- a/contrib/gdb-7/bfd/bfd-in2.h +++ b/contrib/gdb-7/bfd/bfd-in2.h @@ -411,6 +411,10 @@ extern struct bfd_hash_entry *bfd_hash_lookup extern struct bfd_hash_entry *bfd_hash_insert (struct bfd_hash_table *, const char *, unsigned long); +/* Rename an entry in a hash table. */ +extern void bfd_hash_rename + (struct bfd_hash_table *, const char *, struct bfd_hash_entry *); + /* Replace an entry in a hash table. */ extern void bfd_hash_replace (struct bfd_hash_table *, struct bfd_hash_entry *old, @@ -964,6 +968,7 @@ extern struct coff_comdat_info *bfd_coff_get_comdat_section void bfd_init (void); /* Extracted from opncls.c. */ +extern unsigned int bfd_use_reserved_id; bfd *bfd_fopen (const char *filename, const char *target, const char *mode, int fd); @@ -1000,6 +1005,10 @@ bfd_boolean bfd_make_writable (bfd *abfd); bfd_boolean bfd_make_readable (bfd *abfd); +void *bfd_alloc (bfd *abfd, bfd_size_type wanted); + +void *bfd_zalloc (bfd *abfd, bfd_size_type wanted); + unsigned long bfd_calc_gnu_debuglink_crc32 (unsigned long crc, const unsigned char *buf, bfd_size_type len); @@ -1348,6 +1357,12 @@ typedef struct bfd_section /* Mark flag used by some linker backends for garbage collection. */ unsigned int gc_mark : 1; + /* Section compression status. */ + unsigned int compress_status : 2; +#define COMPRESS_SECTION_NONE 0 +#define COMPRESS_SECTION_DONE 1 +#define DECOMPRESS_SECTION_SIZED 2 + /* The following flags are used by the ELF linker. */ /* Mark sections which have been allocated to segments. */ @@ -1404,6 +1419,9 @@ typedef struct bfd_section section size calculated on a previous linker relaxation pass. */ bfd_size_type rawsize; + /* The compressed size of the section in octets. */ + bfd_size_type compressed_size; + /* Relaxation table. */ struct relax_table *relax; @@ -1637,17 +1655,17 @@ extern asection bfd_ind_section; /* name, id, index, next, prev, flags, user_set_vma, */ \ { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ \ - /* linker_mark, linker_has_input, gc_mark, segment_mark, */ \ + /* linker_mark, linker_has_input, gc_mark, decompress_status, */ \ 0, 0, 1, 0, \ \ - /* sec_info_type, use_rela_p, */ \ - 0, 0, \ + /* segment_mark, sec_info_type, use_rela_p, */ \ + 0, 0, 0, \ \ /* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */ \ 0, 0, 0, 0, 0, 0, \ \ - /* vma, lma, size, rawsize, relax, relax_count, */ \ - 0, 0, 0, 0, 0, 0, \ + /* vma, lma, size, rawsize, compressed_size, relax, relax_count, */ \ + 0, 0, 0, 0, 0, 0, 0, \ \ /* output_offset, output_section, alignment_power, */ \ 0, (struct bfd_section *) &SEC, 0, \ @@ -1699,6 +1717,9 @@ asection *bfd_make_section (bfd *, const char *name); bfd_boolean bfd_set_section_flags (bfd *abfd, asection *sec, flagword flags); +void bfd_rename_section + (bfd *abfd, asection *sec, const char *newname); + void bfd_map_over_sections (bfd *abfd, void (*func) (bfd *abfd, asection *sect, void *obj), @@ -1839,6 +1860,7 @@ enum bfd_architecture #define bfd_mach_mips5 5 #define bfd_mach_mips_loongson_2e 3001 #define bfd_mach_mips_loongson_2f 3002 +#define bfd_mach_mips_loongson_3a 3003 #define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ #define bfd_mach_mips_octeon 6501 #define bfd_mach_mips_xlr 887682 /* decimal 'XLR' */ @@ -1850,6 +1872,8 @@ enum bfd_architecture #define bfd_mach_i386_i386 1 #define bfd_mach_i386_i8086 2 #define bfd_mach_i386_i386_intel_syntax 3 +#define bfd_mach_x64_32 32 +#define bfd_mach_x64_32_intel_syntax 33 #define bfd_mach_x86_64 64 #define bfd_mach_x86_64_intel_syntax 65 bfd_arch_l1om, /* Intel L1OM */ @@ -1977,6 +2001,8 @@ enum bfd_architecture #define bfd_mach_v850 1 #define bfd_mach_v850e 'E' #define bfd_mach_v850e1 '1' +#define bfd_mach_v850e2 0x4532 +#define bfd_mach_v850e2v3 0x45325633 bfd_arch_arc, /* ARC Cores */ #define bfd_mach_arc_5 5 #define bfd_mach_arc_6 6 @@ -2037,6 +2063,13 @@ enum bfd_architecture #define bfd_mach_avr5 5 #define bfd_mach_avr51 51 #define bfd_mach_avr6 6 +#define bfd_mach_avrxmega1 101 +#define bfd_mach_avrxmega2 102 +#define bfd_mach_avrxmega3 103 +#define bfd_mach_avrxmega4 104 +#define bfd_mach_avrxmega5 105 +#define bfd_mach_avrxmega6 106 +#define bfd_mach_avrxmega7 107 bfd_arch_bfin, /* ADI Blackfin */ #define bfd_mach_bfin 1 bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ @@ -3120,6 +3153,12 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_TLS_TPOFF32, BFD_RELOC_ARM_TLS_IE32, BFD_RELOC_ARM_TLS_LE32, + BFD_RELOC_ARM_TLS_GOTDESC, + BFD_RELOC_ARM_TLS_CALL, + BFD_RELOC_ARM_THM_TLS_CALL, + BFD_RELOC_ARM_TLS_DESCSEQ, + BFD_RELOC_ARM_THM_TLS_DESCSEQ, + BFD_RELOC_ARM_TLS_DESC, /* ARM group relocations. */ BFD_RELOC_ARM_ALU_PC_G0_NC, @@ -3154,6 +3193,9 @@ pc-relative or some form of GOT-indirect relocation. */ /* Annotation of BX instructions. */ BFD_RELOC_ARM_V4BX, +/* ARM support for STT_GNU_IFUNC. */ + BFD_RELOC_ARM_IRELATIVE, + /* These relocs are only used within the ARM assembler. They are not (at present) written to any object files. */ BFD_RELOC_ARM_IMMEDIATE, @@ -3164,6 +3206,7 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_T32_ADD_PC12, BFD_RELOC_ARM_SHIFT_IMM, BFD_RELOC_ARM_SMC, + BFD_RELOC_ARM_HVC, BFD_RELOC_ARM_SWI, BFD_RELOC_ARM_MULTI, BFD_RELOC_ARM_CP_OFF_IMM, @@ -3605,6 +3648,72 @@ bits placed non-contiguously in the instruction. */ instructions. */ BFD_RELOC_V850_LO16_SPLIT_OFFSET, +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_PCREL, + +/* This is a 17-bit reloc. */ + BFD_RELOC_V850_17_PCREL, + +/* This is a 23-bit reloc. */ + BFD_RELOC_V850_23, + +/* This is a 32-bit reloc. */ + BFD_RELOC_V850_32_PCREL, + +/* This is a 32-bit reloc. */ + BFD_RELOC_V850_32_ABS, + +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_SPLIT_OFFSET, + +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_S1, + +/* Low 16 bits. 16 bit shifted by 1. */ + BFD_RELOC_V850_LO16_S1, + +/* This is a 16 bit offset from the call table base pointer. */ + BFD_RELOC_V850_CALLT_15_16_OFFSET, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOTPCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_16_GOT, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOT, + +/* DSO relocations. */ + BFD_RELOC_V850_22_PLT_PCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_32_PLT_PCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_COPY, + +/* DSO relocations. */ + BFD_RELOC_V850_GLOB_DAT, + +/* DSO relocations. */ + BFD_RELOC_V850_JMP_SLOT, + +/* DSO relocations. */ + BFD_RELOC_V850_RELATIVE, + +/* DSO relocations. */ + BFD_RELOC_V850_16_GOTOFF, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOTOFF, + +/* start code. */ + BFD_RELOC_V850_CODE, + +/* start data in text. */ + BFD_RELOC_V850_DATA, + /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_32_PCREL, @@ -3665,6 +3774,10 @@ the opcode. */ BFD_RELOC_C6000_DSBT_INDEX, BFD_RELOC_C6000_PREL31, BFD_RELOC_C6000_COPY, + BFD_RELOC_C6000_JUMP_SLOT, + BFD_RELOC_C6000_EHTYPE, + BFD_RELOC_C6000_PCR_H16, + BFD_RELOC_C6000_PCR_L16, BFD_RELOC_C6000_ALIGN, BFD_RELOC_C6000_FPHEAD, BFD_RELOC_C6000_NOCMP, @@ -3898,9 +4011,12 @@ instructions */ BFD_RELOC_RX_GPRELL, BFD_RELOC_RX_SYM, BFD_RELOC_RX_OP_SUBTRACT, + BFD_RELOC_RX_OP_NEG, BFD_RELOC_RX_ABS8, BFD_RELOC_RX_ABS16, + BFD_RELOC_RX_ABS16_REV, BFD_RELOC_RX_ABS32, + BFD_RELOC_RX_ABS32_REV, BFD_RELOC_RX_ABS16U, BFD_RELOC_RX_ABS16UW, BFD_RELOC_RX_ABS16UL, @@ -4988,6 +5104,21 @@ struct bfd will be consistent from run to run. */ #define BFD_DETERMINISTIC_OUTPUT 0x4000 + /* Compress sections in this BFD. */ +#define BFD_COMPRESS 0x8000 + + /* Decompress sections in this BFD. */ +#define BFD_DECOMPRESS 0x10000 + + /* Flags bits to be saved in bfd_preserve_save. */ +#define BFD_FLAGS_SAVED \ + (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) + + /* Flags bits which are for BFD use only. */ +#define BFD_FLAGS_FOR_BFD_USE_MASK \ + (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ + | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) + /* Currently my_archive is tested before adding origin to anything. I believe that this can become always an add of origin, with origin set to 0 for non archive files. */ @@ -5344,6 +5475,8 @@ const char *bfd_core_file_failing_command (bfd *abfd); int bfd_core_file_failing_signal (bfd *abfd); +int bfd_core_file_pid (bfd *abfd); + bfd_boolean core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); @@ -5540,11 +5673,13 @@ typedef struct bfd_target #define BFD_JUMP_TABLE_CORE(NAME) \ NAME##_core_file_failing_command, \ NAME##_core_file_failing_signal, \ - NAME##_core_file_matches_executable_p + NAME##_core_file_matches_executable_p, \ + NAME##_core_file_pid char * (*_core_file_failing_command) (bfd *); int (*_core_file_failing_signal) (bfd *); bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *); + int (*_core_file_pid) (bfd *); /* Archive entry points. */ #define BFD_JUMP_TABLE_ARCHIVE(NAME) \ @@ -5815,8 +5950,21 @@ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); /* Extracted from compress.c. */ -bfd_boolean bfd_uncompress_section_contents - (bfd_byte **buffer, bfd_size_type *size); +bfd_boolean bfd_compress_section_contents + (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer, + bfd_size_type uncompressed_size); + +bfd_boolean bfd_get_full_section_contents + (bfd *abfd, asection *section, bfd_byte **ptr); + +bfd_boolean bfd_is_section_compressed + (bfd *abfd, asection *section); + +bfd_boolean bfd_init_section_decompress_status + (bfd *abfd, asection *section); + +bfd_boolean bfd_init_section_compress_status + (bfd *abfd, asection *section); #ifdef __cplusplus } diff --git a/contrib/gdb-7/bfd/bfd.c b/contrib/gdb-7/bfd/bfd.c index 771989b758..77582ec82f 100644 --- a/contrib/gdb-7/bfd/bfd.c +++ b/contrib/gdb-7/bfd/bfd.c @@ -1,6 +1,6 @@ /* Generic BFD library interface and support routines. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -151,6 +151,21 @@ CODE_FRAGMENT . will be consistent from run to run. *} .#define BFD_DETERMINISTIC_OUTPUT 0x4000 . +. {* Compress sections in this BFD. *} +.#define BFD_COMPRESS 0x8000 +. +. {* Decompress sections in this BFD. *} +.#define BFD_DECOMPRESS 0x10000 +. +. {* Flags bits to be saved in bfd_preserve_save. *} +.#define BFD_FLAGS_SAVED \ +. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) +. +. {* Flags bits which are for BFD use only. *} +.#define BFD_FLAGS_FOR_BFD_USE_MASK \ +. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ +. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) +. . {* Currently my_archive is tested before adding origin to . anything. I believe that this can become always an add of . origin, with origin set to 0 for non archive files. *} @@ -508,10 +523,12 @@ DESCRIPTION void bfd_perror (const char *message) { + fflush (stdout); if (message == NULL || *message == '\0') fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ())); else fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ())); + fflush (stderr); } /* @@ -708,6 +725,7 @@ _bfd_default_error_handler (const char *fmt, ...) va_end (ap); putc ('\n', stderr); + fflush (stderr); } /* This is a function pointer to the routine which should handle BFD @@ -1628,7 +1646,7 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve) abfd->tdata.any = NULL; abfd->arch_info = &bfd_default_arch_struct; - abfd->flags &= BFD_IN_MEMORY; + abfd->flags &= BFD_FLAGS_SAVED; abfd->sections = NULL; abfd->section_last = NULL; abfd->section_count = 0; diff --git a/contrib/gdb-7/bfd/compress.c b/contrib/gdb-7/bfd/compress.c index fe1b0fd3b3..669033c5ec 100644 --- a/contrib/gdb-7/bfd/compress.c +++ b/contrib/gdb-7/bfd/compress.c @@ -27,49 +27,301 @@ #include #endif +#ifdef HAVE_ZLIB_H +static bfd_boolean +decompress_contents (bfd_byte *compressed_buffer, + bfd_size_type compressed_size, + bfd_byte *uncompressed_buffer, + bfd_size_type uncompressed_size) +{ + z_stream strm; + int rc; + + /* It is possible the section consists of several compressed + buffers concatenated together, so we uncompress in a loop. */ + strm.zalloc = NULL; + strm.zfree = NULL; + strm.opaque = NULL; + strm.avail_in = compressed_size - 12; + strm.next_in = (Bytef*) compressed_buffer + 12; + strm.avail_out = uncompressed_size; + + rc = inflateInit (&strm); + while (strm.avail_in > 0) + { + if (rc != Z_OK) + return FALSE; + strm.next_out = ((Bytef*) uncompressed_buffer + + (uncompressed_size - strm.avail_out)); + rc = inflate (&strm, Z_FINISH); + if (rc != Z_STREAM_END) + return FALSE; + rc = inflateReset (&strm); + } + rc = inflateEnd (&strm); + return rc == Z_OK && strm.avail_out == 0; +} +#endif + /* FUNCTION - bfd_uncompress_section_contents + bfd_compress_section_contents SYNOPSIS - bfd_boolean bfd_uncompress_section_contents - (bfd_byte **buffer, bfd_size_type *size); + bfd_boolean bfd_compress_section_contents + (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer, + bfd_size_type uncompressed_size); DESCRIPTION - Uncompresses a section that was compressed using zlib, in place. At - the call to this function, *@var{buffer} and *@var{size} should point - to the section contents to be uncompressed. At the end of the - function, *@var{buffer} and *@var{size} will point to the uncompressed - contents. This function assumes *BUFFER was allocated using - bfd_malloc() or equivalent. If the section is not a valid compressed - section, or zlib is not installed on this machine, the input is - unmodified. - - Returns @code{FALSE} if unable to uncompress successfully; in that case - the input is unmodified. Otherwise, returns @code{TRUE}. + Compress data of the size specified in @var{uncompressed_size} + and pointed to by @var{uncompressed_buffer} using zlib and store + as the contents field. This function assumes the contents + field was allocated using bfd_malloc() or equivalent. If zlib + is not installed on this machine, the input is unmodified. + + Return @code{TRUE} if the full section contents is compressed + successfully. */ bfd_boolean -bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED, - bfd_size_type *size ATTRIBUTE_UNUSED) +bfd_compress_section_contents (bfd *abfd ATTRIBUTE_UNUSED, + sec_ptr sec ATTRIBUTE_UNUSED, + bfd_byte *uncompressed_buffer ATTRIBUTE_UNUSED, + bfd_size_type uncompressed_size ATTRIBUTE_UNUSED) { #ifndef HAVE_ZLIB_H + bfd_set_error (bfd_error_invalid_operation); return FALSE; #else - bfd_size_type compressed_size = *size; - bfd_byte *compressed_buffer = *buffer; + uLong compressed_size; + bfd_byte *compressed_buffer; + + compressed_size = compressBound (uncompressed_size) + 12; + compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size); + + if (compressed_buffer == NULL) + return FALSE; + + if (compress ((Bytef*) compressed_buffer + 12, + &compressed_size, + (const Bytef*) uncompressed_buffer, + uncompressed_size) != Z_OK) + { + free (compressed_buffer); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* Write the zlib header. In this case, it should be "ZLIB" followed + by the uncompressed section size, 8 bytes in big-endian order. */ + memcpy (compressed_buffer, "ZLIB", 4); + compressed_buffer[11] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[10] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[9] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[8] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[7] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[6] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[5] = uncompressed_size; uncompressed_size >>= 8; + compressed_buffer[4] = uncompressed_size; + compressed_size += 12; + + /* Free the uncompressed contents if we compress in place. */ + if (uncompressed_buffer == sec->contents) + free (uncompressed_buffer); + + sec->contents = compressed_buffer; + sec->size = compressed_size; + sec->compress_status = COMPRESS_SECTION_DONE; + + return TRUE; +#endif /* HAVE_ZLIB_H */ +} + +/* +FUNCTION + bfd_get_full_section_contents + +SYNOPSIS + bfd_boolean bfd_get_full_section_contents + (bfd *abfd, asection *section, bfd_byte **ptr); + +DESCRIPTION + Read all data from @var{section} in BFD @var{abfd}, decompress + if needed, and store in @var{*ptr}. If @var{*ptr} is NULL, + return @var{*ptr} with memory malloc'd by this function. + + Return @code{TRUE} if the full section contents is retrieved + successfully. +*/ + +bfd_boolean +bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) +{ + bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size; + bfd_byte *p = *ptr; +#ifdef HAVE_ZLIB_H + bfd_boolean ret; + bfd_size_type compressed_size; bfd_size_type uncompressed_size; + bfd_size_type rawsize; + bfd_byte *compressed_buffer; bfd_byte *uncompressed_buffer; - z_stream strm; - int rc; - bfd_size_type header_size = 12; +#endif + + if (sz == 0) + return TRUE; + + switch (sec->compress_status) + { + case COMPRESS_SECTION_NONE: + if (p == NULL) + { + p = (bfd_byte *) bfd_malloc (sz); + if (p == NULL) + return FALSE; + } + if (!bfd_get_section_contents (abfd, sec, p, 0, sz)) + { + if (*ptr != p) + free (p); + return FALSE; + } + *ptr = p; + return TRUE; + + case DECOMPRESS_SECTION_SIZED: +#ifndef HAVE_ZLIB_H + bfd_set_error (bfd_error_invalid_operation); + return FALSE; +#else + /* Read in the full compressed section contents. */ + uncompressed_size = sec->size; + compressed_size = sec->compressed_size; + compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size); + if (compressed_buffer == NULL) + return FALSE; + rawsize = sec->rawsize; + /* Clear rawsize, set size to compressed size and set compress_status + to COMPRESS_SECTION_NONE. If the compressed size is bigger than + the uncompressed size, bfd_get_section_contents will fail. */ + sec->rawsize = 0; + sec->size = compressed_size; + sec->compress_status = COMPRESS_SECTION_NONE; + ret = bfd_get_section_contents (abfd, sec, compressed_buffer, + 0, compressed_size); + /* Restore rawsize and size. */ + sec->rawsize = rawsize; + sec->size = uncompressed_size; + sec->compress_status = DECOMPRESS_SECTION_SIZED; + if (!ret) + goto fail_compressed; + + uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); + if (uncompressed_buffer == NULL) + goto fail_compressed; + + if (!decompress_contents (compressed_buffer, compressed_size, + uncompressed_buffer, uncompressed_size)) + { + bfd_set_error (bfd_error_bad_value); + free (uncompressed_buffer); + fail_compressed: + free (compressed_buffer); + return FALSE; + } + + free (compressed_buffer); + sec->contents = uncompressed_buffer; + sec->compress_status = COMPRESS_SECTION_DONE; + /* Fall thru */ +#endif + + case COMPRESS_SECTION_DONE: + if (p == NULL) + { + p = (bfd_byte *) bfd_malloc (sz); + if (p == NULL) + return FALSE; + *ptr = p; + } + memcpy (p, sec->contents, sz); + return TRUE; + + default: + abort (); + } +} + +/* +FUNCTION + bfd_is_section_compressed + +SYNOPSIS + bfd_boolean bfd_is_section_compressed + (bfd *abfd, asection *section); + +DESCRIPTION + Return @code{TRUE} if @var{section} is compressed. +*/ + +bfd_boolean +bfd_is_section_compressed (bfd *abfd, sec_ptr sec) +{ + bfd_byte compressed_buffer [12]; /* Read the zlib header. In this case, it should be "ZLIB" followed by the uncompressed section size, 8 bytes in big-endian order. */ - if (compressed_size < header_size - || ! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB")) - return FALSE; + return (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12) + && CONST_STRNEQ ((char*) compressed_buffer, "ZLIB")); +} + +/* +FUNCTION + bfd_init_section_decompress_status + +SYNOPSIS + bfd_boolean bfd_init_section_decompress_status + (bfd *abfd, asection *section); + +DESCRIPTION + Record compressed section size, update section size with + decompressed size and set compress_status to + DECOMPRESS_SECTION_SIZED. + + Return @code{FALSE} if the section is not a valid compressed + section or zlib is not installed on this machine. Otherwise, + return @code{TRUE}. +*/ + +bfd_boolean +bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED, + sec_ptr sec ATTRIBUTE_UNUSED) +{ +#ifndef HAVE_ZLIB_H + bfd_set_error (bfd_error_invalid_operation); + return FALSE; +#else + bfd_byte compressed_buffer [12]; + bfd_size_type uncompressed_size; + + if (sec->rawsize != 0 + || sec->contents != NULL + || sec->compress_status != COMPRESS_SECTION_NONE + || !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)) + { + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } + + /* Read the zlib header. In this case, it should be "ZLIB" followed + by the uncompressed section size, 8 bytes in big-endian order. */ + if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB")) + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } + uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8; uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8; uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8; @@ -79,42 +331,66 @@ bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED, uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8; uncompressed_size += compressed_buffer[11]; - /* It is possible the section consists of several compressed - buffers concatenated together, so we uncompress in a loop. */ - strm.zalloc = NULL; - strm.zfree = NULL; - strm.opaque = NULL; - strm.avail_in = compressed_size - header_size; - strm.next_in = (Bytef*) compressed_buffer + header_size; - strm.avail_out = uncompressed_size; - uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); - if (! uncompressed_buffer) - return FALSE; + sec->compressed_size = sec->size; + sec->size = uncompressed_size; + sec->compress_status = DECOMPRESS_SECTION_SIZED; - rc = inflateInit (&strm); - while (strm.avail_in > 0) + return TRUE; +#endif +} + +/* +FUNCTION + bfd_init_section_compress_status + +SYNOPSIS + bfd_boolean bfd_init_section_compress_status + (bfd *abfd, asection *section); + +DESCRIPTION + If open for read, compress section, update section size with + compressed size and set compress_status to COMPRESS_SECTION_DONE. + + Return @code{FALSE} if the section is not a valid compressed + section or zlib is not installed on this machine. Otherwise, + return @code{TRUE}. +*/ + +bfd_boolean +bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED, + sec_ptr sec ATTRIBUTE_UNUSED) +{ +#ifndef HAVE_ZLIB_H + bfd_set_error (bfd_error_invalid_operation); + return FALSE; +#else + bfd_size_type uncompressed_size; + bfd_byte *uncompressed_buffer; + bfd_boolean ret; + + /* Error if not opened for read. */ + if (abfd->direction != read_direction + || sec->size == 0 + || sec->rawsize != 0 + || sec->contents != NULL + || sec->compress_status != COMPRESS_SECTION_NONE) { - if (rc != Z_OK) - goto fail; - strm.next_out = ((Bytef*) uncompressed_buffer - + (uncompressed_size - strm.avail_out)); - rc = inflate (&strm, Z_FINISH); - if (rc != Z_STREAM_END) - goto fail; - rc = inflateReset (&strm); + bfd_set_error (bfd_error_invalid_operation); + return FALSE; } - rc = inflateEnd (&strm); - if (rc != Z_OK - || strm.avail_out != 0) - goto fail; - free (compressed_buffer); - *buffer = uncompressed_buffer; - *size = uncompressed_size; - return TRUE; + /* Read in the full section contents and compress it. */ + uncompressed_size = sec->size; + uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); + if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer, + 0, uncompressed_size)) + ret = FALSE; + else + ret = bfd_compress_section_contents (abfd, sec, + uncompressed_buffer, + uncompressed_size); - fail: free (uncompressed_buffer); - return FALSE; -#endif /* HAVE_ZLIB_H */ + return ret; +#endif } diff --git a/contrib/gdb-7/bfd/config.bfd b/contrib/gdb-7/bfd/config.bfd index 1015f3cc44..76d1927147 100644 --- a/contrib/gdb-7/bfd/config.bfd +++ b/contrib/gdb-7/bfd/config.bfd @@ -418,7 +418,7 @@ case "${targ}" in targ_selvecs=bfd_elf32_frv_vec ;; - moxie-*-elf | moxie-*-uclinux) + moxie-*-elf | moxie-*-rtems | moxie-*-uclinux) targ_defvec=bfd_elf32_moxie_vec ;; @@ -551,13 +551,17 @@ case "${targ}" in targ_defvec=i386bsd_vec targ_underscore=yes ;; + i[3-7]86-*-dragonfly*) + targ_defvec=bfd_elf32_i386_vec + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + ;; i[3-7]86-*-freebsdaout* | i[3-7]86-*-freebsd[12].* | \ i[3-7]86-*-freebsd[12]) targ_defvec=i386freebsd_vec targ_selvecs=i386bsd_vec targ_underscore=yes ;; - i[3-7]86-*-freebsd* | i[3-7]86-*-kfreebsd*-gnu | i[3-7]86-*-dragonfly*) + i[3-7]86-*-freebsd* | i[3-7]86-*-kfreebsd*-gnu) targ_defvec=bfd_elf32_i386_freebsd_vec targ_selvecs="bfd_elf32_i386_vec i386pei_vec i386coff_vec" targ64_selvecs="bfd_elf64_x86_64_freebsd_vec bfd_elf64_x86_64_vec x86_64pei_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec" @@ -598,7 +602,7 @@ case "${targ}" in i[3-7]86-*-linux-*) targ_defvec=bfd_elf32_i386_vec targ_selvecs="i386linux_vec i386pei_vec" - targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf32_x86_64_vec bfd_elf64_l1om_vec" ;; #ifdef BFD64 x86_64-*-darwin*) @@ -617,6 +621,11 @@ case "${targ}" in targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec i386coff_vec" want64=true ;; + x86_64-*-dragonfly*) + targ_defvec=bfd_elf64_x86_64_vec + targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec" + want64=true + ;; x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) targ_defvec=bfd_elf64_x86_64_freebsd_vec targ_selvecs="bfd_elf32_i386_freebsd_vec i386coff_vec i386pei_vec x86_64pei_vec bfd_elf32_i386_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec" @@ -629,12 +638,12 @@ case "${targ}" in ;; x86_64-*-linux-*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec i386linux_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec" + targ_selvecs="bfd_elf32_i386_vec bfd_elf32_x86_64_vec i386linux_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec" want64=true ;; x86_64-*-mingw*) targ_defvec=x86_64pe_vec - targ_selvecs="x86_64pe_vec x86_64pei_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + targ_selvecs="x86_64pe_vec x86_64pei_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec i386pe_vec i386pei_vec bfd_elf32_i386_vec" want64=true targ_underscore=no ;; @@ -1015,6 +1024,40 @@ case "${targ}" in targ_selvecs="bfd_elf32_tradlittlemips_vec ecoff_big_vec ecoff_little_vec bfd_elf32_ntradbigmips_vec bfd_elf64_tradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradlittlemips_vec" want64=true ;; +#ifdef BFD64 + mips64*el-*-freebsd* | mips64*el-*-kfreebsd*-gnu) + # FreeBSD vectors + targ_defvec=bfd_elf32_ntradlittlemips_freebsd_vec + targ_selvecs="bfd_elf32_ntradbigmips_freebsd_vec bfd_elf32_tradlittlemips_freebsd_vec bfd_elf32_tradbigmips_freebsd_vec bfd_elf64_tradlittlemips_freebsd_vec bfd_elf64_tradbigmips_freebsd_vec" + # Generic vectors + targ_selvecs="${targ_selvecs} bfd_elf32_ntradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_tradlittlemips_vec bfd_elf32_tradbigmips_vec bfd_elf64_tradlittlemips_vec bfd_elf64_tradbigmips_vec" + want64=true + ;; + mips64*-*-freebsd* | mips64*-*-kfreebsd*-gnu) + # FreeBSD vectors + targ_defvec=bfd_elf32_ntradbigmips_freebsd_vec + targ_selvecs="bfd_elf32_ntradlittlemips_freebsd_vec bfd_elf32_tradbigmips_freebsd_vec bfd_elf32_tradlittlemips_freebsd_vec bfd_elf64_tradbigmips_freebsd_vec bfd_elf64_tradlittlemips_freebsd_vec" + # Generic vectors + targ_selvecs="${targ_selvecs} bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf32_tradbigmips_vec bfd_elf32_tradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec" + want64=true + ;; +#endif + mips*el-*-freebsd* | mips*el-*-kfreebsd*-gnu) + # FreeBSD vectors + targ_defvec=bfd_elf32_tradlittlemips_freebsd_vec + targ_selvecs="bfd_elf32_tradbigmips_freebsd_vec bfd_elf32_ntradlittlemips_freebsd_vec bfd_elf64_tradlittlemips_freebsd_vec bfd_elf32_ntradbigmips_freebsd_vec bfd_elf64_tradbigmips_freebsd_vec" + # Generic vectors + targ_selvecs="${targ_selvecs} bfd_elf32_tradlittlemips_vec bfd_elf32_tradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf64_tradbigmips_vec" + want64=true + ;; + mips*-*-freebsd* | mips*-*-kfreebsd*-gnu) + # FreeBSD vectors + targ_defvec=bfd_elf32_tradbigmips_freebsd_vec + targ_selvecs="bfd_elf32_tradlittlemips_freebsd_vec bfd_elf32_ntradbigmips_freebsd_vec bfd_elf64_tradbigmips_freebsd_vec bfd_elf32_ntradlittlemips_freebsd_vec bfd_elf64_tradlittlemips_freebsd_vec" + # Generic vectors + targ_selvecs="${targ_selvecs} bfd_elf32_tradbigmips_vec bfd_elf32_tradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf64_tradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradlittlemips_vec" + want64=true + ;; #ifdef BFD64 mmix-*-*) targ_defvec=bfd_elf64_mmix_vec @@ -1076,26 +1119,26 @@ case "${targ}" in targ_selvecs="bfd_elf32_pjl_vec bfd_elf32_pj_vec bfd_elf32_i386_vec" ;; - powerpc-*-aix5.[01]) + powerpc-*-aix5.[01] | rs6000-*-aix5.[01]) targ_defvec=rs6000coff_vec targ_selvecs="aix5coff64_vec" want64=true ;; #ifdef BFD64 - powerpc64-*-aix5.[01]) + powerpc64-*-aix5.[01] | rs6000-*-aix5.[01]) targ_defvec=aix5coff64_vec targ_selvecs="rs6000coff_vec" want64=true ;; #endif - powerpc-*-aix[5-9]*) + powerpc-*-aix[5-9]* | rs6000-*-aix[5-9]*) targ_cflags=-DAIX_WEAK_SUPPORT targ_defvec=rs6000coff_vec targ_selvecs="aix5coff64_vec" want64=true ;; #ifdef BFD64 - powerpc64-*-aix[5-9]*) + powerpc64-*-aix[5-9]* | rs6000-*-aix[5-9]*) targ_cflags=-DAIX_WEAK_SUPPORT targ_defvec=aix5coff64_vec targ_selvecs="rs6000coff_vec" @@ -1122,12 +1165,12 @@ case "${targ}" in powerpc64-*-elf* | powerpc-*-elf64* | powerpc64-*-linux* | \ powerpc64-*-*bsd*) targ_defvec=bfd_elf64_powerpc_vec - targ_selvecs="bfd_elf64_powerpcle_vec bfd_elf32_powerpc_vec bfd_elf32_powerpcle_vec rs6000coff_vec rs6000coff64_vec" + targ_selvecs="bfd_elf64_powerpcle_vec bfd_elf32_powerpc_vec bfd_elf32_powerpcle_vec rs6000coff_vec rs6000coff64_vec aix5coff64_vec" want64=true ;; powerpc64le-*-elf* | powerpcle-*-elf64*) targ_defvec=bfd_elf64_powerpcle_vec - targ_selvecs="bfd_elf64_powerpc_vec bfd_elf32_powerpcle_vec bfd_elf32_powerpc_vec rs6000coff_vec rs6000coff64_vec" + targ_selvecs="bfd_elf64_powerpc_vec bfd_elf32_powerpcle_vec bfd_elf32_powerpc_vec rs6000coff_vec rs6000coff64_vec aix5coff64_vec" want64=true ;; #endif @@ -1395,14 +1438,18 @@ case "${targ}" in targ_defvec=bfd_elf32_sparc_vec targ_selvecs=sparcnetbsd_vec ;; - sparc-*-elf* | sparc-*-solaris2.[0-6] | sparc-*-solaris2.[0-6].*) + sparc-*-elf*) targ_defvec=bfd_elf32_sparc_vec targ_selvecs=sunos_big_vec ;; + sparc-*-solaris2.[0-6] | sparc-*-solaris2.[0-6].*) + targ_defvec=bfd_elf32_sparc_sol2_vec + targ_selvecs=sunos_big_vec + ;; #ifdef BFD64 sparc-*-solaris2* | sparcv9-*-solaris2* | sparc64-*-solaris2*) - targ_defvec=bfd_elf32_sparc_vec - targ_selvecs="bfd_elf64_sparc_vec sunos_big_vec" + targ_defvec=bfd_elf32_sparc_sol2_vec + targ_selvecs="bfd_elf64_sparc_sol2_vec sunos_big_vec" want64=true ;; #endif @@ -1428,7 +1475,7 @@ case "${targ}" in targ_selvecs="bfd_elf32_sparc_vec sparclinux_vec sunos_big_vec" want64=true ;; - sparc64-*-elf*) + sparc64-*-elf* | sparc64-*-rtems* ) targ_defvec=bfd_elf64_sparc_vec targ_selvecs=bfd_elf32_sparc_vec want64=true @@ -1437,7 +1484,7 @@ case "${targ}" in sparc*-*-coff*) targ_defvec=sparccoff_vec ;; - sparc*-*-rtems*) + sparc-*-rtems*) targ_defvec=bfd_elf32_sparc_vec targ_selvecs="sunos_big_vec sparccoff_vec" ;; @@ -1458,7 +1505,7 @@ case "${targ}" in ;; #endif - tic6x-*-elf) + tic6x-*-*) targ_defvec=bfd_elf32_tic6x_le_vec targ_selvecs=bfd_elf32_tic6x_be_vec ;; @@ -1468,13 +1515,7 @@ case "${targ}" in targ_underscore=yes ;; - v850-*-*) - targ_defvec=bfd_elf32_v850_vec - ;; - v850e-*-*) - targ_defvec=bfd_elf32_v850_vec - ;; - v850ea-*-*) + v850*-*-*) targ_defvec=bfd_elf32_v850_vec ;; diff --git a/contrib/gdb-7/bfd/corefile.c b/contrib/gdb-7/bfd/corefile.c index 7802a3a3fa..bba0d1ca4f 100644 --- a/contrib/gdb-7/bfd/corefile.c +++ b/contrib/gdb-7/bfd/corefile.c @@ -82,6 +82,31 @@ bfd_core_file_failing_signal (bfd *abfd) return BFD_SEND (abfd, _core_file_failing_signal, (abfd)); } +/* +FUNCTION + bfd_core_file_pid + +SYNOPSIS + int bfd_core_file_pid (bfd *abfd); + +DESCRIPTION + + Returns the PID of the process the core dump the BFD + @var{abfd} is attached to was generated from. +*/ + +int +bfd_core_file_pid (bfd *abfd) +{ + if (abfd->format != bfd_core) + { + bfd_set_error (bfd_error_invalid_operation); + return 0; + } + return BFD_SEND (abfd, _core_file_pid, (abfd)); +} + + /* FUNCTION core_file_matches_executable_p @@ -161,6 +186,6 @@ generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) if (last_slash != NULL) exec = last_slash + 1; - return strcmp (exec, core) == 0; + return filename_cmp (exec, core) == 0; } diff --git a/contrib/gdb-7/bfd/cpu-i386.c b/contrib/gdb-7/bfd/cpu-i386.c index 44cca9da8c..c4f41c50c2 100644 --- a/contrib/gdb-7/bfd/cpu-i386.c +++ b/contrib/gdb-7/bfd/cpu-i386.c @@ -1,6 +1,6 @@ /* BFD support for the Intel 386 architecture. Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005, - 2007, 2009 + 2007, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -24,6 +24,35 @@ #include "bfd.h" #include "libbfd.h" +static const bfd_arch_info_type * +bfd_i386_compatible (const bfd_arch_info_type *a, + const bfd_arch_info_type *b) +{ + const bfd_arch_info_type *compat = bfd_default_compatible (a, b); + + /* Don't allow mixing x64_32 with x86_64. */ + if (compat && a->bits_per_address != b->bits_per_address) + compat = NULL; + + return compat; +} + +static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax = +{ + 64, /* 64 bits in a word */ + 32, /* 32 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_i386, + bfd_mach_x64_32_intel_syntax, + "i386:intel", + "i386:x64-32:intel", + 3, + FALSE, + bfd_i386_compatible, + bfd_default_scan, + 0 +}; + static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax = { 64, /* 64 bits in a word */ @@ -35,9 +64,9 @@ static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax = "i386:x86-64:intel", 3, FALSE, - bfd_default_compatible, + bfd_i386_compatible, bfd_default_scan, - 0 + &bfd_x64_32_arch_intel_syntax, }; static const bfd_arch_info_type bfd_i386_arch_intel_syntax = @@ -51,7 +80,7 @@ static const bfd_arch_info_type bfd_i386_arch_intel_syntax = "i386:intel", 3, TRUE, - bfd_default_compatible, + bfd_i386_compatible, bfd_default_scan, &bfd_x86_64_arch_intel_syntax }; @@ -67,11 +96,27 @@ static const bfd_arch_info_type i8086_arch = "i8086", 3, FALSE, - bfd_default_compatible, + bfd_i386_compatible, bfd_default_scan, &bfd_i386_arch_intel_syntax }; +static const bfd_arch_info_type bfd_x64_32_arch = +{ + 64, /* 64 bits in a word */ + 32, /* 32 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_i386, + bfd_mach_x64_32, + "i386", + "i386:x64-32", + 3, + FALSE, + bfd_i386_compatible, + bfd_default_scan, + &i8086_arch +}; + static const bfd_arch_info_type bfd_x86_64_arch = { 64, /* 64 bits in a word */ @@ -83,9 +128,9 @@ static const bfd_arch_info_type bfd_x86_64_arch = "i386:x86-64", 3, FALSE, - bfd_default_compatible, + bfd_i386_compatible, bfd_default_scan, - &i8086_arch + &bfd_x64_32_arch }; const bfd_arch_info_type bfd_i386_arch = @@ -99,7 +144,7 @@ const bfd_arch_info_type bfd_i386_arch = "i386", 3, TRUE, - bfd_default_compatible, + bfd_i386_compatible, bfd_default_scan, &bfd_x86_64_arch }; diff --git a/contrib/gdb-7/bfd/dwarf2.c b/contrib/gdb-7/bfd/dwarf2.c index 6983a1c349..38268561fb 100644 --- a/contrib/gdb-7/bfd/dwarf2.c +++ b/contrib/gdb-7/bfd/dwarf2.c @@ -275,6 +275,60 @@ struct attr_abbrev enum dwarf_form form; }; +/* Map of uncompressed DWARF debug section name to compressed one. It + is terminated by NULL uncompressed_name. */ + +struct dwarf_debug_section dwarf_debug_sections[] = +{ + { ".debug_abbrev", ".zdebug_abbrev" }, + { ".debug_aranges", ".zdebug_aranges" }, + { ".debug_frame", ".zdebug_frame" }, + { ".debug_info", ".zdebug_info" }, + { ".debug_line", ".zdebug_line" }, + { ".debug_loc", ".zdebug_loc" }, + { ".debug_macinfo", ".zdebug_macinfo" }, + { ".debug_pubnames", ".zdebug_pubnames" }, + { ".debug_pubtypes", ".zdebug_pubtypes" }, + { ".debug_ranges", ".zdebug_ranges" }, + { ".debug_static_func", ".zdebug_static_func" }, + { ".debug_static_vars", ".zdebug_static_vars" }, + { ".debug_str", ".zdebug_str", }, + { ".debug_types", ".zdebug_types" }, + /* GNU DWARF 1 extensions */ + { ".debug_sfnames", ".zdebug_sfnames" }, + { ".debug_srcinfo", ".zebug_srcinfo" }, + /* SGI/MIPS DWARF 2 extensions */ + { ".debug_funcnames", ".zdebug_funcnames" }, + { ".debug_typenames", ".zdebug_typenames" }, + { ".debug_varnames", ".zdebug_varnames" }, + { ".debug_weaknames", ".zdebug_weaknames" }, + { NULL, NULL }, +}; + +enum dwarf_debug_section_enum +{ + debug_abbrev = 0, + debug_aranges, + debug_frame, + debug_info, + debug_line, + debug_loc, + debug_macinfo, + debug_pubnames, + debug_pubtypes, + debug_ranges, + debug_static_func, + debug_static_vars, + debug_str, + debug_types, + debug_sfnames, + debug_srcinfo, + debug_funcnames, + debug_typenames, + debug_varnames, + debug_weaknames +}; + #ifndef ABBREV_HASH_SIZE #define ABBREV_HASH_SIZE 121 #endif @@ -405,54 +459,6 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key) return entry ? entry->head : NULL; } -/* Read a section, uncompress it if necessary, and relocate it. */ - -static bfd_boolean -read_and_uncompress_section (bfd * abfd, - asection * msec, - bfd_boolean section_is_compressed, - asymbol ** syms, - bfd_byte ** section_buffer, - bfd_size_type * section_size) -{ - /* Get the unrelocated contents of the section. */ - *section_buffer = (bfd_byte *) bfd_malloc (*section_size); - if (! *section_buffer) - return FALSE; - if (! bfd_get_section_contents (abfd, msec, *section_buffer, - 0, *section_size)) - return FALSE; - - if (section_is_compressed) - { - if (! bfd_uncompress_section_contents (section_buffer, section_size)) - { - (*_bfd_error_handler) (_("Dwarf Error: unable to decompress %s section."), - bfd_get_section_name (abfd, msec)); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } - } - - if (syms) - { - /* We want to relocate the data we've already read (and - decompressed), so we store a pointer to the data in - the bfd_section, and tell it that the contents are - already in memory. */ - BFD_ASSERT (msec->contents == NULL && (msec->flags & SEC_IN_MEMORY) == 0); - msec->contents = *section_buffer; - msec->flags |= SEC_IN_MEMORY; - msec->size = *section_size; - *section_buffer - = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); - if (! *section_buffer) - return FALSE; - } - - return TRUE; -} - /* Read a section into its appropriate place in the dwarf2_debug struct (indicated by SECTION_BUFFER and SECTION_SIZE). If SYMS is not NULL, use bfd_simple_get_relocated_section_contents to read the @@ -461,24 +467,23 @@ read_and_uncompress_section (bfd * abfd, static bfd_boolean read_section (bfd * abfd, - const char * section_name, - const char * compressed_section_name, + enum dwarf_debug_section_enum sec, asymbol ** syms, bfd_uint64_t offset, bfd_byte ** section_buffer, bfd_size_type * section_size) { asection *msec; - bfd_boolean section_is_compressed = FALSE; + const char *section_name = dwarf_debug_sections[sec].uncompressed_name; /* read_section is a noop if the section has already been read. */ if (!*section_buffer) { msec = bfd_get_section_by_name (abfd, section_name); - if (! msec && compressed_section_name) + if (! msec) { - msec = bfd_get_section_by_name (abfd, compressed_section_name); - section_is_compressed = TRUE; + section_name = dwarf_debug_sections[sec].compressed_name; + msec = bfd_get_section_by_name (abfd, section_name); } if (! msec) { @@ -488,10 +493,22 @@ read_section (bfd * abfd, } *section_size = msec->rawsize ? msec->rawsize : msec->size; - - if (! read_and_uncompress_section (abfd, msec, section_is_compressed, - syms, section_buffer, section_size)) - return FALSE; + if (syms) + { + *section_buffer + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); + if (! *section_buffer) + return FALSE; + } + else + { + *section_buffer = (bfd_byte *) bfd_malloc (*section_size); + if (! *section_buffer) + return FALSE; + if (! bfd_get_section_contents (abfd, msec, *section_buffer, + 0, *section_size)) + return FALSE; + } } /* It is possible to get a bad value for the offset into the section @@ -587,8 +604,7 @@ read_indirect_string (struct comp_unit * unit, *bytes_read_ptr = unit->offset_size; - if (! read_section (unit->abfd, ".debug_str", ".zdebug_str", - stash->syms, offset, + if (! read_section (unit->abfd, debug_str, stash->syms, offset, &stash->dwarf_str_buffer, &stash->dwarf_str_size)) return NULL; @@ -670,8 +686,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) unsigned int abbrev_form, hash_number; bfd_size_type amt; - if (! read_section (abfd, ".debug_abbrev", ".zdebug_abbrev", - stash->syms, offset, + if (! read_section (abfd, debug_abbrev, stash->syms, offset, &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size)) return NULL; @@ -1379,8 +1394,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) unsigned char op_code, extended_op, adj_opcode; bfd_size_type amt; - if (! read_section (abfd, ".debug_line", ".zdebug_line", - stash->syms, unit->line_offset, + if (! read_section (abfd, debug_line, stash->syms, unit->line_offset, &stash->dwarf_line_buffer, &stash->dwarf_line_size)) return NULL; @@ -1795,8 +1809,7 @@ static bfd_boolean read_debug_ranges (struct comp_unit *unit) { struct dwarf2_debug *stash = unit->stash; - return read_section (unit->abfd, ".debug_ranges", ".zdebug_ranges", - stash->syms, 0, + return read_section (unit->abfd, debug_ranges, stash->syms, 0, &stash->dwarf_ranges_buffer, &stash->dwarf_ranges_size); } @@ -2135,7 +2148,7 @@ scan_unit_for_symbols (struct comp_unit *unit) { info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr); if (info_ptr == NULL) - return FALSE; + goto fail; if (func) { @@ -3218,80 +3231,37 @@ find_line (bfd *abfd, { /* Case 1: only one info section. */ total_size = msec->size; - if (! read_section (debug_bfd, ".debug_info", ".zdebug_info", - symbols, 0, + if (! read_section (debug_bfd, debug_info, symbols, 0, &stash->info_ptr_memory, &total_size)) goto done; } else { - int all_uncompressed = 1; + /* Case 2: multiple sections. */ for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec)) - { - total_size += msec->size; - if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0) - all_uncompressed = 0; - } - if (all_uncompressed) - { - /* Case 2: multiple sections, but none is compressed. */ - stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size); - if (stash->info_ptr_memory == NULL) - goto done; + total_size += msec->size; - total_size = 0; - for (msec = find_debug_info (debug_bfd, NULL); - msec; - msec = find_debug_info (debug_bfd, msec)) - { - bfd_size_type size; + stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size); + if (stash->info_ptr_memory == NULL) + goto done; - size = msec->size; - if (size == 0) - continue; + total_size = 0; + for (msec = find_debug_info (debug_bfd, NULL); + msec; + msec = find_debug_info (debug_bfd, msec)) + { + bfd_size_type size; - if (!(bfd_simple_get_relocated_section_contents - (debug_bfd, msec, stash->info_ptr_memory + total_size, - symbols))) - goto done; + size = msec->size; + if (size == 0) + continue; - total_size += size; - } - } - else - { - /* Case 3: multiple sections, some or all compressed. */ - stash->info_ptr_memory = NULL; - total_size = 0; - for (msec = find_debug_info (debug_bfd, NULL); - msec; - msec = find_debug_info (debug_bfd, msec)) - { - bfd_size_type size = msec->size; - bfd_byte *buffer, *tmp; - bfd_boolean is_compressed = - strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0; - - if (size == 0) - continue; - - if (! read_and_uncompress_section (debug_bfd, msec, - is_compressed, symbols, - &buffer, &size)) - goto done; - - tmp = (bfd_byte *) bfd_realloc (stash->info_ptr_memory, - total_size + size); - if (tmp == NULL) - { - free (buffer); - goto done; - } - stash->info_ptr_memory = tmp; - memcpy (stash->info_ptr_memory + total_size, buffer, size); - free (buffer); - total_size += size; - } + if (!(bfd_simple_get_relocated_section_contents + (debug_bfd, msec, stash->info_ptr_memory + total_size, + symbols))) + goto done; + + total_size += size; } } diff --git a/contrib/gdb-7/bfd/elf-attrs.c b/contrib/gdb-7/bfd/elf-attrs.c index b9d3bf2fe4..569e846cc5 100644 --- a/contrib/gdb-7/bfd/elf-attrs.c +++ b/contrib/gdb-7/bfd/elf-attrs.c @@ -586,3 +586,114 @@ _bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd) return TRUE; } + +/* Merge an unknown processor-specific attribute TAG, within the range + of known attributes, from IBFD into OBFD; return TRUE if the link + is OK, FALSE if it must fail. */ + +bfd_boolean +_bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag) +{ + obj_attribute *in_attr; + obj_attribute *out_attr; + bfd *err_bfd = NULL; + bfd_boolean result = TRUE; + + in_attr = elf_known_obj_attributes_proc (ibfd); + out_attr = elf_known_obj_attributes_proc (obfd); + + if (out_attr[tag].i != 0 || out_attr[tag].s != NULL) + err_bfd = obfd; + else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL) + err_bfd = ibfd; + + if (err_bfd != NULL) + result + = get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag); + + /* Only pass on attributes that match in both inputs. */ + if (in_attr[tag].i != out_attr[tag].i + || (in_attr[tag].s == NULL) != (out_attr[tag].s == NULL) + || (in_attr[tag].s != NULL && out_attr[tag].s != NULL + && strcmp (in_attr[tag].s, out_attr[tag].s) != 0)) + { + out_attr[tag].i = 0; + out_attr[tag].s = NULL; + } + + return result; +} + +/* Merge the lists of unknown processor-specific attributes, outside + the known range, from IBFD into OBFD; return TRUE if the link is + OK, FALSE if it must fail. */ + +bfd_boolean +_bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd) +{ + obj_attribute_list *in_list; + obj_attribute_list *out_list; + obj_attribute_list **out_listp; + bfd_boolean result = TRUE; + + in_list = elf_other_obj_attributes_proc (ibfd); + out_listp = &elf_other_obj_attributes_proc (obfd); + out_list = *out_listp; + + for (; in_list || out_list; ) + { + bfd *err_bfd = NULL; + int err_tag = 0; + + /* The tags for each list are in numerical order. */ + /* If the tags are equal, then merge. */ + if (out_list && (!in_list || in_list->tag > out_list->tag)) + { + /* This attribute only exists in obfd. We can't merge, and we don't + know what the tag means, so delete it. */ + err_bfd = obfd; + err_tag = out_list->tag; + *out_listp = out_list->next; + out_list = *out_listp; + } + else if (in_list && (!out_list || in_list->tag < out_list->tag)) + { + /* This attribute only exists in ibfd. We can't merge, and we don't + know what the tag means, so ignore it. */ + err_bfd = ibfd; + err_tag = in_list->tag; + in_list = in_list->next; + } + else /* The tags are equal. */ + { + /* As present, all attributes in the list are unknown, and + therefore can't be merged meaningfully. */ + err_bfd = obfd; + err_tag = out_list->tag; + + /* Only pass on attributes that match in both inputs. */ + if (in_list->attr.i != out_list->attr.i + || (in_list->attr.s == NULL) != (out_list->attr.s == NULL) + || (in_list->attr.s && out_list->attr.s + && strcmp (in_list->attr.s, out_list->attr.s) != 0)) + { + /* No match. Delete the attribute. */ + *out_listp = out_list->next; + out_list = *out_listp; + } + else + { + /* Matched. Keep the attribute and move to the next. */ + out_list = out_list->next; + in_list = in_list->next; + } + } + + if (err_bfd) + result = result + && get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, + err_tag); + } + + return result; +} diff --git a/contrib/gdb-7/bfd/elf-bfd.h b/contrib/gdb-7/bfd/elf-bfd.h index 754e7335b6..21ec38f2c9 100644 --- a/contrib/gdb-7/bfd/elf-bfd.h +++ b/contrib/gdb-7/bfd/elf-bfd.h @@ -153,6 +153,9 @@ struct elf_link_hash_entry /* Symbol st_other value, symbol visibility. */ unsigned int other : 8; + /* The symbol's st_target_internal value (see Elf_Internal_Sym). */ + unsigned int target_internal : 8; + /* Symbol is referenced by a non-shared object (other than the object in which it is defined). */ unsigned int ref_regular : 1; @@ -689,6 +692,10 @@ struct elf_backend_data /* The architecture for this backend. */ enum bfd_architecture arch; + /* An identifier used to distinguish different target specific + extensions to elf_obj_tdata and elf_link_hash_table structures. */ + enum elf_target_id target_id; + /* The ELF machine code (EM_xxxx) for this backend. */ int elf_machine_code; @@ -1252,6 +1259,13 @@ struct elf_backend_data actual tag number to place in the input position. */ int (*obj_attrs_order) (int); + /* Handle merging unknown attributes; either warn and return TRUE, + or give an error and return FALSE. */ + bfd_boolean (*obj_attrs_handle_unknown) (bfd *, int); + + /* This is non-zero if static TLS segments require a special alignment. */ + unsigned static_tls_alignment; + /* This is TRUE if the linker should act like collect and gather global constructors and destructors by name. This is TRUE for MIPS ELF because the Irix 5 tools can not handle the .init @@ -1315,6 +1329,23 @@ struct elf_backend_data unsigned default_execstack : 1; }; +/* Information about reloc sections associated with a bfd_elf_section_data + structure. */ +struct bfd_elf_section_reloc_data +{ + /* The ELF header for the reloc section associated with this + section, if any. */ + Elf_Internal_Shdr *hdr; + /* The number of relocations currently assigned to HDR. */ + unsigned int count; + /* The ELF section number of the reloc section. Only used for an + output file. */ + int idx; + /* Used by the backend linker to store the symbol hash table entries + associated with relocs against global symbols. */ + struct elf_link_hash_entry **hashes; +}; + /* Information stored for each BFD section in an ELF file. This structure is allocated by elf_new_section_hook. */ @@ -1323,31 +1354,13 @@ struct bfd_elf_section_data /* The ELF header for this section. */ Elf_Internal_Shdr this_hdr; - /* The ELF header for the reloc section associated with this - section, if any. */ - Elf_Internal_Shdr rel_hdr; - - /* If there is a second reloc section associated with this section, - as can happen on Irix 6, this field points to the header. */ - Elf_Internal_Shdr *rel_hdr2; - - /* The number of relocations currently assigned to REL_HDR. */ - unsigned int rel_count; - - /* The number of relocations currently assigned to REL_HDR2. */ - unsigned int rel_count2; + /* Information about the REL and RELA reloc sections associated + with this section, if any. */ + struct bfd_elf_section_reloc_data rel, rela; /* The ELF section number of this section. */ int this_idx; - /* The ELF section number of the reloc section indicated by - REL_HDR if any. Only used for an output file. */ - int rel_idx; - - /* The ELF section number of the reloc section indicated by - REL_HDR2 if any. Only used for an output file. */ - int rel_idx2; - /* Used by the backend linker when generating a shared library to record the dynamic symbol index for a section symbol corresponding to this section. A value of 0 means that there is @@ -1357,10 +1370,6 @@ struct bfd_elf_section_data /* A pointer to the linked-to section for SHF_LINK_ORDER. */ asection *linked_to; - /* Used by the backend linker to store the symbol hash table entries - associated with relocs against global symbols. */ - struct elf_link_hash_entry **rel_hashes; - /* A pointer to the swapped relocs. If the section uses REL relocs, rather than RELA, all the r_addend fields will be zero. This pointer may be NULL. It is used by the backend linker. */ @@ -1739,7 +1748,7 @@ extern bfd_reloc_status_type bfd_elf_generic_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); extern bfd_boolean bfd_elf_allocate_object (bfd *, size_t, enum elf_target_id); -extern bfd_boolean bfd_elf_make_generic_object +extern bfd_boolean bfd_elf_make_object (bfd *); extern bfd_boolean bfd_elf_mkcorefile (bfd *); @@ -1848,7 +1857,7 @@ extern int _bfd_elf_sizeof_headers extern bfd_boolean _bfd_elf_new_section_hook (bfd *, asection *); extern bfd_boolean _bfd_elf_init_reloc_shdr - (bfd *, Elf_Internal_Shdr *, asection *, bfd_boolean); + (bfd *, struct bfd_elf_section_reloc_data *, asection *, bfd_boolean); extern const struct bfd_elf_special_section *_bfd_elf_get_special_section (const char *, const struct bfd_elf_special_section *, unsigned int); extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr @@ -1989,6 +1998,8 @@ extern int bfd_elf32_core_file_failing_signal (bfd *); extern bfd_boolean bfd_elf32_core_file_matches_executable_p (bfd *, bfd *); +extern int bfd_elf32_core_file_pid + (bfd *); extern bfd_boolean bfd_elf32_swap_symbol_in (bfd *, const void *, const void *, Elf_Internal_Sym *); @@ -2033,6 +2044,8 @@ extern int bfd_elf64_core_file_failing_signal (bfd *); extern bfd_boolean bfd_elf64_core_file_matches_executable_p (bfd *, bfd *); +extern int bfd_elf64_core_file_pid + (bfd *); extern bfd_boolean bfd_elf64_swap_symbol_in (bfd *, const void *, const void *, Elf_Internal_Sym *); @@ -2229,6 +2242,9 @@ extern void _bfd_elf_copy_obj_attributes (bfd *, bfd *); extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int); extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *); extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *); +extern bfd_boolean _bfd_elf_merge_unknown_attribute_low (bfd *, bfd *, int); +extern bfd_boolean _bfd_elf_merge_unknown_attribute_list (bfd *, bfd *); +extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec); /* The linker may needs to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. @@ -2259,6 +2275,14 @@ extern bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *, struct elf_link_hash_entry *, struct elf_dyn_relocs **, unsigned int, unsigned int); +extern void elf_append_rela (bfd *, asection *, Elf_Internal_Rela *); +extern void elf_append_rel (bfd *, asection *, Elf_Internal_Rela *); + +extern bfd_vma elf64_r_info (bfd_vma, bfd_vma); +extern bfd_vma elf64_r_sym (bfd_vma); +extern bfd_vma elf32_r_info (bfd_vma, bfd_vma); +extern bfd_vma elf32_r_sym (bfd_vma); + /* Large common section. */ extern asection _bfd_elf_large_com_section; @@ -2348,6 +2372,9 @@ extern asection _bfd_elf_large_com_section; #define RELOC_AGAINST_DISCARDED_SECTION(info, input_bfd, input_section, \ rel, relend, howto, contents) \ { \ + _bfd_clear_contents (howto, input_bfd, input_section, \ + contents + rel->r_offset); \ + \ if (info->relocatable \ && (input_section->flags & SEC_DEBUGGING)) \ { \ @@ -2355,13 +2382,13 @@ extern asection _bfd_elf_large_com_section; sections may require relocations. */ \ Elf_Internal_Shdr *rel_hdr; \ \ - rel_hdr = &elf_section_data (input_section->output_section)->rel_hdr; \ + rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section); \ \ /* Avoid empty output section. */ \ if (rel_hdr->sh_size > rel_hdr->sh_entsize) \ { \ rel_hdr->sh_size -= rel_hdr->sh_entsize; \ - rel_hdr = &elf_section_data (input_section)->rel_hdr; \ + rel_hdr = _bfd_elf_single_rel_hdr (input_section); \ rel_hdr->sh_size -= rel_hdr->sh_entsize; \ \ memmove (rel, rel + 1, (relend - rel) * sizeof (*rel)); \ @@ -2373,7 +2400,6 @@ extern asection _bfd_elf_large_com_section; } \ } \ \ - _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); \ rel->r_info = 0; \ rel->r_addend = 0; \ continue; \ diff --git a/contrib/gdb-7/bfd/elf-eh-frame.c b/contrib/gdb-7/bfd/elf-eh-frame.c index 8380ef8600..0a22138147 100644 --- a/contrib/gdb-7/bfd/elf-eh-frame.c +++ b/contrib/gdb-7/bfd/elf-eh-frame.c @@ -1572,10 +1572,31 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, break; case DW_EH_PE_datarel: { - asection *got = bfd_get_section_by_name (abfd, ".got"); - - BFD_ASSERT (got != NULL); - address += got->vma; + switch (abfd->arch_info->arch) + { + case bfd_arch_ia64: + BFD_ASSERT (elf_gp (abfd) != 0); + address += elf_gp (abfd); + break; + default: + (*info->callbacks->einfo) + (_("%P: DW_EH_PE_datarel unspecified" + " for this architecture.\n")); + /* Fall thru */ + case bfd_arch_frv: + case bfd_arch_i386: + BFD_ASSERT (htab->hgot != NULL + && ((htab->hgot->root.type + == bfd_link_hash_defined) + || (htab->hgot->root.type + == bfd_link_hash_defweak))); + address + += (htab->hgot->root.u.def.value + + htab->hgot->root.u.def.section->output_offset + + (htab->hgot->root.u.def.section->output_section + ->vma)); + break; + } } break; case DW_EH_PE_pcrel: @@ -1596,6 +1617,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, if (hdr_info) { + /* The address calculation may overflow, giving us a + value greater than 4G on a 32-bit target when + dwarf_vma is 64-bit. */ + if (sizeof (address) > 4 && ptr_size == 4) + address &= 0xffffffff; hdr_info->array[hdr_info->array_count].initial_loc = address; hdr_info->array[hdr_info->array_count++].fde = (sec->output_section->vma diff --git a/contrib/gdb-7/bfd/elf-ifunc.c b/contrib/gdb-7/bfd/elf-ifunc.c index 0de236f8c2..81429b8433 100644 --- a/contrib/gdb-7/bfd/elf-ifunc.c +++ b/contrib/gdb-7/bfd/elf-ifunc.c @@ -187,6 +187,29 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, htab = elf_hash_table (info); + /* Support garbage collection against STT_GNU_IFUNC symbols. */ + if (h->plt.refcount <= 0 && h->got.refcount <= 0) + { + /* When building shared library, we need to handle the case + where it is marked with regular reference, but not non-GOT + reference. It may happen if we didn't see STT_GNU_IFUNC + symbol at the time when checking relocations. */ + if (info->shared + && !h->non_got_ref + && h->ref_regular) + for (p = *head; p != NULL; p = p->next) + if (p->count) + { + h->non_got_ref = 1; + goto keep; + } + + h->got = htab->init_got_offset; + h->plt = htab->init_plt_offset; + *head = NULL; + return TRUE; + } + /* Return and discard space for dynamic relocations against it if it is never referenced in a non-shared object. */ if (!h->ref_regular) @@ -200,6 +223,7 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, return TRUE; } +keep: bed = get_elf_backend_data (info->output_bfd); if (bed->rela_plts_and_copies_p) sizeof_reloc = bed->s->sizeof_rela; @@ -249,10 +273,20 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, *head = NULL; /* Finally, allocate space. */ - for (p = *head; p != NULL; p = p->next) - htab->irelifunc->size += p->count * sizeof_reloc; + p = *head; + if (p != NULL) + { + bfd_size_type count = 0; + do + { + count += p->count; + p = p->next; + } + while (p != NULL); + htab->irelifunc->size += count * sizeof_reloc; + } - /* For STT_GNU_IFUNC symbol, .got.plt has the real function addres + /* For STT_GNU_IFUNC symbol, .got.plt has the real function address and .got has the PLT entry adddress. We will load the GOT entry with the PLT entry in finish_dynamic_symbol if it is used. For branch, it uses .got.plt. For symbol value, diff --git a/contrib/gdb-7/bfd/elf.c b/contrib/gdb-7/bfd/elf.c index 0fa75d255c..f69abf2218 100644 --- a/contrib/gdb-7/bfd/elf.c +++ b/contrib/gdb-7/bfd/elf.c @@ -1,7 +1,7 @@ /* ELF executable support for BFD. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -250,17 +250,18 @@ bfd_elf_allocate_object (bfd *abfd, bfd_boolean -bfd_elf_make_generic_object (bfd *abfd) +bfd_elf_make_object (bfd *abfd) { + const struct elf_backend_data *bed = get_elf_backend_data (abfd); return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata), - GENERIC_ELF_DATA); + bed->target_id); } bfd_boolean bfd_elf_mkcorefile (bfd *abfd) { /* I think this can be done just like an object file. */ - return bfd_elf_make_generic_object (abfd); + return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd); } static char * @@ -821,11 +822,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, const struct elf_backend_data *bed; if (hdr->bfd_section != NULL) - { - BFD_ASSERT (strcmp (name, - bfd_get_section_name (abfd, hdr->bfd_section)) == 0); - return TRUE; - } + return TRUE; newsect = bfd_make_section_anyway (abfd, name); if (newsect == NULL) @@ -1008,6 +1005,77 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, } } + /* Compress/decompress DWARF debug sections with names: .debug_* and + .zdebug_*, after the section flags is set. */ + if ((flags & SEC_DEBUGGING) + && ((name[1] == 'd' && name[6] == '_') + || (name[1] == 'z' && name[7] == '_'))) + { + enum { nothing, compress, decompress } action = nothing; + char *new_name; + + if (bfd_is_section_compressed (abfd, newsect)) + { + /* Compressed section. Check if we should decompress. */ + if ((abfd->flags & BFD_DECOMPRESS)) + action = decompress; + } + else + { + /* Normal section. Check if we should compress. */ + if ((abfd->flags & BFD_COMPRESS)) + action = compress; + } + + new_name = NULL; + switch (action) + { + case nothing: + break; + case compress: + if (!bfd_init_section_compress_status (abfd, newsect)) + { + (*_bfd_error_handler) + (_("%B: unable to initialize commpress status for section %s"), + abfd, name); + return FALSE; + } + if (name[1] != 'z') + { + unsigned int len = strlen (name); + + new_name = bfd_alloc (abfd, len + 2); + if (new_name == NULL) + return FALSE; + new_name[0] = '.'; + new_name[1] = 'z'; + memcpy (new_name + 2, name + 1, len); + } + break; + case decompress: + if (!bfd_init_section_decompress_status (abfd, newsect)) + { + (*_bfd_error_handler) + (_("%B: unable to initialize decommpress status for section %s"), + abfd, name); + return FALSE; + } + if (name[1] == 'z') + { + unsigned int len = strlen (name); + + new_name = bfd_alloc (abfd, len); + if (new_name == NULL) + return FALSE; + new_name[0] = '.'; + memcpy (new_name + 1, name + 2, len - 1); + } + break; + } + if (new_name != NULL) + bfd_rename_section (abfd, newsect, new_name); + } + return TRUE; } @@ -1709,8 +1777,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* *These* do a lot of work -- but build no sections! */ { asection *target_sect; - Elf_Internal_Shdr *hdr2; + Elf_Internal_Shdr *hdr2, **p_hdr; unsigned int num_sec = elf_numsections (abfd); + struct bfd_elf_section_data *esdt; + bfd_size_type amt; if (hdr->sh_entsize != (bfd_size_type) (hdr->sh_type == SHT_REL @@ -1789,20 +1859,19 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) if (target_sect == NULL) return FALSE; - if ((target_sect->flags & SEC_RELOC) == 0 - || target_sect->reloc_count == 0) - hdr2 = &elf_section_data (target_sect)->rel_hdr; + esdt = elf_section_data (target_sect); + if (hdr->sh_type == SHT_RELA) + p_hdr = &esdt->rela.hdr; else - { - bfd_size_type amt; - BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL); - amt = sizeof (*hdr2); - hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); - if (hdr2 == NULL) - return FALSE; - elf_section_data (target_sect)->rel_hdr2 = hdr2; - } + p_hdr = &esdt->rel.hdr; + + BFD_ASSERT (*p_hdr == NULL); + amt = sizeof (*hdr2); + hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); + if (hdr2 == NULL) + return FALSE; *hdr2 = *hdr; + *p_hdr = hdr2; elf_elfsections (abfd)[shindex] = hdr2; target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr); target_sect->flags |= SEC_RELOC; @@ -1811,7 +1880,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* In the section to which the relocations apply, mark whether its relocations are of the REL or RELA variety. */ if (hdr->sh_size != 0) - target_sect->use_rela_p = hdr->sh_type == SHT_RELA; + { + if (hdr->sh_type == SHT_RELA) + target_sect->use_rela_p = 1; + } abfd->flags |= HAS_RELOC; return TRUE; } @@ -2010,6 +2082,7 @@ static const struct bfd_elf_special_section special_sections_f[] = static const struct bfd_elf_special_section special_sections_g[] = { { STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, + { STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE }, { STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 }, { STRING_COMMA_LEN (".gnu.version_d"), 0, SHT_GNU_verdef, 0 }, @@ -2231,12 +2304,19 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec) anyway. We will set ELF section type and flags for all linker created sections. If user specifies BFD section flags, we will set ELF section type and flags based on BFD section flags in - elf_fake_sections. */ - if ((!sec->flags && abfd->direction != read_direction) + elf_fake_sections. Special handling for .init_array/.fini_array + output sections since they may contain .ctors/.dtors input + sections. We don't want _bfd_elf_init_private_section_data to + copy ELF section type from .ctors/.dtors input sections. */ + if (abfd->direction != read_direction || (sec->flags & SEC_LINKER_CREATED) != 0) { ssect = (*bed->get_sec_type_attr) (abfd, sec); - if (ssect != NULL) + if (ssect != NULL + && (!sec->flags + || (sec->flags & SEC_LINKER_CREATED) != 0 + || ssect->type == SHT_INIT_ARRAY + || ssect->type == SHT_FINI_ARRAY)) { elf_section_type (sec) = ssect->type; elf_section_flags (sec) = ssect->attr; @@ -2409,20 +2489,43 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) } } -/* Initialize REL_HDR, the section-header for new section, containing - relocations against ASECT. If USE_RELA_P is TRUE, we use RELA - relocations; otherwise, we use REL relocations. */ +/* Return the REL_HDR for SEC, assuming there is only a single one, either + REL or RELA. */ + +Elf_Internal_Shdr * +_bfd_elf_single_rel_hdr (asection *sec) +{ + if (elf_section_data (sec)->rel.hdr) + { + BFD_ASSERT (elf_section_data (sec)->rela.hdr == NULL); + return elf_section_data (sec)->rel.hdr; + } + else + return elf_section_data (sec)->rela.hdr; +} + +/* Allocate and initialize a section-header for a new reloc section, + containing relocations against ASECT. It is stored in RELDATA. If + USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL + relocations. */ bfd_boolean _bfd_elf_init_reloc_shdr (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, + struct bfd_elf_section_reloc_data *reldata, asection *asect, bfd_boolean use_rela_p) { + Elf_Internal_Shdr *rel_hdr; char *name; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_size_type amt = sizeof ".rela" + strlen (asect->name); + bfd_size_type amt; + amt = sizeof (Elf_Internal_Shdr); + BFD_ASSERT (reldata->hdr == NULL); + rel_hdr = bfd_zalloc (abfd, amt); + reldata->hdr = rel_hdr; + + amt = sizeof ".rela" + strlen (asect->name); name = (char *) bfd_alloc (abfd, amt); if (name == NULL) return FALSE; @@ -2451,36 +2554,42 @@ int bfd_elf_get_default_section_type (flagword flags) { if ((flags & SEC_ALLOC) != 0 - && ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0 - || (flags & SEC_NEVER_LOAD) != 0)) + && (flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) return SHT_NOBITS; return SHT_PROGBITS; } +struct fake_section_arg +{ + struct bfd_link_info *link_info; + bfd_boolean failed; +}; + /* Set up an ELF internal section header for a section. */ static void -elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) +elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) { + struct fake_section_arg *arg = (struct fake_section_arg *)fsarg; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_boolean *failedptr = (bfd_boolean *) failedptrarg; + struct bfd_elf_section_data *esd = elf_section_data (asect); Elf_Internal_Shdr *this_hdr; unsigned int sh_type; - if (*failedptr) + if (arg->failed) { /* We already failed; just get out of the bfd_map_over_sections loop. */ return; } - this_hdr = &elf_section_data (asect)->this_hdr; + this_hdr = &esd->this_hdr; this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), asect->name, FALSE); if (this_hdr->sh_name == (unsigned int) -1) { - *failedptr = TRUE; + arg->failed = TRUE; return; } @@ -2632,11 +2741,45 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE) this_hdr->sh_flags |= SHF_EXCLUDE; + /* If the section has relocs, set up a section header for the + SHT_REL[A] section. If two relocation sections are required for + this section, it is up to the processor-specific back-end to + create the other. */ + if ((asect->flags & SEC_RELOC) != 0) + { + /* When doing a relocatable link, create both REL and RELA sections if + needed. */ + if (arg->link_info + /* Do the normal setup if we wouldn't create any sections here. */ + && esd->rel.count + esd->rela.count > 0 + && (arg->link_info->relocatable || arg->link_info->emitrelocations)) + { + if (esd->rel.count && esd->rel.hdr == NULL + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE)) + { + arg->failed = TRUE; + return; + } + if (esd->rela.count && esd->rela.hdr == NULL + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE)) + { + arg->failed = TRUE; + return; + } + } + else if (!_bfd_elf_init_reloc_shdr (abfd, + (asect->use_rela_p + ? &esd->rela : &esd->rel), + asect, + asect->use_rela_p)) + arg->failed = TRUE; + } + /* Check for processor-specific section types. */ sh_type = this_hdr->sh_type; if (bed->elf_backend_fake_sections && !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect)) - *failedptr = TRUE; + arg->failed = TRUE; if (sh_type == SHT_NOBITS && asect->size != 0) { @@ -2644,17 +2787,6 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) called for objcopy --only-keep-debug. */ this_hdr->sh_type = sh_type; } - - /* If the section has relocs, set up a section header for the - SHT_REL[A] section. If two relocation sections are required for - this section, it is up to the processor-specific back-end to - create the other. */ - if ((asect->flags & SEC_RELOC) != 0 - && !_bfd_elf_init_reloc_shdr (abfd, - &elf_section_data (asect)->rel_hdr, - asect, - asect->use_rela_p)) - *failedptr = TRUE; } /* Fill in the contents of a SHT_GROUP section. Called from @@ -2820,21 +2952,21 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (d->this_hdr.sh_type != SHT_GROUP) d->this_idx = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name); - if ((sec->flags & SEC_RELOC) == 0) - d->rel_idx = 0; - else + if (d->rel.hdr) { - d->rel_idx = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name); + d->rel.idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name); } + else + d->rel.idx = 0; - if (d->rel_hdr2) + if (d->rela.hdr) { - d->rel_idx2 = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name); + d->rela.idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name); } else - d->rel_idx2 = 0; + d->rela.idx = 0; } t->shstrtab_section = section_number++; @@ -2906,25 +3038,25 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) d = elf_section_data (sec); i_shdrp[d->this_idx] = &d->this_hdr; - if (d->rel_idx != 0) - i_shdrp[d->rel_idx] = &d->rel_hdr; - if (d->rel_idx2 != 0) - i_shdrp[d->rel_idx2] = d->rel_hdr2; + if (d->rel.idx != 0) + i_shdrp[d->rel.idx] = d->rel.hdr; + if (d->rela.idx != 0) + i_shdrp[d->rela.idx] = d->rela.hdr; /* Fill in the sh_link and sh_info fields while we're at it. */ /* sh_link of a reloc section is the section index of the symbol table. sh_info is the section index of the section to which the relocation entries apply. */ - if (d->rel_idx != 0) + if (d->rel.idx != 0) { - d->rel_hdr.sh_link = t->symtab_section; - d->rel_hdr.sh_info = d->this_idx; + d->rel.hdr->sh_link = t->symtab_section; + d->rel.hdr->sh_info = d->this_idx; } - if (d->rel_idx2 != 0) + if (d->rela.idx != 0) { - d->rel_hdr2->sh_link = t->symtab_section; - d->rel_hdr2->sh_info = d->this_idx; + d->rela.hdr->sh_link = t->symtab_section; + d->rela.hdr->sh_info = d->this_idx; } /* We need to set up sh_link for SHF_LINK_ORDER. */ @@ -3278,6 +3410,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, struct bfd_link_info *link_info) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct fake_section_arg fsargs; bfd_boolean failed; struct bfd_strtab_hash *strtab = NULL; Elf_Internal_Shdr *shstrtab_hdr; @@ -3297,9 +3430,10 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, if (bed->elf_backend_post_process_headers) (*bed->elf_backend_post_process_headers) (abfd, link_info); - failed = FALSE; - bfd_map_over_sections (abfd, elf_fake_sections, &failed); - if (failed) + fsargs.failed = FALSE; + fsargs.link_info = link_info; + bfd_map_over_sections (abfd, elf_fake_sections, &fsargs); + if (fsargs.failed) return FALSE; if (!assign_section_numbers (abfd, link_info)) @@ -3319,6 +3453,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, return FALSE; } + failed = FALSE; if (link_info == NULL) { bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed); @@ -3624,6 +3759,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) asection *first_tls = NULL; asection *dynsec, *eh_frame_hdr; bfd_size_type amt; + bfd_vma addr_mask, wrap_to = 0; /* Select the allocated sections, and sort them. */ @@ -3632,6 +3768,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (sections == NULL) goto error_return; + /* Calculate top address, avoiding undefined behaviour of shift + left operator when shift count is equal to size of type + being shifted. */ + addr_mask = ((bfd_vma) 1 << (bfd_arch_bits_per_address (abfd) - 1)) - 1; + addr_mask = (addr_mask << 1) + 1; + i = 0; for (s = abfd->sections; s != NULL; s = s->next) { @@ -3639,6 +3781,9 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { sections[i] = s; ++i; + /* A wrapping section potentially clashes with header. */ + if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask)) + wrap_to = (s->lma + s->size) & addr_mask; } } BFD_ASSERT (i <= bfd_count_sections (abfd)); @@ -3708,8 +3853,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); if ((abfd->flags & D_PAGED) == 0 - || sections[0]->lma < phdr_size - || sections[0]->lma % maxpagesize < phdr_size % maxpagesize) + || (sections[0]->lma & addr_mask) < phdr_size + || ((sections[0]->lma & addr_mask) % maxpagesize + < phdr_size % maxpagesize) + || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to) phdr_in_segment = FALSE; } @@ -3736,6 +3883,13 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) segment. */ new_segment = TRUE; } + else if (hdr->lma < last_hdr->lma + last_size + || last_hdr->lma + last_size < last_hdr->lma) + { + /* If this section has a load address that makes it overlap + the previous section, then we need a new segment. */ + new_segment = TRUE; + } /* In the next test we have to be careful when last_hdr->lma is close to the end of the address space. If the aligned address wraps around to the start of the address space, then there are no more @@ -3767,9 +3921,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) } else if (! writable && (hdr->flags & SEC_READONLY) == 0 - && (((last_hdr->lma + last_size - 1) - & ~(maxpagesize - 1)) - != (hdr->lma & ~(maxpagesize - 1)))) + && (((last_hdr->lma + last_size - 1) & -maxpagesize) + != (hdr->lma & -maxpagesize))) { /* We don't want to put a writable section in a read only segment, unless they are on the same page in memory @@ -3876,8 +4029,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (s2->next->alignment_power == 2 && (s2->next->flags & SEC_LOAD) != 0 && CONST_STRNEQ (s2->next->name, ".note") - && align_power (s2->vma + s2->size, 2) - == s2->next->vma) + && align_power (s2->lma + s2->size, 2) + == s2->next->lma) count++; else break; @@ -4127,10 +4280,12 @@ print_segment_map (const struct elf_segment_map *m) (unsigned int) m->p_type); pt = buf; } + fflush (stdout); fprintf (stderr, "%s:", pt); for (j = 0; j < m->count; j++) fprintf (stderr, " %s", m->sections [j]->name); putc ('\n',stderr); + fflush (stderr); } static bfd_boolean @@ -4179,8 +4334,18 @@ assign_file_positions_for_load_sections (bfd *abfd, header_pad = m->header_size; } - elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr; - elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr; + if (alloc) + { + elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr; + elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr; + } + else + { + /* PR binutils/12467. */ + elf_elfheader (abfd)->e_phoff = 0; + elf_elfheader (abfd)->e_phentsize = 0; + } + elf_elfheader (abfd)->e_phnum = alloc; if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1) @@ -4330,7 +4495,7 @@ assign_file_positions_for_load_sections (bfd *abfd, break; } - off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align); + off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align); off += off_adjust; if (no_contents) { @@ -4457,15 +4622,20 @@ assign_file_positions_for_load_sections (bfd *abfd, && ((this_hdr->sh_flags & SHF_TLS) == 0 || p->p_type == PT_TLS)))) { - bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz); - - if (sec->lma < p->p_paddr + p->p_memsz) + bfd_vma p_start = p->p_paddr; + bfd_vma p_end = p_start + p->p_memsz; + bfd_vma s_start = sec->lma; + bfd_vma adjust = s_start - p_end; + + if (adjust != 0 + && (s_start < p_end + || p_end < p_start)) { (*_bfd_error_handler) - (_("%B: section %A lma 0x%lx overlaps previous sections"), - abfd, sec, (unsigned long) sec->lma); + (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec, + (unsigned long) s_start, (unsigned long) p_end); adjust = 0; - sec->lma = p->p_paddr + p->p_memsz; + sec->lma = p_end; } p->p_memsz += adjust; @@ -4578,8 +4748,7 @@ assign_file_positions_for_load_sections (bfd *abfd, sec = m->sections[i]; this_hdr = &(elf_section_data(sec)->this_hdr); - if (this_hdr->sh_size != 0 - && !ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma)) + if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)) { (*_bfd_error_handler) (_("%B: section `%A' can't be allocated in segment %d"), @@ -4629,13 +4798,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd, BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos); else if ((hdr->sh_flags & SHF_ALLOC) != 0) { - if (hdr->sh_size != 0) - ((*_bfd_error_handler) - (_("%B: warning: allocated section `%s' not in segment"), - abfd, - (hdr->bfd_section == NULL - ? "*unknown*" - : hdr->bfd_section->name))); + (*_bfd_error_handler) + (_("%B: warning: allocated section `%s' not in segment"), + abfd, + (hdr->bfd_section == NULL + ? "*unknown*" + : hdr->bfd_section->name)); /* We don't need to page align empty sections. */ if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0) off += vma_page_aligned_bias (hdr->sh_addr, off, @@ -5136,9 +5304,8 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr) #if DEBUG & 4 { fprintf (stderr, - "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n", - (long) asym_ptr, asym_ptr->name, idx, flags, - elf_symbol_flags (flags)); + "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx\n", + (long) asym_ptr, asym_ptr->name, idx, (long) flags); fflush (stderr); } #endif @@ -5849,7 +6016,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) bfd_size_type amt; Elf_Internal_Shdr *this_hdr; asection *first_section = NULL; - asection *lowest_section = NULL; + asection *lowest_section; /* Compute how many sections are in this segment. */ for (section = ibfd->sections, section_count = 0; @@ -5857,13 +6024,10 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) section = section->next) { this_hdr = &(elf_section_data(section)->this_hdr); - if (this_hdr->sh_size != 0 - && ELF_SECTION_IN_SEGMENT (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { - if (!first_section) - first_section = lowest_section = section; - if (section->lma < lowest_section->lma) - lowest_section = section; + if (first_section == NULL) + first_section = section; section_count++; } } @@ -5917,17 +6081,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) phdr_included = TRUE; } - if (map->includes_filehdr && first_section) - /* We need to keep the space used by the headers fixed. */ - map->header_size = first_section->vma - segment->p_vaddr; - - if (!map->includes_phdrs - && !map->includes_filehdr - && map->p_paddr_valid) - /* There is some other padding before the first section. */ - map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0) - - segment->p_paddr); - + lowest_section = first_section; if (section_count != 0) { unsigned int isec = 0; @@ -5937,16 +6091,44 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) section = section->next) { this_hdr = &(elf_section_data(section)->this_hdr); - if (this_hdr->sh_size != 0 - && ELF_SECTION_IN_SEGMENT (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { map->sections[isec++] = section->output_section; + if (section->lma < lowest_section->lma) + lowest_section = section; + if ((section->flags & SEC_ALLOC) != 0) + { + bfd_vma seg_off; + + /* Section lmas are set up from PT_LOAD header + p_paddr in _bfd_elf_make_section_from_shdr. + If this header has a p_paddr that disagrees + with the section lma, flag the p_paddr as + invalid. */ + if ((section->flags & SEC_LOAD) != 0) + seg_off = this_hdr->sh_offset - segment->p_offset; + else + seg_off = this_hdr->sh_addr - segment->p_vaddr; + if (section->lma - segment->p_paddr != seg_off) + map->p_paddr_valid = FALSE; + } if (isec == section_count) break; } } } + if (map->includes_filehdr && lowest_section != NULL) + /* We need to keep the space used by the headers fixed. */ + map->header_size = lowest_section->vma - segment->p_vaddr; + + if (!map->includes_phdrs + && !map->includes_filehdr + && map->p_paddr_valid) + /* There is some other padding before the first section. */ + map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0) + - segment->p_paddr); + map->count = section_count; *pointer_to_map = map; pointer_to_map = &map->next; @@ -6015,8 +6197,7 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd) /* Check if this section is covered by the segment. */ this_hdr = &(elf_section_data(section)->this_hdr); - if (this_hdr->sh_size != 0 - && ELF_SECTION_IN_SEGMENT (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { /* FIXME: Check if its output section is changed or removed. What else do we need to check? */ @@ -6075,7 +6256,7 @@ _bfd_elf_init_private_section_data (bfd *ibfd, && (osec->flags == isec->flags || (final_link && ((osec->flags ^ isec->flags) - & ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)) == 0))) + & ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC)) == 0))) elf_section_type (osec) = elf_section_type (isec); /* FIXME: Is this correct for all OS/PROC specific flags? */ @@ -6361,6 +6542,7 @@ swap_out_syms (bfd *abfd, sym.st_info = 0; sym.st_other = 0; sym.st_shndx = SHN_UNDEF; + sym.st_target_internal = 0; bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx); outbound_syms += bed->s->sizeof_sym; if (outbound_shndx != NULL) @@ -6560,9 +6742,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), } if (type_ptr != NULL) - sym.st_other = type_ptr->internal_elf_sym.st_other; + { + sym.st_other = type_ptr->internal_elf_sym.st_other; + sym.st_target_internal + = type_ptr->internal_elf_sym.st_target_internal; + } else - sym.st_other = 0; + { + sym.st_other = 0; + sym.st_target_internal = 0; + } bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx); outbound_syms += bed->s->sizeof_sym; @@ -7513,13 +7702,19 @@ _bfd_elf_rel_vtable_reloc_fn # include #endif -/* FIXME: this is kinda wrong, but it's what gdb wants. */ +/* Return a PID that identifies a "thread" for threaded cores, or the + PID of the main process for non-threaded cores. */ static int elfcore_make_pid (bfd *abfd) { - return ((elf_tdata (abfd)->core_lwpid << 16) - + (elf_tdata (abfd)->core_pid)); + int pid; + + pid = elf_tdata (abfd)->core_lwpid; + if (pid == 0) + pid = elf_tdata (abfd)->core_pid; + + return pid; } /* If there isn't a section called NAME, make one, using @@ -7609,7 +7804,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) has already been set by another thread. */ if (elf_tdata (abfd)->core_signal == 0) elf_tdata (abfd)->core_signal = prstat.pr_cursig; - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core_pid == 0) + elf_tdata (abfd)->core_pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7619,6 +7815,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) */ #if defined (HAVE_PRSTATUS_T_PR_WHO) elf_tdata (abfd)->core_lwpid = prstat.pr_who; +#else + elf_tdata (abfd)->core_lwpid = prstat.pr_pid; #endif } #if defined (HAVE_PRSTATUS32_T) @@ -7635,7 +7833,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) has already been set by another thread. */ if (elf_tdata (abfd)->core_signal == 0) elf_tdata (abfd)->core_signal = prstat.pr_cursig; - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core_pid == 0) + elf_tdata (abfd)->core_pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7645,6 +7844,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) */ #if defined (HAVE_PRSTATUS32_T_PR_WHO) elf_tdata (abfd)->core_lwpid = prstat.pr_who; +#else + elf_tdata (abfd)->core_lwpid = prstat.pr_pid; #endif } #endif /* HAVE_PRSTATUS32_T */ diff --git a/contrib/gdb-7/bfd/elf32-i386.c b/contrib/gdb-7/bfd/elf32-i386.c index 7964c4fd6e..693c8e89d2 100644 --- a/contrib/gdb-7/bfd/elf32-i386.c +++ b/contrib/gdb-7/bfd/elf32-i386.c @@ -419,7 +419,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20); /* pr_pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 28; @@ -437,7 +437,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 72; @@ -475,6 +475,8 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return FALSE; case 124: /* Linux/i386 elf_prpsinfo. */ + elf_tdata (abfd)->core_pid + = bfd_get_32 (abfd, note->descdata + 12); elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); elf_tdata (abfd)->core_command @@ -789,8 +791,6 @@ elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab, ret->elf.indx = sec->id; ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info); ret->elf.dynindx = -1; - ret->elf.plt.offset = (bfd_vma) -1; - ret->elf.got.offset = (bfd_vma) -1; *slot = ret; } return &ret->elf; @@ -1162,6 +1162,12 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, unsigned int to_type = from_type; bfd_boolean check = TRUE; + /* Skip TLS transition for functions. */ + if (h != NULL + && (h->type == STT_FUNC + || h->type == STT_GNU_IFUNC)) + return TRUE; + switch (from_type) { case R_386_TLS_GD: @@ -1330,8 +1336,7 @@ elf_i386_check_relocs (bfd *abfd, /* Check relocation against local STT_GNU_IFUNC symbol. */ if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { - h = elf_i386_get_local_sym_hash (htab, abfd, rel, - TRUE); + h = elf_i386_get_local_sym_hash (htab, abfd, rel, TRUE); if (h == NULL) return FALSE; @@ -1802,16 +1807,36 @@ elf_i386_gc_sweep_hook (bfd *abfd, r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { - struct elf_i386_link_hash_entry *eh; - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct elf_i386_link_hash_entry *) h; + } + else + { + /* A local symbol. */ + Elf_Internal_Sym *isym; + + isym = bfd_sym_from_r_symndx (&htab->sym_cache, + abfd, r_symndx); + + /* Check relocation against local STT_GNU_IFUNC symbol. */ + if (isym != NULL + && ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) + { + h = elf_i386_get_local_sym_hash (htab, abfd, rel, FALSE); + if (h == NULL) + abort (); + } + } + + if (h) + { + struct elf_i386_link_hash_entry *eh; + struct elf_dyn_relocs **pp; + struct elf_dyn_relocs *p; + eh = (struct elf_i386_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) if (p->sec == sec) { @@ -1846,6 +1871,11 @@ elf_i386_gc_sweep_hook (bfd *abfd, { if (h->got.refcount > 0) h->got.refcount -= 1; + if (h->type == STT_GNU_IFUNC) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } } else if (local_got_refcounts != NULL) { @@ -1856,7 +1886,8 @@ elf_i386_gc_sweep_hook (bfd *abfd, case R_386_32: case R_386_PC32: - if (info->shared) + if (info->shared + && (h == NULL || h->type != STT_GNU_IFUNC)) break; /* Fall through */ @@ -1868,6 +1899,16 @@ elf_i386_gc_sweep_hook (bfd *abfd, } break; + case R_386_GOTOFF: + if (h != NULL && h->type == STT_GNU_IFUNC) + { + if (h->got.refcount > 0) + h->got.refcount -= 1; + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + break; + default: break; } @@ -2520,6 +2561,30 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->elf.srelplt) htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; + if (htab->elf.sgotplt) + { + struct elf_link_hash_entry *got; + got = elf_link_hash_lookup (elf_hash_table (info), + "_GLOBAL_OFFSET_TABLE_", + FALSE, FALSE, FALSE); + + /* Don't allocate .got.plt section if there are no GOT nor PLT + entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */ + if ((got == NULL + || !got->ref_regular_nonweak) + && (htab->elf.sgotplt->size + == get_elf_backend_data (output_bfd)->got_header_size) + && (htab->elf.splt == NULL + || htab->elf.splt->size == 0) + && (htab->elf.sgot == NULL + || htab->elf.sgot->size == 0) + && (htab->elf.iplt == NULL + || htab->elf.iplt->size == 0) + && (htab->elf.igotplt == NULL + || htab->elf.igotplt->size == 0)) + htab->elf.sgotplt->size = 0; + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -2767,11 +2832,16 @@ static bfd_vma elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address) { struct elf_link_hash_table *htab = elf_hash_table (info); + const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd); + bfd_vma static_tls_size; /* If tls_sec is NULL, we should have signalled an error already. */ if (htab->tls_sec == NULL) return 0; - return htab->tls_size + htab->tls_sec->vma - address; + + /* Consider special static TLS alignment requirements. */ + static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment); + return static_tls_size + htab->tls_sec->vma - address; } /* Relocate an i386 ELF section. */ @@ -2934,8 +3004,8 @@ elf_i386_relocate_section (bfd *output_bfd, && ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { /* Relocate against local STT_GNU_IFUNC symbol. */ - h = elf_i386_get_local_sym_hash (htab, input_bfd, - rel, FALSE); + h = elf_i386_get_local_sym_hash (htab, input_bfd, rel, + FALSE); if (h == NULL) abort (); @@ -3058,7 +3128,7 @@ elf_i386_relocate_section (bfd *output_bfd, internal symbol, we have updated addend. */ continue; } - + /* FALLTHROUGH */ case R_386_PC32: case R_386_PLT32: goto do_relocation; @@ -4561,6 +4631,13 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, if (htab->elf.sgotplt) { + if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) + { + (*_bfd_error_handler) + (_("discarded output section: `%A'"), htab->elf.sgotplt); + return FALSE; + } + /* Fill in the first three entries in the global offset table. */ if (htab->elf.sgotplt->size > 0) { @@ -4631,6 +4708,7 @@ elf_i386_add_symbol_hook (bfd * abfd, #define TARGET_LITTLE_SYM bfd_elf32_i386_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 +#define ELF_TARGET_ID I386_ELF_DATA #define ELF_MACHINE_CODE EM_386 #define ELF_MAXPAGESIZE 0x1000 @@ -4726,6 +4804,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #undef elf32_bed #define elf32_bed elf32_i386_sol2_bed +/* The 32-bit static TLS arena size is rounded to the nearest 8-byte + boundary. */ +#undef elf_backend_static_tls_alignment +#define elf_backend_static_tls_alignment 8 + /* The Solaris 2 ABI requires a plt symbol on all platforms. Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output @@ -4779,6 +4862,7 @@ elf_i386_vxworks_link_hash_table_create (bfd *abfd) #undef elf_backend_final_write_processing #define elf_backend_final_write_processing \ elf_vxworks_final_write_processing +#undef elf_backend_static_tls_alignment /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so define it. */ diff --git a/contrib/gdb-7/bfd/elf64-x86-64.c b/contrib/gdb-7/bfd/elf64-x86-64.c index 21524fa749..927b3ed4a5 100644 --- a/contrib/gdb-7/bfd/elf64-x86-64.c +++ b/contrib/gdb-7/bfd/elf64-x86-64.c @@ -1,4 +1,4 @@ -/* X86-64 specific support for 64-bit ELF +/* X86-64 specific support for ELF Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Jan Hubicka . @@ -34,6 +34,14 @@ /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) +/* Since both 32-bit and 64-bit x86-64 encode relocation type in the + identical manner, we use ELF32_R_TYPE instead of ELF64_R_TYPE to get + relocation type. We also use ELF_ST_TYPE instead of ELF64_ST_TYPE + since they are the same. */ + +#define ABI_64_P(abfd) \ + (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) + /* The relocation "howto" table. Order of fields: type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow, special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */ @@ -222,7 +230,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] = }; static reloc_howto_type * -elf64_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) +elf_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) { unsigned i; @@ -245,8 +253,8 @@ elf64_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) /* Given a BFD reloc type, return a HOWTO structure. */ static reloc_howto_type * -elf64_x86_64_reloc_type_lookup (bfd *abfd, - bfd_reloc_code_real_type code) +elf_x86_64_reloc_type_lookup (bfd *abfd, + bfd_reloc_code_real_type code) { unsigned int i; @@ -254,15 +262,15 @@ elf64_x86_64_reloc_type_lookup (bfd *abfd, i++) { if (x86_64_reloc_map[i].bfd_reloc_val == code) - return elf64_x86_64_rtype_to_howto (abfd, - x86_64_reloc_map[i].elf_reloc_val); + return elf_x86_64_rtype_to_howto (abfd, + x86_64_reloc_map[i].elf_reloc_val); } return 0; } static reloc_howto_type * -elf64_x86_64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, - const char *r_name) +elf_x86_64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) { unsigned int i; @@ -280,19 +288,19 @@ elf64_x86_64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* Given an x86_64 ELF reloc type, fill in an arelent structure. */ static void -elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, - Elf_Internal_Rela *dst) +elf_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, + Elf_Internal_Rela *dst) { unsigned r_type; - r_type = ELF64_R_TYPE (dst->r_info); - cache_ptr->howto = elf64_x86_64_rtype_to_howto (abfd, r_type); + r_type = ELF32_R_TYPE (dst->r_info); + cache_ptr->howto = elf_x86_64_rtype_to_howto (abfd, r_type); BFD_ASSERT (r_type == cache_ptr->howto->type); } /* Support for core dump NOTE sections. */ static bfd_boolean -elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +elf_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; size_t size; @@ -308,7 +316,7 @@ elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 32); /* pr_reg */ @@ -324,7 +332,7 @@ elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) } static bfd_boolean -elf64_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { switch (note->descsz) { @@ -332,6 +340,8 @@ elf64_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return FALSE; case 136: /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */ + elf_tdata (abfd)->core_pid + = bfd_get_32 (abfd, note->descdata + 24); elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); elf_tdata (abfd)->core_command @@ -358,7 +368,8 @@ elf64_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) /* The name of the dynamic interpreter. This is put in the .interp section. */ -#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1" +#define ELF64_DYNAMIC_INTERPRETER "/lib/ld64.so.1" +#define ELF32_DYNAMIC_INTERPRETER "/lib/ld32.so.1" /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid copying dynamic variables from a shared lib into an app's dynbss @@ -377,7 +388,7 @@ elf64_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) /* The first entry in a procedure linkage table looks like this. See the SVR4 ABI i386 supplement and the x86-64 ABI to see how this works. */ -static const bfd_byte elf64_x86_64_plt0_entry[PLT_ENTRY_SIZE] = +static const bfd_byte elf_x86_64_plt0_entry[PLT_ENTRY_SIZE] = { 0xff, 0x35, 8, 0, 0, 0, /* pushq GOT+8(%rip) */ 0xff, 0x25, 16, 0, 0, 0, /* jmpq *GOT+16(%rip) */ @@ -386,7 +397,7 @@ static const bfd_byte elf64_x86_64_plt0_entry[PLT_ENTRY_SIZE] = /* Subsequent entries in a procedure linkage table look like this. */ -static const bfd_byte elf64_x86_64_plt_entry[PLT_ENTRY_SIZE] = +static const bfd_byte elf_x86_64_plt_entry[PLT_ENTRY_SIZE] = { 0xff, 0x25, /* jmpq *name@GOTPC(%rip) */ 0, 0, 0, 0, /* replaced with offset to this symbol in .got. */ @@ -398,7 +409,7 @@ static const bfd_byte elf64_x86_64_plt_entry[PLT_ENTRY_SIZE] = /* x86-64 ELF linker hash entry. */ -struct elf64_x86_64_link_hash_entry +struct elf_x86_64_link_hash_entry { struct elf_link_hash_entry elf; @@ -425,10 +436,10 @@ struct elf64_x86_64_link_hash_entry bfd_vma tlsdesc_got; }; -#define elf64_x86_64_hash_entry(ent) \ - ((struct elf64_x86_64_link_hash_entry *)(ent)) +#define elf_x86_64_hash_entry(ent) \ + ((struct elf_x86_64_link_hash_entry *)(ent)) -struct elf64_x86_64_obj_tdata +struct elf_x86_64_obj_tdata { struct elf_obj_tdata root; @@ -439,14 +450,14 @@ struct elf64_x86_64_obj_tdata bfd_vma *local_tlsdesc_gotent; }; -#define elf64_x86_64_tdata(abfd) \ - ((struct elf64_x86_64_obj_tdata *) (abfd)->tdata.any) +#define elf_x86_64_tdata(abfd) \ + ((struct elf_x86_64_obj_tdata *) (abfd)->tdata.any) -#define elf64_x86_64_local_got_tls_type(abfd) \ - (elf64_x86_64_tdata (abfd)->local_got_tls_type) +#define elf_x86_64_local_got_tls_type(abfd) \ + (elf_x86_64_tdata (abfd)->local_got_tls_type) -#define elf64_x86_64_local_tlsdesc_gotent(abfd) \ - (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent) +#define elf_x86_64_local_tlsdesc_gotent(abfd) \ + (elf_x86_64_tdata (abfd)->local_tlsdesc_gotent) #define is_x86_64_elf(bfd) \ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ @@ -454,15 +465,15 @@ struct elf64_x86_64_obj_tdata && elf_object_id (bfd) == X86_64_ELF_DATA) static bfd_boolean -elf64_x86_64_mkobject (bfd *abfd) +elf_x86_64_mkobject (bfd *abfd) { - return bfd_elf_allocate_object (abfd, sizeof (struct elf64_x86_64_obj_tdata), + return bfd_elf_allocate_object (abfd, sizeof (struct elf_x86_64_obj_tdata), X86_64_ELF_DATA); } /* x86-64 ELF linker hash table. */ -struct elf64_x86_64_link_hash_table +struct elf_x86_64_link_hash_table { struct elf_link_hash_table elf; @@ -482,6 +493,12 @@ struct elf64_x86_64_link_hash_table /* Small local sym cache. */ struct sym_cache sym_cache; + bfd_vma (*r_info) (bfd_vma, bfd_vma); + bfd_vma (*r_sym) (bfd_vma); + unsigned int pointer_r_type; + const char *dynamic_interpreter; + int dynamic_interpreter_size; + /* _TLS_MODULE_BASE_ symbol. */ struct bfd_link_hash_entry *tls_module_base; @@ -501,19 +518,19 @@ struct elf64_x86_64_link_hash_table /* Get the x86-64 ELF linker hash table from a link_info structure. */ -#define elf64_x86_64_hash_table(p) \ +#define elf_x86_64_hash_table(p) \ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ - == X86_64_ELF_DATA ? ((struct elf64_x86_64_link_hash_table *) ((p)->hash)) : NULL) + == X86_64_ELF_DATA ? ((struct elf_x86_64_link_hash_table *) ((p)->hash)) : NULL) -#define elf64_x86_64_compute_jump_table_size(htab) \ +#define elf_x86_64_compute_jump_table_size(htab) \ ((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE) /* Create an entry in an x86-64 ELF linker hash table. */ static struct bfd_hash_entry * -elf64_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, - struct bfd_hash_table *table, - const char *string) +elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ @@ -521,7 +538,7 @@ elf64_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, { entry = (struct bfd_hash_entry *) bfd_hash_allocate (table, - sizeof (struct elf64_x86_64_link_hash_entry)); + sizeof (struct elf_x86_64_link_hash_entry)); if (entry == NULL) return entry; } @@ -530,9 +547,9 @@ elf64_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, entry = _bfd_elf_link_hash_newfunc (entry, table, string); if (entry != NULL) { - struct elf64_x86_64_link_hash_entry *eh; + struct elf_x86_64_link_hash_entry *eh; - eh = (struct elf64_x86_64_link_hash_entry *) entry; + eh = (struct elf_x86_64_link_hash_entry *) entry; eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; eh->tlsdesc_got = (bfd_vma) -1; @@ -547,7 +564,7 @@ elf64_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, hash since they aren't used by global symbols in this backend. */ static hashval_t -elf64_x86_64_local_htab_hash (const void *ptr) +elf_x86_64_local_htab_hash (const void *ptr) { struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr; @@ -557,7 +574,7 @@ elf64_x86_64_local_htab_hash (const void *ptr) /* Compare local hash entries. */ static int -elf64_x86_64_local_htab_eq (const void *ptr1, const void *ptr2) +elf_x86_64_local_htab_eq (const void *ptr1, const void *ptr2) { struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1; @@ -570,18 +587,18 @@ elf64_x86_64_local_htab_eq (const void *ptr1, const void *ptr2) /* Find and/or create a hash entry for local symbol. */ static struct elf_link_hash_entry * -elf64_x86_64_get_local_sym_hash (struct elf64_x86_64_link_hash_table *htab, - bfd *abfd, const Elf_Internal_Rela *rel, - bfd_boolean create) +elf_x86_64_get_local_sym_hash (struct elf_x86_64_link_hash_table *htab, + bfd *abfd, const Elf_Internal_Rela *rel, + bfd_boolean create) { - struct elf64_x86_64_link_hash_entry e, *ret; + struct elf_x86_64_link_hash_entry e, *ret; asection *sec = abfd->sections; hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, - ELF64_R_SYM (rel->r_info)); + htab->r_sym (rel->r_info)); void **slot; e.elf.indx = sec->id; - e.elf.dynstr_index = ELF64_R_SYM (rel->r_info); + e.elf.dynstr_index = htab->r_sym (rel->r_info); slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h, create ? INSERT : NO_INSERT); @@ -590,21 +607,19 @@ elf64_x86_64_get_local_sym_hash (struct elf64_x86_64_link_hash_table *htab, if (*slot) { - ret = (struct elf64_x86_64_link_hash_entry *) *slot; + ret = (struct elf_x86_64_link_hash_entry *) *slot; return &ret->elf; } - ret = (struct elf64_x86_64_link_hash_entry *) + ret = (struct elf_x86_64_link_hash_entry *) objalloc_alloc ((struct objalloc *) htab->loc_hash_memory, - sizeof (struct elf64_x86_64_link_hash_entry)); + sizeof (struct elf_x86_64_link_hash_entry)); if (ret) { memset (ret, 0, sizeof (*ret)); ret->elf.indx = sec->id; - ret->elf.dynstr_index = ELF64_R_SYM (rel->r_info); + ret->elf.dynstr_index = htab->r_sym (rel->r_info); ret->elf.dynindx = -1; - ret->elf.plt.offset = (bfd_vma) -1; - ret->elf.got.offset = (bfd_vma) -1; *slot = ret; } return &ret->elf; @@ -613,18 +628,18 @@ elf64_x86_64_get_local_sym_hash (struct elf64_x86_64_link_hash_table *htab, /* Create an X86-64 ELF linker hash table. */ static struct bfd_link_hash_table * -elf64_x86_64_link_hash_table_create (bfd *abfd) +elf_x86_64_link_hash_table_create (bfd *abfd) { - struct elf64_x86_64_link_hash_table *ret; - bfd_size_type amt = sizeof (struct elf64_x86_64_link_hash_table); + struct elf_x86_64_link_hash_table *ret; + bfd_size_type amt = sizeof (struct elf_x86_64_link_hash_table); - ret = (struct elf64_x86_64_link_hash_table *) bfd_malloc (amt); + ret = (struct elf_x86_64_link_hash_table *) bfd_malloc (amt); if (ret == NULL) return NULL; if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, - elf64_x86_64_link_hash_newfunc, - sizeof (struct elf64_x86_64_link_hash_entry), + elf_x86_64_link_hash_newfunc, + sizeof (struct elf_x86_64_link_hash_entry), X86_64_ELF_DATA)) { free (ret); @@ -640,9 +655,26 @@ elf64_x86_64_link_hash_table_create (bfd *abfd) ret->sgotplt_jump_table_size = 0; ret->tls_module_base = NULL; + if (ABI_64_P (abfd)) + { + ret->r_info = elf64_r_info; + ret->r_sym = elf64_r_sym; + ret->pointer_r_type = R_X86_64_64; + ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER; + ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER; + } + else + { + ret->r_info = elf32_r_info; + ret->r_sym = elf32_r_sym; + ret->pointer_r_type = R_X86_64_32; + ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER; + ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER; + } + ret->loc_hash_table = htab_try_create (1024, - elf64_x86_64_local_htab_hash, - elf64_x86_64_local_htab_eq, + elf_x86_64_local_htab_hash, + elf_x86_64_local_htab_eq, NULL); ret->loc_hash_memory = objalloc_create (); if (!ret->loc_hash_table || !ret->loc_hash_memory) @@ -657,10 +689,10 @@ elf64_x86_64_link_hash_table_create (bfd *abfd) /* Destroy an X86-64 ELF linker hash table. */ static void -elf64_x86_64_link_hash_table_free (struct bfd_link_hash_table *hash) +elf_x86_64_link_hash_table_free (struct bfd_link_hash_table *hash) { - struct elf64_x86_64_link_hash_table *htab - = (struct elf64_x86_64_link_hash_table *) hash; + struct elf_x86_64_link_hash_table *htab + = (struct elf_x86_64_link_hash_table *) hash; if (htab->loc_hash_table) htab_delete (htab->loc_hash_table); @@ -674,14 +706,15 @@ elf64_x86_64_link_hash_table_free (struct bfd_link_hash_table *hash) hash table. */ static bfd_boolean -elf64_x86_64_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) +elf_x86_64_create_dynamic_sections (bfd *dynobj, + struct bfd_link_info *info) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; if (!_bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -699,14 +732,14 @@ elf64_x86_64_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) /* Copy the extra info we tack onto an elf_link_hash_entry. */ static void -elf64_x86_64_copy_indirect_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *dir, - struct elf_link_hash_entry *ind) +elf_x86_64_copy_indirect_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *dir, + struct elf_link_hash_entry *ind) { - struct elf64_x86_64_link_hash_entry *edir, *eind; + struct elf_x86_64_link_hash_entry *edir, *eind; - edir = (struct elf64_x86_64_link_hash_entry *) dir; - eind = (struct elf64_x86_64_link_hash_entry *) ind; + edir = (struct elf_x86_64_link_hash_entry *) dir; + eind = (struct elf_x86_64_link_hash_entry *) ind; if (eind->dyn_relocs != NULL) { @@ -789,18 +822,21 @@ x86_64_opcode32; from R_TYPE. */ static bfd_boolean -elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, - bfd_byte *contents, - Elf_Internal_Shdr *symtab_hdr, - struct elf_link_hash_entry **sym_hashes, - unsigned int r_type, - const Elf_Internal_Rela *rel, - const Elf_Internal_Rela *relend) +elf_x86_64_check_tls_transition (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + bfd_byte *contents, + Elf_Internal_Shdr *symtab_hdr, + struct elf_link_hash_entry **sym_hashes, + unsigned int r_type, + const Elf_Internal_Rela *rel, + const Elf_Internal_Rela *relend) { unsigned int val; unsigned long r_symndx; struct elf_link_hash_entry *h; bfd_vma offset; + struct elf_x86_64_link_hash_table *htab; /* Get the section contents. */ if (contents == NULL) @@ -818,6 +854,7 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, } } + htab = elf_x86_64_hash_table (info); offset = rel->r_offset; switch (r_type) { @@ -828,18 +865,34 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, if (r_type == R_X86_64_TLSGD) { - /* Check transition from GD access model. Only + /* Check transition from GD access model. For 64bit, only .byte 0x66; leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr + can transit to different access model. For 32bit, only + leaq foo@tlsgd(%rip), %rdi + .word 0x6666; rex64; call __tls_get_addr can transit to different access model. */ - static x86_64_opcode32 leaq = { { 0x66, 0x48, 0x8d, 0x3d } }, - call = { { 0x66, 0x66, 0x48, 0xe8 } }; - if (offset < 4 - || (offset + 12) > sec->size - || bfd_get_32 (abfd, contents + offset - 4) != leaq.i + static x86_64_opcode32 call = { { 0x66, 0x66, 0x48, 0xe8 } }; + if ((offset + 12) > sec->size || bfd_get_32 (abfd, contents + offset + 4) != call.i) return FALSE; + + if (ABI_64_P (abfd)) + { + static x86_64_opcode32 leaq = { { 0x66, 0x48, 0x8d, 0x3d } }; + if (offset < 4 + || bfd_get_32 (abfd, contents + offset - 4) != leaq.i) + return FALSE; + } + else + { + static x86_64_opcode16 lea = { { 0x8d, 0x3d } }; + if (offset < 3 + || bfd_get_8 (abfd, contents + offset - 3) != 0x48 + || bfd_get_16 (abfd, contents + offset - 2) != lea.i) + return FALSE; + } } else { @@ -860,7 +913,7 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, return FALSE; } - r_symndx = ELF64_R_SYM (rel[1].r_info); + r_symndx = htab->r_sym (rel[1].r_info); if (r_symndx < symtab_hdr->sh_info) return FALSE; @@ -869,23 +922,36 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, may be versioned. */ return (h != NULL && h->root.root.string != NULL - && (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32 - || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32) + && (ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PC32 + || ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLT32) && (strncmp (h->root.root.string, "__tls_get_addr", 14) == 0)); case R_X86_64_GOTTPOFF: /* Check transition from IE access model: - movq foo@gottpoff(%rip), %reg - addq foo@gottpoff(%rip), %reg + mov foo@gottpoff(%rip), %reg + add foo@gottpoff(%rip), %reg */ - if (offset < 3 || (offset + 4) > sec->size) - return FALSE; - - val = bfd_get_8 (abfd, contents + offset - 3); - if (val != 0x48 && val != 0x4c) - return FALSE; + /* Check REX prefix first. */ + if (offset >= 3 && (offset + 4) <= sec->size) + { + val = bfd_get_8 (abfd, contents + offset - 3); + if (val != 0x48 && val != 0x4c) + { + /* X32 may have 0x44 REX prefix or no REX prefix. */ + if (ABI_64_P (abfd)) + return FALSE; + } + } + else + { + /* X32 may not have any REX prefix. */ + if (ABI_64_P (abfd)) + return FALSE; + if (offset < 2 || (offset + 3) > sec->size) + return FALSE; + } val = bfd_get_8 (abfd, contents + offset - 2); if (val != 0x8b && val != 0x03) @@ -937,20 +1003,26 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, will be performed. Update R_TYPE if there is a transition. */ static bfd_boolean -elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, - asection *sec, bfd_byte *contents, - Elf_Internal_Shdr *symtab_hdr, - struct elf_link_hash_entry **sym_hashes, - unsigned int *r_type, int tls_type, - const Elf_Internal_Rela *rel, - const Elf_Internal_Rela *relend, - struct elf_link_hash_entry *h, - unsigned long r_symndx) +elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, + asection *sec, bfd_byte *contents, + Elf_Internal_Shdr *symtab_hdr, + struct elf_link_hash_entry **sym_hashes, + unsigned int *r_type, int tls_type, + const Elf_Internal_Rela *rel, + const Elf_Internal_Rela *relend, + struct elf_link_hash_entry *h, + unsigned long r_symndx) { unsigned int from_type = *r_type; unsigned int to_type = from_type; bfd_boolean check = TRUE; + /* Skip TLS transition for functions. */ + if (h != NULL + && (h->type == STT_FUNC + || h->type == STT_GNU_IFUNC)) + return TRUE; + switch (from_type) { case R_X86_64_TLSGD: @@ -965,7 +1037,7 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, to_type = R_X86_64_GOTTPOFF; } - /* When we are called from elf64_x86_64_relocate_section, + /* When we are called from elf_x86_64_relocate_section, CONTENTS isn't NULL and there may be additional transitions based on TLS_TYPE. */ if (contents != NULL) @@ -987,7 +1059,7 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, } /* We checked the transition before when we were called from - elf64_x86_64_check_relocs. We only want to check the new + elf_x86_64_check_relocs. We only want to check the new transition which hasn't been checked before. */ check = new_to_type != to_type && from_type == to_type; to_type = new_to_type; @@ -1010,23 +1082,23 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, /* Check if the transition can be performed. */ if (check - && ! elf64_x86_64_check_tls_transition (abfd, sec, contents, - symtab_hdr, sym_hashes, - from_type, rel, relend)) + && ! elf_x86_64_check_tls_transition (abfd, info, sec, contents, + symtab_hdr, sym_hashes, + from_type, rel, relend)) { reloc_howto_type *from, *to; const char *name; - from = elf64_x86_64_rtype_to_howto (abfd, from_type); - to = elf64_x86_64_rtype_to_howto (abfd, to_type); + from = elf_x86_64_rtype_to_howto (abfd, from_type); + to = elf_x86_64_rtype_to_howto (abfd, to_type); if (h) name = h->root.root.string; else { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) name = "*unknown*"; else @@ -1057,11 +1129,11 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, linkage table, and dynamic reloc sections. */ static bfd_boolean -elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) +elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; @@ -1073,7 +1145,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, BFD_ASSERT (is_x86_64_elf (abfd)); - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -1091,8 +1163,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *isym; const char *name; - r_symndx = ELF64_R_SYM (rel->r_info); - r_type = ELF64_R_TYPE (rel->r_info); + r_symndx = htab->r_sym (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { @@ -1110,10 +1182,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, return FALSE; /* Check relocation against local STT_GNU_IFUNC symbol. */ - if (ELF64_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) + if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { - h = elf64_x86_64_get_local_sym_hash (htab, abfd, rel, - TRUE); + h = elf_x86_64_get_local_sym_hash (htab, abfd, rel, + TRUE); if (h == NULL) return FALSE; @@ -1136,6 +1208,39 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, h = (struct elf_link_hash_entry *) h->root.u.i.link; } + /* Check invalid x32 relocations. */ + if (!ABI_64_P (abfd)) + switch (r_type) + { + default: + break; + + case R_X86_64_64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + case R_X86_64_PC64: + case R_X86_64_GOTOFF64: + case R_X86_64_GOT64: + case R_X86_64_GOTPCREL64: + case R_X86_64_GOTPC64: + case R_X86_64_GOTPLT64: + case R_X86_64_PLTOFF64: + { + if (h) + name = h->root.root.string; + else + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, + NULL); + (*_bfd_error_handler) + (_("%B: relocation %s against symbol `%s' isn't " + "supported in x32 mode"), abfd, + x86_64_elf_howto_table[r_type].name, name); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + break; + } + if (h != NULL) { /* Create the ifunc sections for static executables. If we @@ -1192,6 +1297,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, bfd_set_error (bfd_error_bad_value); return FALSE; + case R_X86_64_32: + if (ABI_64_P (abfd)) + goto not_pointer; case R_X86_64_64: h->non_got_ref = 1; h->pointer_equality_needed = 1; @@ -1202,16 +1310,16 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, make room for this reloc. */ sreloc = _bfd_elf_create_ifunc_dyn_reloc (abfd, info, sec, sreloc, - &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs); + &((struct elf_x86_64_link_hash_entry *) h)->dyn_relocs); if (sreloc == NULL) return FALSE; } break; case R_X86_64_32S: - case R_X86_64_32: case R_X86_64_PC32: case R_X86_64_PC64: +not_pointer: h->non_got_ref = 1; if (r_type != R_X86_64_PC32 && r_type != R_X86_64_PC64) @@ -1235,10 +1343,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, } } - if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL, - symtab_hdr, sym_hashes, - &r_type, GOT_UNKNOWN, - rel, rel_end, h, r_symndx)) + if (! elf_x86_64_tls_transition (info, abfd, sec, NULL, + symtab_hdr, sym_hashes, + &r_type, GOT_UNKNOWN, + rel, rel_end, h, r_symndx)) return FALSE; switch (r_type) @@ -1248,7 +1356,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, goto create_got; case R_X86_64_TPOFF32: - if (!info->executable) + if (!info->executable && ABI_64_P (abfd)) { if (h) name = h->root.root.string; @@ -1302,7 +1410,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, h->plt.refcount += 1; } h->got.refcount += 1; - old_tls_type = elf64_x86_64_hash_entry (h)->tls_type; + old_tls_type = elf_x86_64_hash_entry (h)->tls_type; } else { @@ -1322,14 +1430,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (local_got_refcounts == NULL) return FALSE; elf_local_got_refcounts (abfd) = local_got_refcounts; - elf64_x86_64_local_tlsdesc_gotent (abfd) + elf_x86_64_local_tlsdesc_gotent (abfd) = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info); - elf64_x86_64_local_got_tls_type (abfd) + elf_x86_64_local_got_tls_type (abfd) = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info); } local_got_refcounts[r_symndx] += 1; old_tls_type - = elf64_x86_64_local_got_tls_type (abfd) [r_symndx]; + = elf_x86_64_local_got_tls_type (abfd) [r_symndx]; } /* If a TLS symbol is accessed using IE at least once, @@ -1360,9 +1468,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (old_tls_type != tls_type) { if (h != NULL) - elf64_x86_64_hash_entry (h)->tls_type = tls_type; + elf_x86_64_hash_entry (h)->tls_type = tls_type; else - elf64_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type; + elf_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type; } } /* Fall through */ @@ -1408,9 +1516,11 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, } goto create_got; + case R_X86_64_32: + if (!ABI_64_P (abfd)) + goto pointer; case R_X86_64_8: case R_X86_64_16: - case R_X86_64_32: case R_X86_64_32S: /* Let's help debug shared library creation. These relocs cannot be used in shared libs. Don't error out for @@ -1437,6 +1547,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_PC32: case R_X86_64_PC64: case R_X86_64_64: +pointer: if (h != NULL && info->executable) { /* If this reloc is in a read-only section, we might @@ -1501,7 +1612,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, htab->elf.dynobj = abfd; sreloc = _bfd_elf_make_dynamic_reloc_section - (sec, htab->elf.dynobj, 3, abfd, /*rela?*/ TRUE); + (sec, htab->elf.dynobj, ABI_64_P (abfd) ? 3 : 2, + abfd, /*rela?*/ TRUE); if (sreloc == NULL) return FALSE; @@ -1511,7 +1623,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, relocations we need for this symbol. */ if (h != NULL) { - head = &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs; + head = &((struct elf_x86_64_link_hash_entry *) h)->dyn_relocs; } else { @@ -1586,14 +1698,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, relocation. */ static asection * -elf64_x86_64_gc_mark_hook (asection *sec, - struct bfd_link_info *info, - Elf_Internal_Rela *rel, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) +elf_x86_64_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - switch (ELF64_R_TYPE (rel->r_info)) + switch (ELF32_R_TYPE (rel->r_info)) { case R_X86_64_GNU_VTINHERIT: case R_X86_64_GNU_VTENTRY: @@ -1606,11 +1718,11 @@ elf64_x86_64_gc_mark_hook (asection *sec, /* Update the got entry reference counts for the section being removed. */ static bfd_boolean -elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) +elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; @@ -1619,7 +1731,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, if (info->relocatable) return TRUE; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -1629,6 +1741,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); + htab = elf_x86_64_hash_table (info); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { @@ -1636,18 +1749,39 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, unsigned int r_type; struct elf_link_hash_entry *h = NULL; - r_symndx = ELF64_R_SYM (rel->r_info); + r_symndx = htab->r_sym (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { - struct elf64_x86_64_link_hash_entry *eh; - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct elf64_x86_64_link_hash_entry *) h; + } + else + { + /* A local symbol. */ + Elf_Internal_Sym *isym; + + isym = bfd_sym_from_r_symndx (&htab->sym_cache, + abfd, r_symndx); + + /* Check relocation against local STT_GNU_IFUNC symbol. */ + if (isym != NULL + && ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) + { + h = elf_x86_64_get_local_sym_hash (htab, abfd, rel, FALSE); + if (h == NULL) + abort (); + } + } + + if (h) + { + struct elf_x86_64_link_hash_entry *eh; + struct elf_dyn_relocs **pp; + struct elf_dyn_relocs *p; + + eh = (struct elf_x86_64_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) if (p->sec == sec) @@ -1658,11 +1792,11 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, } } - r_type = ELF64_R_TYPE (rel->r_info); - if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL, - symtab_hdr, sym_hashes, - &r_type, GOT_UNKNOWN, - rel, relend, h, r_symndx)) + r_type = ELF32_R_TYPE (rel->r_info); + if (! elf_x86_64_tls_transition (info, abfd, sec, NULL, + symtab_hdr, sym_hashes, + &r_type, GOT_UNKNOWN, + rel, relend, h, r_symndx)) return FALSE; switch (r_type) @@ -1687,6 +1821,11 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, h->plt.refcount -= 1; if (h->got.refcount > 0) h->got.refcount -= 1; + if (h->type == STT_GNU_IFUNC) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } } else if (local_got_refcounts != NULL) { @@ -1704,7 +1843,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, case R_X86_64_PC16: case R_X86_64_PC32: case R_X86_64_PC64: - if (info->shared) + if (info->shared + && (h == NULL || h->type != STT_GNU_IFUNC)) break; /* Fall thru */ @@ -1732,10 +1872,10 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, understand. */ static bfd_boolean -elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) +elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; asection *s; /* STT_GNU_IFUNC symbol must go through PLT. */ @@ -1817,10 +1957,10 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS) { - struct elf64_x86_64_link_hash_entry * eh; + struct elf_x86_64_link_hash_entry * eh; struct elf_dyn_relocs *p; - eh = (struct elf64_x86_64_link_hash_entry *) h; + eh = (struct elf_x86_64_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { s = p->sec->output_section; @@ -1854,7 +1994,7 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, both the dynamic object and the regular object will refer to the same memory location for the variable. */ - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -1863,7 +2003,9 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, runtime process image. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { - htab->srelbss->size += sizeof (Elf64_External_Rela); + const struct elf_backend_data *bed; + bed = get_elf_backend_data (info->output_bfd); + htab->srelbss->size += bed->s->sizeof_rela; h->needs_copy = 1; } @@ -1876,24 +2018,26 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, dynamic relocs. */ static bfd_boolean -elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) +elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct bfd_link_info *info; - struct elf64_x86_64_link_hash_table *htab; - struct elf64_x86_64_link_hash_entry *eh; + struct elf_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_entry *eh; struct elf_dyn_relocs *p; + const struct elf_backend_data *bed; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct elf64_x86_64_link_hash_entry *) h; + eh = (struct elf_x86_64_link_hash_entry *) h; info = (struct bfd_link_info *) inf; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; + bed = get_elf_backend_data (info->output_bfd); /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ @@ -1947,7 +2091,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) htab->elf.sgotplt->size += GOT_ENTRY_SIZE; /* We also need to make an entry in the .rela.plt section. */ - htab->elf.srelplt->size += sizeof (Elf64_External_Rela); + htab->elf.srelplt->size += bed->s->sizeof_rela; htab->elf.srelplt->reloc_count++; } else @@ -1969,7 +2113,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) if (h->got.refcount > 0 && info->executable && h->dynindx == -1 - && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE) + && elf_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE) { h->got.offset = (bfd_vma) -1; } @@ -1977,7 +2121,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { asection *s; bfd_boolean dyn; - int tls_type = elf64_x86_64_hash_entry (h)->tls_type; + int tls_type = elf_x86_64_hash_entry (h)->tls_type; /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -1991,7 +2135,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) if (GOT_TLS_GDESC_P (tls_type)) { eh->tlsdesc_got = htab->elf.sgotplt->size - - elf64_x86_64_compute_jump_table_size (htab); + - elf_x86_64_compute_jump_table_size (htab); htab->elf.sgotplt->size += 2 * GOT_ENTRY_SIZE; h->got.offset = (bfd_vma) -2; } @@ -2010,18 +2154,18 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) R_X86_64_GOTTPOFF needs one dynamic relocation. */ if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) || tls_type == GOT_TLS_IE) - htab->elf.srelgot->size += sizeof (Elf64_External_Rela); + htab->elf.srelgot->size += bed->s->sizeof_rela; else if (GOT_TLS_GD_P (tls_type)) - htab->elf.srelgot->size += 2 * sizeof (Elf64_External_Rela); + htab->elf.srelgot->size += 2 * bed->s->sizeof_rela; else if (! GOT_TLS_GDESC_P (tls_type) && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) - htab->elf.srelgot->size += sizeof (Elf64_External_Rela); + htab->elf.srelgot->size += bed->s->sizeof_rela; if (GOT_TLS_GDESC_P (tls_type)) { - htab->elf.srelplt->size += sizeof (Elf64_External_Rela); + htab->elf.srelplt->size += bed->s->sizeof_rela; htab->tlsdesc_plt = (bfd_vma) -1; } } @@ -2117,7 +2261,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) BFD_ASSERT (sreloc != NULL); - sreloc->size += p->count * sizeof (Elf64_External_Rela); + sreloc->size += p->count * bed->s->sizeof_rela; } return TRUE; @@ -2127,7 +2271,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) local dynamic relocs. */ static bfd_boolean -elf64_x86_64_allocate_local_dynrelocs (void **slot, void *inf) +elf_x86_64_allocate_local_dynrelocs (void **slot, void *inf) { struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; @@ -2139,21 +2283,22 @@ elf64_x86_64_allocate_local_dynrelocs (void **slot, void *inf) || h->root.type != bfd_link_hash_defined) abort (); - return elf64_x86_64_allocate_dynrelocs (h, inf); + return elf_x86_64_allocate_dynrelocs (h, inf); } /* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean -elf64_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) +elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, + void * inf) { - struct elf64_x86_64_link_hash_entry *eh; + struct elf_x86_64_link_hash_entry *eh; struct elf_dyn_relocs *p; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct elf64_x86_64_link_hash_entry *) h; + eh = (struct elf_x86_64_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *s = p->sec->output_section; @@ -2174,18 +2319,20 @@ elf64_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* Set the sizes of the dynamic sections. */ static bfd_boolean -elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info) +elf_x86_64_size_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; bfd *dynobj; asection *s; bfd_boolean relocs; bfd *ibfd; + const struct elf_backend_data *bed; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; + bed = get_elf_backend_data (output_bfd); dynobj = htab->elf.dynobj; if (dynobj == NULL) @@ -2199,8 +2346,8 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, s = bfd_get_section_by_name (dynobj, ".interp"); if (s == NULL) abort (); - s->size = sizeof ELF_DYNAMIC_INTERPRETER; - s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; + s->size = htab->dynamic_interpreter_size; + s->contents = (unsigned char *) htab->dynamic_interpreter; } } @@ -2239,7 +2386,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, else if (p->count != 0) { srel = elf_section_data (p->sec)->sreloc; - srel->size += p->count * sizeof (Elf64_External_Rela); + srel->size += p->count * bed->s->sizeof_rela; if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; } @@ -2253,8 +2400,8 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, symtab_hdr = &elf_symtab_hdr (ibfd); locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; - local_tls_type = elf64_x86_64_local_got_tls_type (ibfd); - local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd); + local_tls_type = elf_x86_64_local_got_tls_type (ibfd); + local_tlsdesc_gotent = elf_x86_64_local_tlsdesc_gotent (ibfd); s = htab->elf.sgot; srel = htab->elf.srelgot; for (; local_got < end_local_got; @@ -2266,7 +2413,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (GOT_TLS_GDESC_P (*local_tls_type)) { *local_tlsdesc_gotent = htab->elf.sgotplt->size - - elf64_x86_64_compute_jump_table_size (htab); + - elf_x86_64_compute_jump_table_size (htab); htab->elf.sgotplt->size += 2 * GOT_ENTRY_SIZE; *local_got = (bfd_vma) -2; } @@ -2285,12 +2432,12 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (GOT_TLS_GDESC_P (*local_tls_type)) { htab->elf.srelplt->size - += sizeof (Elf64_External_Rela); + += bed->s->sizeof_rela; htab->tlsdesc_plt = (bfd_vma) -1; } if (! GOT_TLS_GDESC_P (*local_tls_type) || GOT_TLS_GD_P (*local_tls_type)) - srel->size += sizeof (Elf64_External_Rela); + srel->size += bed->s->sizeof_rela; } } else @@ -2304,19 +2451,19 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, relocs. */ htab->tls_ld_got.offset = htab->elf.sgot->size; htab->elf.sgot->size += 2 * GOT_ENTRY_SIZE; - htab->elf.srelgot->size += sizeof (Elf64_External_Rela); + htab->elf.srelgot->size += bed->s->sizeof_rela; } else htab->tls_ld_got.offset = -1; /* Allocate global sym .plt and .got entries, and space for global sym dynamic relocs. */ - elf_link_hash_traverse (&htab->elf, elf64_x86_64_allocate_dynrelocs, + elf_link_hash_traverse (&htab->elf, elf_x86_64_allocate_dynrelocs, info); /* Allocate .plt and .got entries, and space for local symbols. */ htab_traverse (htab->loc_hash_table, - elf64_x86_64_allocate_local_dynrelocs, + elf_x86_64_allocate_local_dynrelocs, info); /* For every jump slot reserved in the sgotplt, reloc_count is @@ -2326,7 +2473,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, slot size. */ if (htab->elf.srelplt) htab->sgotplt_jump_table_size - = elf64_x86_64_compute_jump_table_size (htab); + = elf_x86_64_compute_jump_table_size (htab); if (htab->tlsdesc_plt) { @@ -2347,6 +2494,30 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } } + if (htab->elf.sgotplt) + { + struct elf_link_hash_entry *got; + got = elf_link_hash_lookup (elf_hash_table (info), + "_GLOBAL_OFFSET_TABLE_", + FALSE, FALSE, FALSE); + + /* Don't allocate .got.plt section if there are no GOT nor PLT + entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */ + if ((got == NULL + || !got->ref_regular_nonweak) + && (htab->elf.sgotplt->size + == get_elf_backend_data (output_bfd)->got_header_size) + && (htab->elf.splt == NULL + || htab->elf.splt->size == 0) + && (htab->elf.sgot == NULL + || htab->elf.sgot->size == 0) + && (htab->elf.iplt == NULL + || htab->elf.iplt->size == 0) + && (htab->elf.igotplt == NULL + || htab->elf.igotplt->size == 0)) + htab->elf.sgotplt->size = 0; + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -2413,7 +2584,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the - values later, in elf64_x86_64_finish_dynamic_sections, but we + values later, in elf_x86_64_finish_dynamic_sections, but we must add the entries now so that we get the correct size for the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ @@ -2444,14 +2615,14 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { if (!add_dynamic_entry (DT_RELA, 0) || !add_dynamic_entry (DT_RELASZ, 0) - || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) + || !add_dynamic_entry (DT_RELAENT, bed->s->sizeof_rela)) 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->elf, - elf64_x86_64_readonly_dynrelocs, + elf_x86_64_readonly_dynrelocs, info); if ((info->flags & DF_TEXTREL) != 0) @@ -2467,8 +2638,8 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } static bfd_boolean -elf64_x86_64_always_size_sections (bfd *output_bfd, - struct bfd_link_info *info) +elf_x86_64_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) { asection *tls_sec = elf_hash_table (info)->tls_sec; @@ -2482,12 +2653,12 @@ elf64_x86_64_always_size_sections (bfd *output_bfd, if (tlsbase && tlsbase->type == STT_TLS) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; struct bfd_link_hash_entry *bh = NULL; const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -2515,15 +2686,15 @@ elf64_x86_64_always_size_sections (bfd *output_bfd, multiple times, it is idempotent. */ static void -elf64_x86_64_set_tls_module_base (struct bfd_link_info *info) +elf_x86_64_set_tls_module_base (struct bfd_link_info *info) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; struct bfd_link_hash_entry *base; if (!info->executable) return; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return; @@ -2539,7 +2710,7 @@ elf64_x86_64_set_tls_module_base (struct bfd_link_info *info) This is PT_TLS segment p_vaddr. */ static bfd_vma -elf64_x86_64_dtpoff_base (struct bfd_link_info *info) +elf_x86_64_dtpoff_base (struct bfd_link_info *info) { /* If tls_sec is NULL, we should have signalled an error already. */ if (elf_hash_table (info)->tls_sec == NULL) @@ -2551,14 +2722,19 @@ elf64_x86_64_dtpoff_base (struct bfd_link_info *info) if STT_TLS virtual address is ADDRESS. */ static bfd_vma -elf64_x86_64_tpoff (struct bfd_link_info *info, bfd_vma address) +elf_x86_64_tpoff (struct bfd_link_info *info, bfd_vma address) { struct elf_link_hash_table *htab = elf_hash_table (info); + const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd); + bfd_vma static_tls_size; /* If tls_segment is NULL, we should have signalled an error already. */ if (htab->tls_sec == NULL) return 0; - return address - htab->tls_size - htab->tls_sec->vma; + + /* Consider special static TLS alignment requirements. */ + static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment); + return address - static_tls_size - htab->tls_sec->vma; } /* Is the instruction before OFFSET in CONTENTS a 32bit relative @@ -2579,26 +2755,19 @@ is_32bit_relative_branch (bfd_byte *contents, bfd_vma offset) && (contents [offset - 1] & 0xf0) == 0x80)); } -static void -elf64_x86_64_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) -{ - bfd_byte *loc = s->contents; - loc += s->reloc_count++ * sizeof (Elf64_External_Rela); - BFD_ASSERT (loc + sizeof (Elf64_External_Rela) - <= s->contents + s->size); - bfd_elf64_swap_reloca_out (abfd, rel, loc); -} - /* Relocate an x86_64 ELF section. */ static bfd_boolean -elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, - bfd *input_bfd, asection *input_section, - bfd_byte *contents, Elf_Internal_Rela *relocs, - Elf_Internal_Sym *local_syms, - asection **local_sections) +elf_x86_64_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; @@ -2608,15 +2777,15 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (is_x86_64_elf (input_bfd)); - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; symtab_hdr = &elf_symtab_hdr (input_bfd); sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); - local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd); + local_tlsdesc_gotents = elf_x86_64_local_tlsdesc_gotent (input_bfd); - elf64_x86_64_set_tls_module_base (info); + elf_x86_64_set_tls_module_base (info); rel = relocs; relend = relocs + input_section->reloc_count; @@ -2635,7 +2804,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, int tls_type; asection *base_got; - r_type = ELF64_R_TYPE (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_X86_64_GNU_VTINHERIT || r_type == (int) R_X86_64_GNU_VTENTRY) continue; @@ -2647,7 +2816,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } howto = x86_64_elf_howto_table + r_type; - r_symndx = ELF64_R_SYM (rel->r_info); + r_symndx = htab->r_sym (rel->r_info); h = NULL; sym = NULL; sec = NULL; @@ -2662,10 +2831,10 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, /* Relocate against local STT_GNU_IFUNC symbol. */ if (!info->relocatable - && ELF64_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { - h = elf64_x86_64_get_local_sym_hash (htab, input_bfd, - rel, FALSE); + h = elf_x86_64_get_local_sym_hash (htab, input_bfd, + rel, FALSE); if (h == NULL) abort (); @@ -2731,6 +2900,10 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, abort (); goto do_relocation; + case R_X86_64_32: + if (ABI_64_P (output_bfd)) + goto do_relocation; + /* FALLTHROUGH */ case R_X86_64_64: if (rel->r_addend != 0) { @@ -2773,19 +2946,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, || info->executable) { /* This symbol is resolved locally. */ - outrel.r_info = ELF64_R_INFO (0, R_X86_64_IRELATIVE); + outrel.r_info = htab->r_info (0, R_X86_64_IRELATIVE); outrel.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); } else { - outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); + outrel.r_info = htab->r_info (h->dynindx, r_type); outrel.r_addend = 0; } sreloc = htab->elf.irelifunc; - elf64_x86_64_append_rela (output_bfd, sreloc, &outrel); + elf_append_rela (output_bfd, sreloc, &outrel); /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, @@ -2794,8 +2967,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, internal symbol, we have updated addend. */ continue; } - - case R_X86_64_32: + /* FALLTHROUGH */ case R_X86_64_PC32: case R_X86_64_PC64: case R_X86_64_PLT32: @@ -2857,18 +3029,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, relocation = (base_got->output_section->vma + base_got->output_offset + off); - if (r_type != R_X86_64_GOTPCREL - && r_type != R_X86_64_GOTPCREL64) - { - asection *gotplt; - if (htab->elf.splt != NULL) - gotplt = htab->elf.sgotplt; - else - gotplt = htab->elf.igotplt; - relocation -= (gotplt->output_section->vma - - gotplt->output_offset); - } - goto do_relocation; } } @@ -2978,9 +3138,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, outrel.r_offset = (base_got->output_section->vma + base_got->output_offset + off); - outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); + outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); outrel.r_addend = relocation; - elf64_x86_64_append_rela (output_bfd, s, &outrel); + elf_append_rela (output_bfd, s, &outrel); } local_got_offsets[r_symndx] |= 1; @@ -3081,6 +3241,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_X86_64_PC16: case R_X86_64_PC32: if (info->shared + && ABI_64_P (output_bfd) && (input_section->flags & SEC_ALLOC) != 0 && (input_section->flags & SEC_READONLY) != 0 && h != NULL) @@ -3201,16 +3362,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, || ! SYMBOLIC_BIND (info, h) || ! h->def_regular)) { - outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); + outrel.r_info = htab->r_info (h->dynindx, r_type); outrel.r_addend = rel->r_addend; } else { /* This symbol is local, or marked to become local. */ - if (r_type == R_X86_64_64) + if (r_type == htab->pointer_r_type) { relocate = TRUE; - outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); + outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); outrel.r_addend = relocation + rel->r_addend; } else @@ -3243,7 +3404,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (sindx != 0); } - outrel.r_info = ELF64_R_INFO (sindx, r_type); + outrel.r_info = htab->r_info (sindx, r_type); outrel.r_addend = relocation + rel->r_addend; } } @@ -3252,7 +3413,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL); - elf64_x86_64_append_rela (output_bfd, sreloc, &outrel); + elf_append_rela (output_bfd, sreloc, &outrel); /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -3270,15 +3431,15 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_X86_64_GOTTPOFF: tls_type = GOT_UNKNOWN; if (h == NULL && local_got_offsets) - tls_type = elf64_x86_64_local_got_tls_type (input_bfd) [r_symndx]; + tls_type = elf_x86_64_local_got_tls_type (input_bfd) [r_symndx]; else if (h != NULL) - tls_type = elf64_x86_64_hash_entry (h)->tls_type; + tls_type = elf_x86_64_hash_entry (h)->tls_type; - if (! elf64_x86_64_tls_transition (info, input_bfd, - input_section, contents, - symtab_hdr, sym_hashes, - &r_type, tls_type, rel, - relend, h, r_symndx)) + if (! elf_x86_64_tls_transition (info, input_bfd, + input_section, contents, + symtab_hdr, sym_hashes, + &r_type, tls_type, rel, + relend, h, r_symndx)) return FALSE; if (r_type == R_X86_64_TPOFF32) @@ -3287,25 +3448,36 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (! unresolved_reloc); - if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD) + if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD) { - /* GD->LE transition. + /* GD->LE transition. For 64bit, change .byte 0x66; leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr - Change it into: + into: movq %fs:0, %rax + leaq foo@tpoff(%rax), %rax + For 32bit, change + leaq foo@tlsgd(%rip), %rdi + .word 0x6666; rex64; call __tls_get_addr + into: + movl %fs:0, %eax leaq foo@tpoff(%rax), %rax */ - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", - 16); + if (ABI_64_P (output_bfd)) + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 16); + else + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 15); bfd_put_32 (output_bfd, - elf64_x86_64_tpoff (info, relocation), + elf_x86_64_tpoff (info, relocation), contents + roff + 8); /* Skip R_X86_64_PC32/R_X86_64_PLT32. */ rel++; continue; } - else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) + else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) { /* GDesc -> LE transition. It's originally something like: @@ -3324,11 +3496,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7), contents + roff - 1); bfd_put_32 (output_bfd, - elf64_x86_64_tpoff (info, relocation), + elf_x86_64_tpoff (info, relocation), contents + roff); continue; } - else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) + else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) { /* GDesc -> LE transition. It's originally: @@ -3339,7 +3511,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd_put_8 (output_bfd, 0x90, contents + roff + 1); continue; } - else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTTPOFF) + else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTTPOFF) { /* IE->LE transition: Originally it can be one of: @@ -3362,6 +3534,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (val == 0x4c) bfd_put_8 (output_bfd, 0x49, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3374,6 +3549,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (val == 0x4c) bfd_put_8 (output_bfd, 0x49, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); bfd_put_8 (output_bfd, 0x81, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3385,13 +3563,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (val == 0x4c) bfd_put_8 (output_bfd, 0x4d, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x45, + contents + roff - 3); bfd_put_8 (output_bfd, 0x8d, contents + roff - 2); bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3), contents + roff - 1); } bfd_put_32 (output_bfd, - elf64_x86_64_tpoff (info, relocation), + elf_x86_64_tpoff (info, relocation), contents + roff); continue; } @@ -3405,7 +3586,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (h != NULL) { off = h->got.offset; - offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got; + offplt = elf_x86_64_hash_entry (h)->tlsdesc_got; } else { @@ -3431,7 +3612,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (GOT_TLS_GDESC_P (tls_type)) { - outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC); + outrel.r_info = htab->r_info (indx, R_X86_64_TLSDESC); BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 2 * GOT_ENTRY_SIZE <= htab->elf.sgotplt->size); outrel.r_offset = (htab->elf.sgotplt->output_section->vma @@ -3440,10 +3621,10 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, + htab->sgotplt_jump_table_size); sreloc = htab->elf.srelplt; if (indx == 0) - outrel.r_addend = relocation - elf64_x86_64_dtpoff_base (info); + outrel.r_addend = relocation - elf_x86_64_dtpoff_base (info); else outrel.r_addend = 0; - elf64_x86_64_append_rela (output_bfd, sreloc, &outrel); + elf_append_rela (output_bfd, sreloc, &outrel); } sreloc = htab->elf.srelgot; @@ -3462,10 +3643,10 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, outrel.r_addend = 0; if ((dr_type == R_X86_64_TPOFF64 || dr_type == R_X86_64_TLSDESC) && indx == 0) - outrel.r_addend = relocation - elf64_x86_64_dtpoff_base (info); - outrel.r_info = ELF64_R_INFO (indx, dr_type); + outrel.r_addend = relocation - elf_x86_64_dtpoff_base (info); + outrel.r_info = htab->r_info (indx, dr_type); - elf64_x86_64_append_rela (output_bfd, sreloc, &outrel); + elf_append_rela (output_bfd, sreloc, &outrel); if (GOT_TLS_GD_P (tls_type)) { @@ -3473,17 +3654,17 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, { BFD_ASSERT (! unresolved_reloc); bfd_put_64 (output_bfd, - relocation - elf64_x86_64_dtpoff_base (info), + relocation - elf_x86_64_dtpoff_base (info), htab->elf.sgot->contents + off + GOT_ENTRY_SIZE); } else { bfd_put_64 (output_bfd, 0, htab->elf.sgot->contents + off + GOT_ENTRY_SIZE); - outrel.r_info = ELF64_R_INFO (indx, + outrel.r_info = htab->r_info (indx, R_X86_64_DTPOFF64); outrel.r_offset += GOT_ENTRY_SIZE; - elf64_x86_64_append_rela (output_bfd, sreloc, + elf_append_rela (output_bfd, sreloc, &outrel); } } @@ -3498,7 +3679,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (off >= (bfd_vma) -2 && ! GOT_TLS_GDESC_P (tls_type)) abort (); - if (r_type == ELF64_R_TYPE (rel->r_info)) + if (r_type == ELF32_R_TYPE (rel->r_info)) { if (r_type == R_X86_64_GOTPC32_TLSDESC || r_type == R_X86_64_TLSDESC_CALL) @@ -3514,17 +3695,28 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, { bfd_vma roff = rel->r_offset; - if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD) + if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD) { - /* GD->IE transition. + /* GD->IE transition. For 64bit, change .byte 0x66; leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr@plt - Change it into: + into: movq %fs:0, %rax + addq foo@gottpoff(%rip), %rax + For 32bit, change + leaq foo@tlsgd(%rip), %rdi + .word 0x6666; rex64; call __tls_get_addr@plt + into: + movl %fs:0, %eax addq foo@gottpoff(%rip), %rax */ - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", - 16); + if (ABI_64_P (output_bfd)) + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 16); + else + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 15); relocation = (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off @@ -3538,7 +3730,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, rel++; continue; } - else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) + else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) { /* GDesc -> IE transition. It's originally something like: @@ -3563,7 +3755,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, contents + roff); continue; } - else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) + else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) { /* GDesc -> IE transition. It's originally: @@ -3582,23 +3774,29 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, break; case R_X86_64_TLSLD: - if (! elf64_x86_64_tls_transition (info, input_bfd, - input_section, contents, - symtab_hdr, sym_hashes, - &r_type, GOT_UNKNOWN, - rel, relend, h, r_symndx)) + if (! elf_x86_64_tls_transition (info, input_bfd, + input_section, contents, + symtab_hdr, sym_hashes, + &r_type, GOT_UNKNOWN, + rel, relend, h, r_symndx)) return FALSE; if (r_type != R_X86_64_TLSLD) { /* LD->LE transition: leaq foo@tlsld(%rip), %rdi; call __tls_get_addr. - We change it into: - .word 0x6666; .byte 0x66; movl %fs:0, %rax. */ + For 64bit, we change it into: + .word 0x6666; .byte 0x66; movq %fs:0, %rax. + For 32bit, we change it into: + nopl 0x0(%rax); movl %fs:0, %eax. */ BFD_ASSERT (r_type == R_X86_64_TPOFF32); - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + if (ABI_64_P (output_bfd)) + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + else + memcpy (contents + rel->r_offset - 3, + "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); /* Skip R_X86_64_PC32/R_X86_64_PLT32. */ rel++; continue; @@ -3624,9 +3822,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, htab->elf.sgot->contents + off); bfd_put_64 (output_bfd, 0, htab->elf.sgot->contents + off + GOT_ENTRY_SIZE); - outrel.r_info = ELF64_R_INFO (0, R_X86_64_DTPMOD64); + outrel.r_info = htab->r_info (0, R_X86_64_DTPMOD64); outrel.r_addend = 0; - elf64_x86_64_append_rela (output_bfd, htab->elf.srelgot, + elf_append_rela (output_bfd, htab->elf.srelgot, &outrel); htab->tls_ld_got.offset |= 1; } @@ -3637,14 +3835,14 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_X86_64_DTPOFF32: if (!info->executable|| (input_section->flags & SEC_CODE) == 0) - relocation -= elf64_x86_64_dtpoff_base (info); + relocation -= elf_x86_64_dtpoff_base (info); else - relocation = elf64_x86_64_tpoff (info, relocation); + relocation = elf_x86_64_tpoff (info, relocation); break; case R_X86_64_TPOFF32: BFD_ASSERT (info->executable); - relocation = elf64_x86_64_tpoff (info, relocation); + relocation = elf_x86_64_tpoff (info, relocation); break; default: @@ -3713,14 +3911,14 @@ do_relocation: dynamic sections here. */ static bfd_boolean -elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, - struct bfd_link_info *info, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) +elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -3731,6 +3929,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Rela rela; bfd_byte *loc; asection *plt, *gotplt, *relplt; + const struct elf_backend_data *bed; /* When building a static executable, use .iplt, .igot.plt and .rela.iplt sections for STT_GNU_IFUNC symbols. */ @@ -3781,7 +3980,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, } /* Fill in the entry in the procedure linkage table. */ - memcpy (plt->contents + h->plt.offset, elf64_x86_64_plt_entry, + memcpy (plt->contents + h->plt.offset, elf_x86_64_plt_entry, PLT_ENTRY_SIZE); /* Insert the relocation positions of the plt section. The magic @@ -3829,18 +4028,20 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, { /* If an STT_GNU_IFUNC symbol is locally defined, generate R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT. */ - rela.r_info = ELF64_R_INFO (0, R_X86_64_IRELATIVE); + rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE); rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); } else { - rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT); + rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT); rela.r_addend = 0; } - loc = relplt->contents + plt_index * sizeof (Elf64_External_Rela); - bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); + + bed = get_elf_backend_data (output_bfd); + loc = relplt->contents + plt_index * bed->s->sizeof_rela; + bed->s->swap_reloca_out (output_bfd, &rela, loc); if (!h->def_regular) { @@ -3859,8 +4060,8 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, } if (h->got.offset != (bfd_vma) -1 - && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type) - && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE) + && ! GOT_TLS_GD_ANY_P (elf_x86_64_hash_entry (h)->tls_type) + && elf_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE) { Elf_Internal_Rela rela; @@ -3910,7 +4111,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, if (!h->def_regular) return FALSE; BFD_ASSERT((h->got.offset & 1) != 0); - rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); + rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); @@ -3921,11 +4122,11 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, do_glob_dat: bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset); - rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT); + rela.r_info = htab->r_info (h->dynindx, R_X86_64_GLOB_DAT); rela.r_addend = 0; } - elf64_x86_64_append_rela (output_bfd, htab->elf.srelgot, &rela); + elf_append_rela (output_bfd, htab->elf.srelgot, &rela); } if (h->needs_copy) @@ -3943,9 +4144,9 @@ do_glob_dat: rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); - rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY); + rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY); rela.r_addend = 0; - elf64_x86_64_append_rela (output_bfd, htab->srelbss, &rela); + elf_append_rela (output_bfd, htab->srelbss, &rela); } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. SYM may @@ -3962,14 +4163,14 @@ do_glob_dat: various dynamic sections here. */ static bfd_boolean -elf64_x86_64_finish_local_dynamic_symbol (void **slot, void *inf) +elf_x86_64_finish_local_dynamic_symbol (void **slot, void *inf) { struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; struct bfd_link_info *info = (struct bfd_link_info *) inf; - return elf64_x86_64_finish_dynamic_symbol (info->output_bfd, + return elf_x86_64_finish_dynamic_symbol (info->output_bfd, info, h, NULL); } @@ -3977,9 +4178,9 @@ elf64_x86_64_finish_local_dynamic_symbol (void **slot, void *inf) dynamic linker, before writing them out. */ static enum elf_reloc_type_class -elf64_x86_64_reloc_type_class (const Elf_Internal_Rela *rela) +elf_x86_64_reloc_type_class (const Elf_Internal_Rela *rela) { - switch ((int) ELF64_R_TYPE (rela->r_info)) + switch ((int) ELF32_R_TYPE (rela->r_info)) { case R_X86_64_RELATIVE: return reloc_class_relative; @@ -3995,13 +4196,14 @@ elf64_x86_64_reloc_type_class (const Elf_Internal_Rela *rela) /* Finish up the dynamic sections. */ static bfd_boolean -elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) +elf_x86_64_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) { - struct elf64_x86_64_link_hash_table *htab; + struct elf_x86_64_link_hash_table *htab; bfd *dynobj; asection *sdyn; - htab = elf64_x86_64_hash_table (info); + htab = elf_x86_64_hash_table (info); if (htab == NULL) return FALSE; @@ -4010,19 +4212,23 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf if (htab->elf.dynamic_sections_created) { - Elf64_External_Dyn *dyncon, *dynconend; + bfd_byte *dyncon, *dynconend; + const struct elf_backend_data *bed; + bfd_size_type sizeof_dyn; if (sdyn == NULL || htab->elf.sgot == NULL) abort (); - dyncon = (Elf64_External_Dyn *) sdyn->contents; - dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); - for (; dyncon < dynconend; dyncon++) + bed = get_elf_backend_data (dynobj); + sizeof_dyn = bed->s->sizeof_dyn; + dyncon = sdyn->contents; + dynconend = sdyn->contents + sdyn->size; + for (; dyncon < dynconend; dyncon += sizeof_dyn) { Elf_Internal_Dyn dyn; asection *s; - bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); + (*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn); switch (dyn.d_tag) { @@ -4071,14 +4277,14 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf break; } - bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); + (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); } /* Fill in the special first entry in the procedure linkage table. */ if (htab->elf.splt && htab->elf.splt->size > 0) { /* Fill in the first entry in the procedure linkage table. */ - memcpy (htab->elf.splt->contents, elf64_x86_64_plt0_entry, + memcpy (htab->elf.splt->contents, elf_x86_64_plt0_entry, PLT_ENTRY_SIZE); /* Add offset for pushq GOT+8(%rip), since the instruction uses 6 bytes subtract this value. */ @@ -4110,7 +4316,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf htab->elf.sgot->contents + htab->tlsdesc_got); memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, - elf64_x86_64_plt0_entry, + elf_x86_64_plt0_entry, PLT_ENTRY_SIZE); /* Add offset for pushq GOT+8(%rip), since the @@ -4142,6 +4348,13 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf if (htab->elf.sgotplt) { + if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) + { + (*_bfd_error_handler) + (_("discarded output section: `%A'"), htab->elf.sgotplt); + return FALSE; + } + /* Fill in the first three entries in the global offset table. */ if (htab->elf.sgotplt->size > 0) { @@ -4168,7 +4381,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ htab_traverse (htab->loc_hash_table, - elf64_x86_64_finish_local_dynamic_symbol, + elf_x86_64_finish_local_dynamic_symbol, info); return TRUE; @@ -4178,8 +4391,8 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf or (bfd_vma) -1 if it should not be included. */ static bfd_vma -elf64_x86_64_plt_sym_val (bfd_vma i, const asection *plt, - const arelent *rel ATTRIBUTE_UNUSED) +elf_x86_64_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) { return plt->vma + (i + 1) * PLT_ENTRY_SIZE; } @@ -4188,7 +4401,7 @@ elf64_x86_64_plt_sym_val (bfd_vma i, const asection *plt, is called when elfcode.h finds a section with an unknown type. */ static bfd_boolean -elf64_x86_64_section_from_shdr (bfd *abfd, +elf_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, int shindex) @@ -4207,13 +4420,13 @@ elf64_x86_64_section_from_shdr (bfd *abfd, of .bss. */ static bfd_boolean -elf64_x86_64_add_symbol_hook (bfd *abfd, - struct bfd_link_info *info, - Elf_Internal_Sym *sym, - const char **namep ATTRIBUTE_UNUSED, - flagword *flagsp ATTRIBUTE_UNUSED, - asection **secp, - bfd_vma *valp) +elf_x86_64_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) { asection *lcomm; @@ -4249,8 +4462,8 @@ elf64_x86_64_add_symbol_hook (bfd *abfd, index. */ static bfd_boolean -elf64_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, - asection *sec, int *index_return) +elf_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, int *index_return) { if (sec == &_bfd_elf_large_com_section) { @@ -4263,8 +4476,8 @@ elf64_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, /* Process a symbol. */ static void -elf64_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, - asymbol *asym) +elf_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, + asymbol *asym) { elf_symbol_type *elfsym = (elf_symbol_type *) asym; @@ -4280,14 +4493,14 @@ elf64_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, } static bfd_boolean -elf64_x86_64_common_definition (Elf_Internal_Sym *sym) +elf_x86_64_common_definition (Elf_Internal_Sym *sym) { return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_X86_64_LCOMMON); } static unsigned int -elf64_x86_64_common_section_index (asection *sec) +elf_x86_64_common_section_index (asection *sec) { if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0) return SHN_COMMON; @@ -4296,7 +4509,7 @@ elf64_x86_64_common_section_index (asection *sec) } static asection * -elf64_x86_64_common_section (asection *sec) +elf_x86_64_common_section (asection *sec) { if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0) return bfd_com_section_ptr; @@ -4305,29 +4518,29 @@ elf64_x86_64_common_section (asection *sec) } static bfd_boolean -elf64_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, - struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym, - asection **psec, - bfd_vma *pvalue ATTRIBUTE_UNUSED, - unsigned int *pold_alignment ATTRIBUTE_UNUSED, - bfd_boolean *skip ATTRIBUTE_UNUSED, - bfd_boolean *override ATTRIBUTE_UNUSED, - bfd_boolean *type_change_ok ATTRIBUTE_UNUSED, - bfd_boolean *size_change_ok ATTRIBUTE_UNUSED, - bfd_boolean *newdef ATTRIBUTE_UNUSED, - bfd_boolean *newdyn, - bfd_boolean *newdyncommon ATTRIBUTE_UNUSED, - bfd_boolean *newweak ATTRIBUTE_UNUSED, - bfd *abfd ATTRIBUTE_UNUSED, - asection **sec, - bfd_boolean *olddef ATTRIBUTE_UNUSED, - bfd_boolean *olddyn, - bfd_boolean *olddyncommon ATTRIBUTE_UNUSED, - bfd_boolean *oldweak ATTRIBUTE_UNUSED, - bfd *oldbfd, - asection **oldsec) +elf_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym, + asection **psec, + bfd_vma *pvalue ATTRIBUTE_UNUSED, + unsigned int *pold_alignment ATTRIBUTE_UNUSED, + bfd_boolean *skip ATTRIBUTE_UNUSED, + bfd_boolean *override ATTRIBUTE_UNUSED, + bfd_boolean *type_change_ok ATTRIBUTE_UNUSED, + bfd_boolean *size_change_ok ATTRIBUTE_UNUSED, + bfd_boolean *newdef ATTRIBUTE_UNUSED, + bfd_boolean *newdyn, + bfd_boolean *newdyncommon ATTRIBUTE_UNUSED, + bfd_boolean *newweak ATTRIBUTE_UNUSED, + bfd *abfd ATTRIBUTE_UNUSED, + asection **sec, + bfd_boolean *olddef ATTRIBUTE_UNUSED, + bfd_boolean *olddyn, + bfd_boolean *olddyncommon ATTRIBUTE_UNUSED, + bfd_boolean *oldweak ATTRIBUTE_UNUSED, + bfd *oldbfd, + asection **oldsec) { /* A normal common symbol and a large common symbol result in a normal common symbol. We turn the large common symbol into a @@ -4354,8 +4567,8 @@ elf64_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, } static int -elf64_x86_64_additional_program_headers (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED) +elf_x86_64_additional_program_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { asection *s; int count = 0; @@ -4378,7 +4591,7 @@ elf64_x86_64_additional_program_headers (bfd *abfd, /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ static bfd_boolean -elf64_x86_64_hash_symbol (struct elf_link_hash_entry *h) +elf_x86_64_hash_symbol (struct elf_link_hash_entry *h) { if (h->plt.offset != (bfd_vma) -1 && !h->def_regular @@ -4388,8 +4601,19 @@ elf64_x86_64_hash_symbol (struct elf_link_hash_entry *h) return _bfd_elf_hash_symbol (h); } +/* Return TRUE iff relocations for INPUT are compatible with OUTPUT. */ + +static bfd_boolean +elf_x86_64_relocs_compatible (const bfd_target *input, + const bfd_target *output) +{ + return ((xvec_get_elf_backend_data (input)->s->elfclass + == xvec_get_elf_backend_data (output)->s->elfclass) + && _bfd_elf_relocs_compatible (input, output)); +} + static const struct bfd_elf_special_section - elf64_x86_64_special_sections[]= + elf_x86_64_special_sections[]= { { STRING_COMMA_LEN (".gnu.linkonce.lb"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE}, { STRING_COMMA_LEN (".gnu.linkonce.lr"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE}, @@ -4403,6 +4627,7 @@ static const struct bfd_elf_special_section #define TARGET_LITTLE_SYM bfd_elf64_x86_64_vec #define TARGET_LITTLE_NAME "elf64-x86-64" #define ELF_ARCH bfd_arch_i386 +#define ELF_TARGET_ID X86_64_ELF_DATA #define ELF_MACHINE_CODE EM_X86_64 #define ELF_MAXPAGESIZE 0x200000 #define ELF_MINPAGESIZE 0x1000 @@ -4416,59 +4641,59 @@ static const struct bfd_elf_special_section #define elf_backend_got_header_size (GOT_ENTRY_SIZE*3) #define elf_backend_rela_normal 1 -#define elf_info_to_howto elf64_x86_64_info_to_howto +#define elf_info_to_howto elf_x86_64_info_to_howto #define bfd_elf64_bfd_link_hash_table_create \ - elf64_x86_64_link_hash_table_create + elf_x86_64_link_hash_table_create #define bfd_elf64_bfd_link_hash_table_free \ - elf64_x86_64_link_hash_table_free -#define bfd_elf64_bfd_reloc_type_lookup elf64_x86_64_reloc_type_lookup + elf_x86_64_link_hash_table_free +#define bfd_elf64_bfd_reloc_type_lookup elf_x86_64_reloc_type_lookup #define bfd_elf64_bfd_reloc_name_lookup \ - elf64_x86_64_reloc_name_lookup - -#define elf_backend_adjust_dynamic_symbol elf64_x86_64_adjust_dynamic_symbol -#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible -#define elf_backend_check_relocs elf64_x86_64_check_relocs -#define elf_backend_copy_indirect_symbol elf64_x86_64_copy_indirect_symbol -#define elf_backend_create_dynamic_sections elf64_x86_64_create_dynamic_sections -#define elf_backend_finish_dynamic_sections elf64_x86_64_finish_dynamic_sections -#define elf_backend_finish_dynamic_symbol elf64_x86_64_finish_dynamic_symbol -#define elf_backend_gc_mark_hook elf64_x86_64_gc_mark_hook -#define elf_backend_gc_sweep_hook elf64_x86_64_gc_sweep_hook -#define elf_backend_grok_prstatus elf64_x86_64_grok_prstatus -#define elf_backend_grok_psinfo elf64_x86_64_grok_psinfo -#define elf_backend_reloc_type_class elf64_x86_64_reloc_type_class -#define elf_backend_relocate_section elf64_x86_64_relocate_section -#define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections -#define elf_backend_always_size_sections elf64_x86_64_always_size_sections + elf_x86_64_reloc_name_lookup + +#define elf_backend_adjust_dynamic_symbol elf_x86_64_adjust_dynamic_symbol +#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible +#define elf_backend_check_relocs elf_x86_64_check_relocs +#define elf_backend_copy_indirect_symbol elf_x86_64_copy_indirect_symbol +#define elf_backend_create_dynamic_sections elf_x86_64_create_dynamic_sections +#define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections +#define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol +#define elf_backend_gc_mark_hook elf_x86_64_gc_mark_hook +#define elf_backend_gc_sweep_hook elf_x86_64_gc_sweep_hook +#define elf_backend_grok_prstatus elf_x86_64_grok_prstatus +#define elf_backend_grok_psinfo elf_x86_64_grok_psinfo +#define elf_backend_reloc_type_class elf_x86_64_reloc_type_class +#define elf_backend_relocate_section elf_x86_64_relocate_section +#define elf_backend_size_dynamic_sections elf_x86_64_size_dynamic_sections +#define elf_backend_always_size_sections elf_x86_64_always_size_sections #define elf_backend_init_index_section _bfd_elf_init_1_index_section -#define elf_backend_plt_sym_val elf64_x86_64_plt_sym_val +#define elf_backend_plt_sym_val elf_x86_64_plt_sym_val #define elf_backend_object_p elf64_x86_64_elf_object_p -#define bfd_elf64_mkobject elf64_x86_64_mkobject +#define bfd_elf64_mkobject elf_x86_64_mkobject #define elf_backend_section_from_shdr \ - elf64_x86_64_section_from_shdr + elf_x86_64_section_from_shdr #define elf_backend_section_from_bfd_section \ - elf64_x86_64_elf_section_from_bfd_section + elf_x86_64_elf_section_from_bfd_section #define elf_backend_add_symbol_hook \ - elf64_x86_64_add_symbol_hook + elf_x86_64_add_symbol_hook #define elf_backend_symbol_processing \ - elf64_x86_64_symbol_processing + elf_x86_64_symbol_processing #define elf_backend_common_section_index \ - elf64_x86_64_common_section_index + elf_x86_64_common_section_index #define elf_backend_common_section \ - elf64_x86_64_common_section + elf_x86_64_common_section #define elf_backend_common_definition \ - elf64_x86_64_common_definition + elf_x86_64_common_definition #define elf_backend_merge_symbol \ - elf64_x86_64_merge_symbol + elf_x86_64_merge_symbol #define elf_backend_special_sections \ - elf64_x86_64_special_sections + elf_x86_64_special_sections #define elf_backend_additional_program_headers \ - elf64_x86_64_additional_program_headers + elf_x86_64_additional_program_headers #define elf_backend_hash_symbol \ - elf64_x86_64_hash_symbol + elf_x86_64_hash_symbol #undef elf_backend_post_process_headers #define elf_backend_post_process_headers _bfd_elf_set_osabi @@ -4504,6 +4729,11 @@ static const struct bfd_elf_special_section #undef elf64_bed #define elf64_bed elf64_x86_64_sol2_bed +/* The 64-bit static TLS arena size is rounded to the nearest 16-byte + boundary. */ +#undef elf_backend_static_tls_alignment +#define elf_backend_static_tls_alignment 16 + /* The Solaris 2 ABI requires a plt symbol on all platforms. Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output @@ -4542,6 +4772,10 @@ elf64_l1om_elf_object_p (bfd *abfd) #define elf_backend_object_p elf64_l1om_elf_object_p #undef elf_backend_post_process_headers +#undef elf_backend_static_tls_alignment + +#undef elf_backend_want_plt_sym +#define elf_backend_want_plt_sym 0 #include "elf64-target.h" @@ -4562,3 +4796,53 @@ elf64_l1om_elf_object_p (bfd *abfd) #define elf_backend_post_process_headers _bfd_elf_set_osabi #include "elf64-target.h" + +/* 32bit x86-64 support. */ + +static bfd_boolean +elf32_x86_64_elf_object_p (bfd *abfd) +{ + /* Set the right machine number for an x86-64 elf32 file. */ + bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x64_32); + return TRUE; +} + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM bfd_elf32_x86_64_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elf32-x86-64" + +#undef ELF_ARCH +#define ELF_ARCH bfd_arch_i386 + +#undef ELF_MACHINE_CODE +#define ELF_MACHINE_CODE EM_X86_64 + +#define bfd_elf32_bfd_link_hash_table_create \ + elf_x86_64_link_hash_table_create +#define bfd_elf32_bfd_link_hash_table_free \ + elf_x86_64_link_hash_table_free +#define bfd_elf32_bfd_reloc_type_lookup \ + elf_x86_64_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup \ + elf_x86_64_reloc_name_lookup +#define bfd_elf32_mkobject \ + elf_x86_64_mkobject + +#undef ELF_OSABI + +#undef elf_backend_post_process_headers + +#undef elf_backend_object_p +#define elf_backend_object_p \ + elf32_x86_64_elf_object_p + +#undef elf_backend_bfd_from_remote_memory +#define elf_backend_bfd_from_remote_memory \ + _bfd_elf32_bfd_from_remote_memory + +#undef elf_backend_size_info +#define elf_backend_size_info \ + _bfd_elf32_size_info + +#include "elf32-target.h" diff --git a/contrib/gdb-7/bfd/elfcode.h b/contrib/gdb-7/bfd/elfcode.h index cd06455664..28b6b904e5 100644 --- a/contrib/gdb-7/bfd/elfcode.h +++ b/contrib/gdb-7/bfd/elfcode.h @@ -87,6 +87,7 @@ #define elf_core_file_failing_signal NAME(bfd_elf,core_file_failing_signal) #define elf_core_file_matches_executable_p \ NAME(bfd_elf,core_file_matches_executable_p) +#define elf_core_file_pid NAME(bfd_elf,core_file_pid) #define elf_object_p NAME(bfd_elf,object_p) #define elf_core_file_p NAME(bfd_elf,core_file_p) #define elf_get_symtab_upper_bound NAME(bfd_elf,get_symtab_upper_bound) @@ -197,6 +198,7 @@ elf_swap_symbol_in (bfd *abfd, } else if (dst->st_shndx >= (SHN_LORESERVE & 0xffff)) dst->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); + dst->st_target_internal = 0; return TRUE; } @@ -958,7 +960,9 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data) if (sec->orelocation == NULL) return; - rela_hdr = &elf_section_data (sec)->rel_hdr; + rela_hdr = elf_section_data (sec)->rela.hdr; + if (rela_hdr == NULL) + rela_hdr = elf_section_data (sec)->rel.hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size); @@ -1465,7 +1469,7 @@ elf_slurp_reloc_table_from_section (bfd *abfd, else relent->address = rela.r_offset - asect->vma; - if (ELF_R_SYM (rela.r_info) == 0) + if (ELF_R_SYM (rela.r_info) == STN_UNDEF) relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; else if (ELF_R_SYM (rela.r_info) > symcount) { @@ -1529,13 +1533,13 @@ elf_slurp_reloc_table (bfd *abfd, || asect->reloc_count == 0) return TRUE; - rel_hdr = &d->rel_hdr; - reloc_count = NUM_SHDR_ENTRIES (rel_hdr); - rel_hdr2 = d->rel_hdr2; - reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0); + rel_hdr = d->rel.hdr; + reloc_count = rel_hdr ? NUM_SHDR_ENTRIES (rel_hdr) : 0; + rel_hdr2 = d->rela.hdr; + reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0; BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2); - BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset) || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); } @@ -1559,10 +1563,11 @@ elf_slurp_reloc_table (bfd *abfd, if (relents == NULL) return FALSE; - if (!elf_slurp_reloc_table_from_section (abfd, asect, - rel_hdr, reloc_count, - relents, - symbols, dynamic)) + if (rel_hdr + && !elf_slurp_reloc_table_from_section (abfd, asect, + rel_hdr, reloc_count, + relents, + symbols, dynamic)) return FALSE; if (rel_hdr2 @@ -1851,6 +1856,22 @@ NAME(_bfd_elf,bfd_from_remote_memory) *loadbasep = loadbase; return nbfd; } + +/* Function for ELF_R_INFO. */ + +bfd_vma +NAME(elf,r_info) (bfd_vma sym, bfd_vma type) +{ + return ELF_R_INFO (sym, type); +} + +/* Function for ELF_R_SYM. */ + +bfd_vma +NAME(elf,r_sym) (bfd_vma r_info) +{ + return ELF_R_SYM (r_info); +} #include "elfcore.h" diff --git a/contrib/gdb-7/bfd/elfcore.h b/contrib/gdb-7/bfd/elfcore.h index 168c81ae21..81980c0fec 100644 --- a/contrib/gdb-7/bfd/elfcore.h +++ b/contrib/gdb-7/bfd/elfcore.h @@ -31,6 +31,12 @@ elf_core_file_failing_signal (bfd *abfd) return elf_tdata (abfd)->core_signal; } +int +elf_core_file_pid (bfd *abfd) +{ + return elf_tdata (abfd)->core_pid; +} + bfd_boolean elf_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) { diff --git a/contrib/gdb-7/bfd/elflink.c b/contrib/gdb-7/bfd/elflink.c index f445912dc9..9ccc841da2 100644 --- a/contrib/gdb-7/bfd/elflink.c +++ b/contrib/gdb-7/bfd/elflink.c @@ -86,6 +86,7 @@ _bfd_elf_define_linkage_sym (bfd *abfd, return NULL; h = (struct elf_link_hash_entry *) bh; h->def_regular = 1; + h->non_elf = 0; h->type = STT_OBJECT; h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; @@ -2170,7 +2171,7 @@ elf_link_read_relocs_from_section (bfd *abfd, return FALSE; } } - else if (r_symndx != 0) + else if (r_symndx != STN_UNDEF) { (*_bfd_error_handler) (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'" @@ -2195,7 +2196,7 @@ elf_link_read_relocs_from_section (bfd *abfd, according to the KEEP_MEMORY argument. If O has two relocation sections (both REL and RELA relocations), then the REL_HDR relocations will appear first in INTERNAL_RELOCS, followed by the - REL_HDR2 relocations. */ + RELA_HDR relocations. */ Elf_Internal_Rela * _bfd_elf_link_read_relocs (bfd *abfd, @@ -2204,19 +2205,18 @@ _bfd_elf_link_read_relocs (bfd *abfd, Elf_Internal_Rela *internal_relocs, bfd_boolean keep_memory) { - Elf_Internal_Shdr *rel_hdr; void *alloc1 = NULL; Elf_Internal_Rela *alloc2 = NULL; const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct bfd_elf_section_data *esdo = elf_section_data (o); + Elf_Internal_Rela *internal_rela_relocs; - if (elf_section_data (o)->relocs != NULL) - return elf_section_data (o)->relocs; + if (esdo->relocs != NULL) + return esdo->relocs; if (o->reloc_count == 0) return NULL; - rel_hdr = &elf_section_data (o)->rel_hdr; - if (internal_relocs == NULL) { bfd_size_type size; @@ -2233,32 +2233,41 @@ _bfd_elf_link_read_relocs (bfd *abfd, if (external_relocs == NULL) { - bfd_size_type size = rel_hdr->sh_size; + bfd_size_type size = 0; + + if (esdo->rel.hdr) + size += esdo->rel.hdr->sh_size; + if (esdo->rela.hdr) + size += esdo->rela.hdr->sh_size; - if (elf_section_data (o)->rel_hdr2) - size += elf_section_data (o)->rel_hdr2->sh_size; alloc1 = bfd_malloc (size); if (alloc1 == NULL) goto error_return; external_relocs = alloc1; } - if (!elf_link_read_relocs_from_section (abfd, o, rel_hdr, - external_relocs, - internal_relocs)) - goto error_return; - if (elf_section_data (o)->rel_hdr2 - && (!elf_link_read_relocs_from_section - (abfd, o, - elf_section_data (o)->rel_hdr2, - ((bfd_byte *) external_relocs) + rel_hdr->sh_size, - internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr) - * bed->s->int_rels_per_ext_rel)))) + internal_rela_relocs = internal_relocs; + if (esdo->rel.hdr) + { + if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr, + external_relocs, + internal_relocs)) + goto error_return; + external_relocs = (((bfd_byte *) external_relocs) + + esdo->rel.hdr->sh_size); + internal_rela_relocs += (NUM_SHDR_ENTRIES (esdo->rel.hdr) + * bed->s->int_rels_per_ext_rel); + } + + if (esdo->rela.hdr + && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, + external_relocs, + internal_rela_relocs))) goto error_return; /* Cache the results for next time, if we can. */ if (keep_memory) - elf_section_data (o)->relocs = internal_relocs; + esdo->relocs = internal_relocs; if (alloc1 != NULL) free (alloc1); @@ -2286,24 +2295,12 @@ _bfd_elf_link_read_relocs (bfd *abfd, static bfd_boolean _bfd_elf_link_size_reloc_section (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, - asection *o) + struct bfd_elf_section_reloc_data *reldata) { - bfd_size_type reloc_count; - bfd_size_type num_rel_hashes; - - /* Figure out how many relocations there will be. */ - if (rel_hdr == &elf_section_data (o)->rel_hdr) - reloc_count = elf_section_data (o)->rel_count; - else - reloc_count = elf_section_data (o)->rel_count2; - - num_rel_hashes = o->reloc_count; - if (num_rel_hashes < reloc_count) - num_rel_hashes = reloc_count; + Elf_Internal_Shdr *rel_hdr = reldata->hdr; /* That allows us to calculate the size of the section. */ - rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count; + rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count; /* The contents field must last into write_object_contents, so we allocate it with bfd_alloc rather than malloc. Also since we @@ -2313,19 +2310,16 @@ _bfd_elf_link_size_reloc_section (bfd *abfd, if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0) return FALSE; - /* We only allocate one set of hash entries, so we only do it the - first time we are called. */ - if (elf_section_data (o)->rel_hashes == NULL - && num_rel_hashes) + if (reldata->hashes == NULL && reldata->count) { struct elf_link_hash_entry **p; p = (struct elf_link_hash_entry **) - bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *)); + bfd_zmalloc (reldata->count * sizeof (struct elf_link_hash_entry *)); if (p == NULL) return FALSE; - elf_section_data (o)->rel_hashes = p; + reldata->hashes = p; } return TRUE; @@ -2346,27 +2340,26 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, Elf_Internal_Rela *irela; Elf_Internal_Rela *irelaend; bfd_byte *erel; - Elf_Internal_Shdr *output_rel_hdr; + struct bfd_elf_section_reloc_data *output_reldata; asection *output_section; - unsigned int *rel_countp = NULL; const struct elf_backend_data *bed; void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); + struct bfd_elf_section_data *esdo; output_section = input_section->output_section; - output_rel_hdr = NULL; - if (elf_section_data (output_section)->rel_hdr.sh_entsize - == input_rel_hdr->sh_entsize) + bed = get_elf_backend_data (output_bfd); + esdo = elf_section_data (output_section); + if (esdo->rel.hdr && esdo->rel.hdr->sh_entsize == input_rel_hdr->sh_entsize) { - output_rel_hdr = &elf_section_data (output_section)->rel_hdr; - rel_countp = &elf_section_data (output_section)->rel_count; + output_reldata = &esdo->rel; + swap_out = bed->s->swap_reloc_out; } - else if (elf_section_data (output_section)->rel_hdr2 - && (elf_section_data (output_section)->rel_hdr2->sh_entsize - == input_rel_hdr->sh_entsize)) + else if (esdo->rela.hdr + && esdo->rela.hdr->sh_entsize == input_rel_hdr->sh_entsize) { - output_rel_hdr = elf_section_data (output_section)->rel_hdr2; - rel_countp = &elf_section_data (output_section)->rel_count2; + output_reldata = &esdo->rela; + swap_out = bed->s->swap_reloca_out; } else { @@ -2377,16 +2370,8 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, return FALSE; } - bed = get_elf_backend_data (output_bfd); - if (input_rel_hdr->sh_entsize == bed->s->sizeof_rel) - swap_out = bed->s->swap_reloc_out; - else if (input_rel_hdr->sh_entsize == bed->s->sizeof_rela) - swap_out = bed->s->swap_reloca_out; - else - abort (); - - erel = output_rel_hdr->contents; - erel += *rel_countp * input_rel_hdr->sh_entsize; + erel = output_reldata->hdr->contents; + erel += output_reldata->count * input_rel_hdr->sh_entsize; irela = internal_relocs; irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr) * bed->s->int_rels_per_ext_rel); @@ -2399,7 +2384,7 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, /* Bump the counter, so that we know where to add the next set of relocations. */ - *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr); + output_reldata->count += NUM_SHDR_ENTRIES (input_rel_hdr); return TRUE; } @@ -2770,7 +2755,7 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data) bfd_boolean _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, struct bfd_link_info *info, - bfd_boolean ignore_protected) + bfd_boolean not_local_protected) { bfd_boolean binding_stays_local_p; const struct elf_backend_data *bed; @@ -2809,7 +2794,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, /* Proper resolution for function pointer equality may require that these symbols perhaps be resolved dynamically, even though we should be resolving them to the current module. */ - if (!ignore_protected || !bed->is_function_type (h->type)) + if (!not_local_protected || !bed->is_function_type (h->type)) binding_stays_local_p = TRUE; break; @@ -2818,7 +2803,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, } /* If it isn't defined locally, then clearly it's dynamic. */ - if (!h->def_regular) + if (!h->def_regular && !ELF_COMMON_DEF_P (h)) return TRUE; /* Otherwise, the symbol is dynamic if binding rules don't tell @@ -2829,7 +2814,15 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h, /* Return true if the symbol referred to by H should be considered to resolve local to the current module, and false otherwise. Differs from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of - undefined symbols and weak symbols. */ + undefined symbols. The two functions are virtually identical except + for the place where forced_local and dynindx == -1 are tested. If + either of those tests are true, _bfd_elf_dynamic_symbol_p will say + the symbol is local, while _bfd_elf_symbol_refs_local_p will say + the symbol is local only for defined symbols. + It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as + !_bfd_elf_symbol_refs_local_p, except that targets differ in their + treatment of undefined weak symbols. For those that do not make + undefined weak symbols dynamic, both functions may return false. */ bfd_boolean _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h, @@ -4191,7 +4184,8 @@ error_free_dyn: h = (struct elf_link_hash_entry *) h->root.u.i.link; *sym_hash = h; - h->unique_global = (flags & BSF_GNU_UNIQUE) != 0; + if (is_elf_hash_table (htab)) + h->unique_global = (flags & BSF_GNU_UNIQUE) != 0; new_weakdef = FALSE; if (dynamic @@ -4402,6 +4396,9 @@ error_free_dyn: dynsym = FALSE; } + if (definition) + h->target_internal = isym->st_target_internal; + /* Check to see if we need to add an indirect symbol for the default name. */ if (definition || h->root.type == bfd_link_hash_common) @@ -4791,6 +4788,7 @@ error_free_dyn: if (! dynamic && is_elf_hash_table (htab) && bed->check_relocs != NULL + && elf_object_id (abfd) == elf_hash_table_id (htab) && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) { asection *o; @@ -5078,10 +5076,10 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) undefs_tail = info->hash->undefs_tail; - if (! (*info->callbacks->add_archive_element) (info, element, - symdef->name)) + if (!(*info->callbacks + ->add_archive_element) (info, element, symdef->name, &element)) goto error_return; - if (! bfd_link_add_symbols (element, info)) + if (!bfd_link_add_symbols (element, info)) goto error_return; /* If there are any new undefined symbols, we need to make @@ -5352,7 +5350,7 @@ static const size_t elf_buckets[] = Therefore the result is always a good payoff between few collisions (= short chain lengths) and table size. */ static size_t -compute_bucket_count (struct bfd_link_info *info, +compute_bucket_count (struct bfd_link_info *info ATTRIBUTE_UNUSED, unsigned long int *hashcodes ATTRIBUTE_UNUSED, unsigned long int nsyms, int gnu_hash) @@ -5374,6 +5372,7 @@ compute_bucket_count (struct bfd_link_info *info, const struct elf_backend_data *bed = get_elf_backend_data (dynobj); unsigned long int *counts; bfd_size_type amt; + unsigned int no_improvement_count = 0; /* Possible optimization parameters: if we have NSYMS symbols we say that the hashing table must at least have NSYMS/4 and at most @@ -5458,7 +5457,12 @@ compute_bucket_count (struct bfd_link_info *info, { best_chlen = max; best_size = i; + no_improvement_count = 0; } + /* PR 11843: Avoid futile long searches for the best bucket size + when there are a large number of symbols. */ + else if (++no_improvement_count == 100) + break; } free (counts); @@ -5709,11 +5713,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { const char *verstr, *name; size_t namelen, verlen, newlen; - char *newname, *p; + char *newname, *p, leading_char; struct elf_link_hash_entry *newh; + leading_char = bfd_get_symbol_leading_char (output_bfd); name = d->pattern; - namelen = strlen (name); + namelen = strlen (name) + (leading_char != '\0'); verstr = t->name; verlen = strlen (verstr); newlen = namelen + verlen + 3; @@ -5721,7 +5726,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, newname = (char *) bfd_malloc (newlen); if (newname == NULL) return FALSE; - memcpy (newname, name, namelen); + newname[0] = leading_char; + memcpy (newname + (leading_char != '\0'), name, namelen); /* Check the hidden versioned definition. */ p = newname + namelen; @@ -7881,7 +7887,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, "chunksz %ld, start %ld, len %ld, oplen %ld\n" " dest: %8.8lx, mask: %8.8lx, reloc: %8.8lx\n", lsb0_p, signed_p, trunc_p, wordsz, chunksz, start, len, - oplen, x, mask, relocation); + oplen, (unsigned long) x, (unsigned long) mask, + (unsigned long) relocation); #endif r = bfd_reloc_ok; @@ -7901,8 +7908,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, " shifted mask: %8.8lx\n" " shifted/masked reloc: %8.8lx\n" " result: %8.8lx\n", - relocation, (mask << shift), - ((relocation & mask) << shift), x); + (unsigned long) relocation, (unsigned long) (mask << shift), + (unsigned long) ((relocation & mask) << shift), (unsigned long) x); #endif /* FIXME: octets_per_byte. */ put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset); @@ -7911,14 +7918,12 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, /* When performing a relocatable link, the input relocations are preserved. But, if they reference global symbols, the indices - referenced must be updated. Update all the relocations in - REL_HDR (there are COUNT of them), using the data in REL_HASH. */ + referenced must be updated. Update all the relocations found in + RELDATA. */ static void elf_link_adjust_relocs (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, - unsigned int count, - struct elf_link_hash_entry **rel_hash) + struct bfd_elf_section_reloc_data *reldata) { unsigned int i; const struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -7927,13 +7932,15 @@ elf_link_adjust_relocs (bfd *abfd, void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); bfd_vma r_type_mask; int r_sym_shift; + unsigned int count = reldata->count; + struct elf_link_hash_entry **rel_hash = reldata->hashes; - if (rel_hdr->sh_entsize == bed->s->sizeof_rel) + if (reldata->hdr->sh_entsize == bed->s->sizeof_rel) { swap_in = bed->s->swap_reloc_in; swap_out = bed->s->swap_reloc_out; } - else if (rel_hdr->sh_entsize == bed->s->sizeof_rela) + else if (reldata->hdr->sh_entsize == bed->s->sizeof_rela) { swap_in = bed->s->swap_reloca_in; swap_out = bed->s->swap_reloca_out; @@ -7955,8 +7962,8 @@ elf_link_adjust_relocs (bfd *abfd, r_sym_shift = 32; } - erela = rel_hdr->contents; - for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize) + erela = reldata->hdr->contents; + for (i = 0; i < count; i++, rel_hash++, erela += reldata->hdr->sh_entsize) { Elf_Internal_Rela irela[MAX_INT_RELS_PER_EXT_REL]; unsigned int j; @@ -8627,7 +8634,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) ignore_undef = bed->elf_backend_ignore_undef_symbol (h); /* If we are reporting errors for this situation then do so now. */ - if (ignore_undef == FALSE + if (!ignore_undef && h->ref_dynamic && (!h->ref_regular || finfo->info->gc_sections) && ! elf_link_check_versioned_symbol (finfo->info, bed, h) @@ -8638,6 +8645,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) h->ref_regular ? NULL : h->root.u.undef.abfd, NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR))) { + bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; } @@ -8654,16 +8662,21 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) && !h->dynamic_weak && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) { - (*_bfd_error_handler) - (_("%B: %s symbol `%s' in %B is referenced by DSO"), - finfo->output_bfd, - h->root.u.def.section == bfd_abs_section_ptr - ? finfo->output_bfd : h->root.u.def.section->owner, - ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - ? "internal" - : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN - ? "hidden" : "local", - h->root.root.string); + bfd *def_bfd; + const char *msg; + + if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL) + msg = _("%B: internal symbol `%s' in %B is referenced by DSO"); + else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + msg = _("%B: hidden symbol `%s' in %B is referenced by DSO"); + else + msg = _("%B: local symbol `%s' in %B is referenced by DSO"); + def_bfd = finfo->output_bfd; + if (h->root.u.def.section != bfd_abs_section_ptr) + def_bfd = h->root.u.def.section->owner; + (*_bfd_error_handler) (msg, finfo->output_bfd, def_bfd, + h->root.root.string); + bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; } @@ -8719,6 +8732,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); else sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type); + sym.st_target_internal = h->target_internal; switch (h->root.type) { @@ -8748,6 +8762,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) (*_bfd_error_handler) (_("%B: could not find output section %A for input section %A"), finfo->output_bfd, input_sec->output_section, input_sec); + bfd_set_error (bfd_error_nonrepresentable_section); eoinfo->failed = TRUE; return FALSE; } @@ -8865,14 +8880,16 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) && h->root.type == bfd_link_hash_undefined && !h->def_regular) { - (*_bfd_error_handler) - (_("%B: %s symbol `%s' isn't defined"), - finfo->output_bfd, - ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED - ? "protected" - : ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL - ? "internal" : "hidden", - h->root.root.string); + const char *msg; + + if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED) + msg = _("%B: protected symbol `%s' isn't defined"); + else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL) + msg = _("%B: internal symbol `%s' isn't defined"); + else + msg = _("%B: hidden symbol `%s' isn't defined"); + (*_bfd_error_handler) (msg, finfo->output_bfd, h->root.root.string); + bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; } @@ -9349,10 +9366,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) contents = elf_section_data (o)->this_hdr.contents; else { - bfd_size_type amt = o->rawsize ? o->rawsize : o->size; - contents = finfo->contents; - if (! bfd_get_section_contents (input_bfd, o, contents, 0, amt)) + if (! bfd_get_full_section_contents (input_bfd, o, &contents)) return FALSE; } @@ -9461,7 +9476,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) #ifdef DEBUG printf ("Encountered a complex symbol!"); printf (" (input_bfd %s, section %s, reloc %ld\n", - input_bfd->filename, o->name, rel - internal_relocs); + input_bfd->filename, o->name, + (long) (rel - internal_relocs)); printf (" symbol: idx %8.8lx, name %s\n", r_symndx, sym_name); printf (" reloc : info %8.8lx, addr %8.8lx\n", @@ -9484,7 +9500,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) discarded section. */ if ((sec = *ps) != NULL && elf_discarded_section (sec)) { - BFD_ASSERT (r_symndx != 0); + BFD_ASSERT (r_symndx != STN_UNDEF); if (action_discarded & COMPLAIN) (*finfo->info->callbacks->einfo) (_("%X`%s' referenced in section `%A' of %B: " @@ -9546,27 +9562,32 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) || finfo->info->emitrelocations) { Elf_Internal_Rela *irela; - Elf_Internal_Rela *irelaend; + Elf_Internal_Rela *irelaend, *irelamid; bfd_vma last_offset; struct elf_link_hash_entry **rel_hash; - struct elf_link_hash_entry **rel_hash_list; - Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2; + struct elf_link_hash_entry **rel_hash_list, **rela_hash_list; + Elf_Internal_Shdr *input_rel_hdr, *input_rela_hdr; unsigned int next_erel; bfd_boolean rela_normal; + struct bfd_elf_section_data *esdi, *esdo; - input_rel_hdr = &elf_section_data (o)->rel_hdr; - rela_normal = (bed->rela_normal - && (input_rel_hdr->sh_entsize - == bed->s->sizeof_rela)); + esdi = elf_section_data (o); + esdo = elf_section_data (o->output_section); + rela_normal = FALSE; /* Adjust the reloc addresses and symbol indices. */ irela = internal_relocs; irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel; - rel_hash = (elf_section_data (o->output_section)->rel_hashes - + elf_section_data (o->output_section)->rel_count - + elf_section_data (o->output_section)->rel_count2); + rel_hash = esdo->rel.hashes + esdo->rel.count; + /* We start processing the REL relocs, if any. When we reach + IRELAMID in the loop, we switch to the RELA relocs. */ + irelamid = irela; + if (esdi->rel.hdr != NULL) + irelamid += (NUM_SHDR_ENTRIES (esdi->rel.hdr) + * bed->s->int_rels_per_ext_rel); rel_hash_list = rel_hash; + rela_hash_list = NULL; last_offset = o->output_offset; if (!finfo->info->relocatable) last_offset += o->output_section->vma; @@ -9582,6 +9603,13 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) next_erel = 0; } + if (irela == irelamid) + { + rel_hash = esdo->rela.hashes + esdo->rela.count; + rela_hash_list = rel_hash; + rela_normal = bed->rela_normal; + } + irela->r_offset = _bfd_elf_section_offset (output_bfd, finfo->info, o, irela->r_offset); @@ -9651,7 +9679,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* I suppose the backend ought to fill in the section of any STT_SECTION symbol against a processor specific section. */ - r_symndx = 0; + r_symndx = STN_UNDEF; if (bfd_is_abs_section (sec)) ; else if (sec == NULL || sec->owner == NULL) @@ -9680,7 +9708,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (!bfd_is_abs_section (osec)) { r_symndx = osec->target_index; - if (r_symndx == 0) + if (r_symndx == STN_UNDEF) { struct elf_link_hash_table *htab; asection *oi; @@ -9698,7 +9726,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } } - BFD_ASSERT (r_symndx != 0); + BFD_ASSERT (r_symndx != STN_UNDEF); } } @@ -9773,23 +9801,26 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } /* Swap out the relocs. */ - if (input_rel_hdr->sh_size != 0 - && !bed->elf_backend_emit_relocs (output_bfd, o, - input_rel_hdr, - internal_relocs, - rel_hash_list)) - return FALSE; - - input_rel_hdr2 = elf_section_data (o)->rel_hdr2; - if (input_rel_hdr2 && input_rel_hdr2->sh_size != 0) + input_rel_hdr = esdi->rel.hdr; + if (input_rel_hdr && input_rel_hdr->sh_size != 0) { + if (!bed->elf_backend_emit_relocs (output_bfd, o, + input_rel_hdr, + internal_relocs, + rel_hash_list)) + return FALSE; internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr) * bed->s->int_rels_per_ext_rel); rel_hash_list += NUM_SHDR_ENTRIES (input_rel_hdr); + } + + input_rela_hdr = esdi->rela.hdr; + if (input_rela_hdr && input_rela_hdr->sh_size != 0) + { if (!bed->elf_backend_emit_relocs (output_bfd, o, - input_rel_hdr2, + input_rela_hdr, internal_relocs, - rel_hash_list)) + rela_hash_list)) return FALSE; } } @@ -9827,7 +9858,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { /* FIXME: octets_per_byte. */ if (! (o->flags & SEC_EXCLUDE) - && ! (o->output_section->flags & SEC_NEVER_LOAD) && ! bfd_set_section_contents (output_bfd, o->output_section, contents, (file_ptr) o->output_offset, @@ -9856,12 +9886,14 @@ elf_reloc_link_order (bfd *output_bfd, long indx; bfd_vma offset; bfd_vma addend; + struct bfd_elf_section_reloc_data *reldata; struct elf_link_hash_entry **rel_hash_ptr; Elf_Internal_Shdr *rel_hdr; const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL]; bfd_byte *erel; unsigned int i; + struct bfd_elf_section_data *esdo = elf_section_data (output_section); howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); if (howto == NULL) @@ -9872,10 +9904,18 @@ elf_reloc_link_order (bfd *output_bfd, addend = link_order->u.reloc.p->addend; + if (esdo->rel.hdr) + reldata = &esdo->rel; + else if (esdo->rela.hdr) + reldata = &esdo->rela; + else + { + reldata = NULL; + BFD_ASSERT (0); + } + /* Figure out the symbol index. */ - rel_hash_ptr = (elf_section_data (output_section)->rel_hashes - + elf_section_data (output_section)->rel_count - + elf_section_data (output_section)->rel_count2); + rel_hash_ptr = reldata->hashes + reldata->count; if (link_order->type == bfd_section_reloc_link_order) { indx = link_order->u.reloc.p->u.section->target_index; @@ -9987,23 +10027,21 @@ elf_reloc_link_order (bfd *output_bfd, else irel[0].r_info = ELF64_R_INFO (indx, howto->type); - rel_hdr = &elf_section_data (output_section)->rel_hdr; + rel_hdr = reldata->hdr; erel = rel_hdr->contents; if (rel_hdr->sh_type == SHT_REL) { - erel += (elf_section_data (output_section)->rel_count - * bed->s->sizeof_rel); + erel += reldata->count * bed->s->sizeof_rel; (*bed->s->swap_reloc_out) (output_bfd, irel, erel); } else { irel[0].r_addend = addend; - erel += (elf_section_data (output_section)->rel_count - * bed->s->sizeof_rela); + erel += reldata->count * bed->s->sizeof_rela; (*bed->s->swap_reloca_out) (output_bfd, irel, erel); } - ++elf_section_data (output_section)->rel_count; + ++reldata->count; return TRUE; } @@ -10289,7 +10327,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { unsigned int reloc_count = 0; struct bfd_elf_section_data *esdi = NULL; - unsigned int *rel_count1; if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) @@ -10342,9 +10379,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if ((sec->flags & SEC_RELOC) != 0) { - size_t ext_size; + size_t ext_size = 0; + + if (esdi->rel.hdr != NULL) + ext_size = esdi->rel.hdr->sh_size; + if (esdi->rela.hdr != NULL) + ext_size += esdi->rela.hdr->sh_size; - ext_size = elf_section_data (sec)->rel_hdr.sh_size; if (ext_size > max_external_reloc_size) max_external_reloc_size = ext_size; if (sec->reloc_count > max_internal_reloc_count) @@ -10358,54 +10399,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) o->reloc_count += reloc_count; - /* MIPS may have a mix of REL and RELA relocs on sections. - To support this curious ABI we keep reloc counts in - elf_section_data too. We must be careful to add the - relocations from the input section to the right output - count. FIXME: Get rid of one count. We have - o->reloc_count == esdo->rel_count + esdo->rel_count2. */ - rel_count1 = &esdo->rel_count; - if (esdi != NULL) + if (p->type == bfd_indirect_link_order + && (info->relocatable || info->emitrelocations)) + { + if (esdi->rel.hdr) + esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + if (esdi->rela.hdr) + esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + } + else { - bfd_boolean same_size; - bfd_size_type entsize1; - - entsize1 = esdi->rel_hdr.sh_entsize; - /* PR 9827: If the header size has not been set yet then - assume that it will match the output section's reloc type. */ - if (entsize1 == 0) - entsize1 = o->use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel; + if (o->use_rela_p) + esdo->rela.count += reloc_count; else - BFD_ASSERT (entsize1 == bed->s->sizeof_rel - || entsize1 == bed->s->sizeof_rela); - same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel); - - if (!same_size) - rel_count1 = &esdo->rel_count2; - - if (esdi->rel_hdr2 != NULL) - { - bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize; - unsigned int alt_count; - unsigned int *rel_count2; - - BFD_ASSERT (entsize2 != entsize1 - && (entsize2 == bed->s->sizeof_rel - || entsize2 == bed->s->sizeof_rela)); - - rel_count2 = &esdo->rel_count2; - if (!same_size) - rel_count2 = &esdo->rel_count; - - /* The following is probably too simplistic if the - backend counts output relocs unusually. */ - BFD_ASSERT (bed->elf_backend_count_relocs == NULL); - alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2); - *rel_count2 += alt_count; - reloc_count -= alt_count; - } + esdo->rel.count += reloc_count; } - *rel_count1 += reloc_count; } if (o->reloc_count > 0) @@ -10442,22 +10450,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Set sizes, and assign file positions for reloc sections. */ for (o = abfd->sections; o != NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); if ((o->flags & SEC_RELOC) != 0) { - if (!(_bfd_elf_link_size_reloc_section - (abfd, &elf_section_data (o)->rel_hdr, o))) + if (esdo->rel.hdr + && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rel))) goto error_return; - if (elf_section_data (o)->rel_hdr2 - && !(_bfd_elf_link_size_reloc_section - (abfd, elf_section_data (o)->rel_hdr2, o))) + if (esdo->rela.hdr + && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rela))) goto error_return; } /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them to count upwards while actually outputting the relocations. */ - elf_section_data (o)->rel_count = 0; - elf_section_data (o)->rel_count2 = 0; + esdo->rel.count = 0; + esdo->rela.count = 0; } _bfd_elf_assign_file_positions_for_relocs (abfd); @@ -10516,6 +10524,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_info = 0; elfsym.st_other = 0; elfsym.st_shndx = SHN_UNDEF; + elfsym.st_target_internal = 0; if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr, NULL) != 1) goto error_return; @@ -10533,6 +10542,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); elfsym.st_other = 0; elfsym.st_value = 0; + elfsym.st_target_internal = 0; for (i = 1; i < elf_numsections (abfd); i++) { o = bfd_section_from_elf_index (abfd, i); @@ -10626,7 +10636,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) end = sec->vma + size; } base = elf_hash_table (info)->tls_sec->vma; - end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power); + /* Only align end of TLS section if static TLS doesn't have special + alignment requirements. */ + if (bed->static_tls_alignment == 1) + end = align_power (end, + elf_hash_table (info)->tls_sec->alignment_power); elf_hash_table (info)->tls_size = end - base; } @@ -10684,7 +10698,34 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) else { if (! _bfd_default_link_order (abfd, info, o, p)) - goto error_return; + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (sub) + == bfd_target_elf_flavour) + && (elf_elfheader (sub)->e_ident[EI_CLASS] + != bed->s->elfclass)) + { + const char *iclass, *oclass; + + if (bed->s->elfclass == ELFCLASS64) + { + iclass = "ELFCLASS32"; + oclass = "ELFCLASS64"; + } + else + { + iclass = "ELFCLASS64"; + oclass = "ELFCLASS32"; + } + + bfd_set_error (bfd_error_wrong_format); + (*_bfd_error_handler) + (_("%B: file class %s incompatible with %s"), + sub, iclass, oclass); + } + + goto error_return; + } } } } @@ -10752,6 +10793,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) sym.st_name = 0; sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); sym.st_other = 0; + sym.st_target_internal = 0; for (s = abfd->sections; s != NULL; s = s->next) { @@ -10889,17 +10931,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Adjust the relocs to have the correct symbol indices. */ for (o = abfd->sections; o != NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); if ((o->flags & SEC_RELOC) == 0) continue; - elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr, - elf_section_data (o)->rel_count, - elf_section_data (o)->rel_hashes); - if (elf_section_data (o)->rel_hdr2 != NULL) - elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2, - elf_section_data (o)->rel_count2, - (elf_section_data (o)->rel_hashes - + elf_section_data (o)->rel_count)); + if (esdo->rel.hdr != NULL) + elf_link_adjust_relocs (abfd, &esdo->rel); + if (esdo->rela.hdr != NULL) + elf_link_adjust_relocs (abfd, &esdo->rela); /* Set the reloc_count field to 0 to prevent write_relocs from trying to swap the relocs out itself. */ @@ -11194,9 +11233,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) free (finfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { - if ((o->flags & SEC_RELOC) != 0 - && elf_section_data (o)->rel_hashes != NULL) - free (elf_section_data (o)->rel_hashes); + struct bfd_elf_section_data *esdo = elf_section_data (o); + if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL) + free (esdo->rel.hashes); + if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL) + free (esdo->rela.hashes); } elf_tdata (abfd)->linker = TRUE; @@ -11238,9 +11279,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) free (finfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { - if ((o->flags & SEC_RELOC) != 0 - && elf_section_data (o)->rel_hashes != NULL) - free (elf_section_data (o)->rel_hashes); + struct bfd_elf_section_data *esdo = elf_section_data (o); + if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL) + free (esdo->rel.hashes); + if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL) + free (esdo->rela.hashes); } return FALSE; @@ -11453,7 +11496,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, struct elf_link_hash_entry *h; r_symndx = cookie->rel->r_info >> cookie->r_sym_shift; - if (r_symndx == 0) + if (r_symndx == STN_UNDEF) return NULL; if (r_symndx >= cookie->locsymcount @@ -12178,7 +12221,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) continue; r_symndx = rcookie->rel->r_info >> rcookie->r_sym_shift; - if (r_symndx == SHN_UNDEF) + if (r_symndx == STN_UNDEF) return TRUE; if (r_symndx >= rcookie->locsymcount @@ -12561,20 +12604,6 @@ _bfd_elf_default_got_elt_size (bfd *abfd, /* Routines to support the creation of dynamic relocs. */ -/* Return true if NAME is a name of a relocation - section associated with section S. */ - -static bfd_boolean -is_reloc_section (bfd_boolean rela, const char * name, asection * s) -{ - if (rela) - return CONST_STRNEQ (name, ".rela") - && strcmp (bfd_get_section_name (NULL, s), name + 5) == 0; - - return CONST_STRNEQ (name, ".rel") - && strcmp (bfd_get_section_name (NULL, s), name + 4) == 0; -} - /* Returns the name of the dynamic reloc section associated with SEC. */ static const char * @@ -12582,26 +12611,15 @@ get_dynamic_reloc_section_name (bfd * abfd, asection * sec, bfd_boolean is_rela) { - const char * name; - unsigned int strndx = elf_elfheader (abfd)->e_shstrndx; - unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name; + char *name; + const char *old_name = bfd_get_section_name (NULL, sec); + const char *prefix = is_rela ? ".rela" : ".rel"; - name = bfd_elf_string_from_elf_section (abfd, strndx, shnam); - if (name == NULL) + if (old_name == NULL) return NULL; - if (! is_reloc_section (is_rela, name, sec)) - { - static bfd_boolean complained = FALSE; - - if (! complained) - { - (*_bfd_error_handler) - (_("%B: bad relocation section name `%s\'"), abfd, name); - complained = TRUE; - } - name = NULL; - } + name = bfd_alloc (abfd, strlen (prefix) + strlen (old_name) + 1); + sprintf (name, "%s%s", prefix, old_name); return name; } @@ -12694,4 +12712,27 @@ _bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED, struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc; ehdest->type = ehsrc->type; + ehdest->target_internal = ehsrc->target_internal; +} + +/* Append a RELA relocation REL to section S in BFD. */ + +void +elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); + BFD_ASSERT (loc + bed->s->sizeof_rela <= s->contents + s->size); + bed->s->swap_reloca_out (abfd, rel, loc); +} + +/* Append a REL relocation REL to section S in BFD. */ + +void +elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel); + BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size); + bed->s->swap_reloca_out (abfd, rel, loc); } diff --git a/contrib/gdb-7/bfd/elfxx-target.h b/contrib/gdb-7/bfd/elfxx-target.h index ebce6a8f07..fab1b04ec3 100644 --- a/contrib/gdb-7/bfd/elfxx-target.h +++ b/contrib/gdb-7/bfd/elfxx-target.h @@ -1,6 +1,6 @@ /* Target definitions for NN-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -278,7 +278,7 @@ #endif #ifndef bfd_elfNN_mkobject -#define bfd_elfNN_mkobject bfd_elf_make_generic_object +#define bfd_elfNN_mkobject bfd_elf_make_object #endif #ifndef bfd_elfNN_mkcorefile @@ -305,6 +305,10 @@ #define elf_info_to_howto_rel 0 #endif +#ifndef ELF_TARGET_ID +#define ELF_TARGET_ID GENERIC_ELF_DATA +#endif + #ifndef ELF_OSABI #define ELF_OSABI ELFOSABI_NONE #endif @@ -473,6 +477,12 @@ #ifndef elf_backend_obj_attrs_order #define elf_backend_obj_attrs_order NULL #endif +#ifndef elf_backend_obj_attrs_handle_unknown +#define elf_backend_obj_attrs_handle_unknown NULL +#endif +#ifndef elf_backend_static_tls_alignment +#define elf_backend_static_tls_alignment 1 +#endif #ifndef elf_backend_post_process_headers #define elf_backend_post_process_headers NULL #endif @@ -638,6 +648,7 @@ extern const struct elf_size_info _bfd_elfNN_size_info; static struct elf_backend_data elfNN_bed = { ELF_ARCH, /* arch */ + ELF_TARGET_ID, /* target_id */ ELF_MACHINE_CODE, /* elf_machine_code */ ELF_OSABI, /* elf_osabi */ ELF_MAXPAGESIZE, /* maxpagesize */ @@ -733,6 +744,8 @@ static struct elf_backend_data elfNN_bed = elf_backend_obj_attrs_arg_type, elf_backend_obj_attrs_section_type, elf_backend_obj_attrs_order, + elf_backend_obj_attrs_handle_unknown, + elf_backend_static_tls_alignment, elf_backend_collect, elf_backend_type_change_ok, elf_backend_may_use_rel_p, @@ -776,7 +789,7 @@ const bfd_target TARGET_BIG_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS - | DYNAMIC | WP_TEXT | D_PAGED), + | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY @@ -872,7 +885,7 @@ const bfd_target TARGET_LITTLE_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS - | DYNAMIC | WP_TEXT | D_PAGED), + | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY diff --git a/contrib/gdb-7/bfd/hash.c b/contrib/gdb-7/bfd/hash.c index fc05923a5c..e2fa3a9138 100644 --- a/contrib/gdb-7/bfd/hash.c +++ b/contrib/gdb-7/bfd/hash.c @@ -1,6 +1,6 @@ /* hash.c -- hash table routines for BFD Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2009 Free Software Foundation, Inc. + 2006, 2007, 2009, 2010 Free Software Foundation, Inc. Written by Steve Chamberlain This file is part of BFD, the Binary File Descriptor library. @@ -412,20 +412,13 @@ bfd_hash_table_free (struct bfd_hash_table *table) table->memory = NULL; } -/* Look up a string in a hash table. */ - -struct bfd_hash_entry * -bfd_hash_lookup (struct bfd_hash_table *table, - const char *string, - bfd_boolean create, - bfd_boolean copy) +static inline unsigned long +bfd_hash_hash (const char *string, unsigned int *lenp) { const unsigned char *s; unsigned long hash; - unsigned int c; - struct bfd_hash_entry *hashp; unsigned int len; - unsigned int _index; + unsigned int c; hash = 0; len = 0; @@ -438,7 +431,25 @@ bfd_hash_lookup (struct bfd_hash_table *table, len = (s - (const unsigned char *) string) - 1; hash += len + (len << 17); hash ^= hash >> 2; + if (lenp != NULL) + *lenp = len; + return hash; +} + +/* Look up a string in a hash table. */ +struct bfd_hash_entry * +bfd_hash_lookup (struct bfd_hash_table *table, + const char *string, + bfd_boolean create, + bfd_boolean copy) +{ + unsigned long hash; + struct bfd_hash_entry *hashp; + unsigned int len; + unsigned int _index; + + hash = bfd_hash_hash (string, &len); _index = hash % table->size; for (hashp = table->table[_index]; hashp != NULL; @@ -535,6 +546,31 @@ bfd_hash_insert (struct bfd_hash_table *table, return hashp; } +/* Rename an entry in a hash table. */ + +void +bfd_hash_rename (struct bfd_hash_table *table, + const char *string, + struct bfd_hash_entry *ent) +{ + unsigned int _index; + struct bfd_hash_entry **pph; + + _index = ent->hash % table->size; + for (pph = &table->table[_index]; *pph != NULL; pph = &(*pph)->next) + if (*pph == ent) + break; + if (*pph == NULL) + abort (); + + *pph = ent->next; + ent->string = string; + ent->hash = bfd_hash_hash (string, NULL); + _index = ent->hash % table->size; + ent->next = table->table[_index]; + table->table[_index] = ent; +} + /* Replace an entry in a hash table. */ void diff --git a/contrib/gdb-7/bfd/libbfd.c b/contrib/gdb-7/bfd/libbfd.c index b378622b6b..8b24378456 100644 --- a/contrib/gdb-7/bfd/libbfd.c +++ b/contrib/gdb-7/bfd/libbfd.c @@ -1,6 +1,6 @@ /* Assorted BFD support routines, only used internally. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -150,6 +150,16 @@ _bfd_nocore_core_file_failing_signal (bfd *ignore_abfd ATTRIBUTE_UNUSED) return 0; } +/* Routine to handle the core_file_pid entry point for targets without + core file support. */ + +int +_bfd_nocore_core_file_pid (bfd *ignore_abfd ATTRIBUTE_UNUSED) +{ + bfd_set_error (bfd_error_invalid_operation); + return 0; +} + const bfd_target * _bfd_dummy_target (bfd *ignore_abfd ATTRIBUTE_UNUSED) { @@ -847,6 +857,15 @@ _bfd_generic_get_section_contents (bfd *abfd, if (count == 0) return TRUE; + if (section->compress_status != COMPRESS_SECTION_NONE) + { + (*_bfd_error_handler) + (_("%B: unable to get decompressed section %A"), + abfd, section); + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } + sz = section->rawsize ? section->rawsize : section->size; if (offset + count < count || offset + count > sz) @@ -1002,6 +1021,7 @@ warn_deprecated (const char *what, if (~(size_t) func & ~mask) { + fflush (stdout); /* Note: separate sentences in order to allow for translation into other languages. */ if (func) @@ -1009,6 +1029,7 @@ warn_deprecated (const char *what, what, file, line, func); else fprintf (stderr, _("Deprecated %s called\n"), what); + fflush (stderr); mask |= ~(size_t) func; } } diff --git a/contrib/gdb-7/bfd/libbfd.h b/contrib/gdb-7/bfd/libbfd.h index 3da79d9dde..2e7df4f11c 100644 --- a/contrib/gdb-7/bfd/libbfd.h +++ b/contrib/gdb-7/bfd/libbfd.h @@ -123,10 +123,6 @@ extern bfd_error_handler_type _bfd_error_handler; /* These routines allocate and free things on the BFD's objalloc. */ -extern void *bfd_alloc - (bfd *, bfd_size_type); -extern void *bfd_zalloc - (bfd *, bfd_size_type); extern void *bfd_alloc2 (bfd *, bfd_size_type, bfd_size_type); extern void *bfd_zalloc2 @@ -275,6 +271,8 @@ extern int _bfd_nocore_core_file_failing_signal (bfd *); extern bfd_boolean _bfd_nocore_core_file_matches_executable_p (bfd *, bfd *); +extern int _bfd_nocore_core_file_pid + (bfd *); /* Routines to use for BFD_JUMP_TABLE_ARCHIVE when there is no archive file support. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive). */ @@ -631,7 +629,7 @@ extern bfd_reloc_status_type _bfd_relocate_contents /* Clear a given location using a given howto. */ extern void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, - bfd_byte *location); + asection *input_section, bfd_byte *location); /* Link stabs in sections in the first pass. */ @@ -815,6 +813,16 @@ extern void bfd_section_already_linked_table_traverse extern bfd_vma read_unsigned_leb128 (bfd *, bfd_byte *, unsigned int *); extern bfd_signed_vma read_signed_leb128 (bfd *, bfd_byte *, unsigned int *); +struct dwarf_debug_section +{ + const char *uncompressed_name; + const char *compressed_name; +}; + +/* Map of uncompressed DWARF debug section name to compressed one. It + is terminated by NULL uncompressed_name. */ + +extern struct dwarf_debug_section dwarf_debug_sections[]; /* Extracted from init.c. */ /* Extracted from libbfd.c. */ bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int); @@ -1369,6 +1377,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_TLS_TPOFF32", "BFD_RELOC_ARM_TLS_IE32", "BFD_RELOC_ARM_TLS_LE32", + "BFD_RELOC_ARM_TLS_GOTDESC", + "BFD_RELOC_ARM_TLS_CALL", + "BFD_RELOC_ARM_THM_TLS_CALL", + "BFD_RELOC_ARM_TLS_DESCSEQ", + "BFD_RELOC_ARM_THM_TLS_DESCSEQ", + "BFD_RELOC_ARM_TLS_DESC", "BFD_RELOC_ARM_ALU_PC_G0_NC", "BFD_RELOC_ARM_ALU_PC_G0", "BFD_RELOC_ARM_ALU_PC_G1_NC", @@ -1398,6 +1412,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_LDC_SB_G1", "BFD_RELOC_ARM_LDC_SB_G2", "BFD_RELOC_ARM_V4BX", + "BFD_RELOC_ARM_IRELATIVE", "BFD_RELOC_ARM_IMMEDIATE", "BFD_RELOC_ARM_ADRL_IMMEDIATE", "BFD_RELOC_ARM_T32_IMMEDIATE", @@ -1406,6 +1421,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_T32_ADD_PC12", "BFD_RELOC_ARM_SHIFT_IMM", "BFD_RELOC_ARM_SMC", + "BFD_RELOC_ARM_HVC", "BFD_RELOC_ARM_SWI", "BFD_RELOC_ARM_MULTI", "BFD_RELOC_ARM_CP_OFF_IMM", @@ -1636,6 +1652,28 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_V850_LONGJUMP", "BFD_RELOC_V850_ALIGN", "BFD_RELOC_V850_LO16_SPLIT_OFFSET", + "BFD_RELOC_V850_16_PCREL", + "BFD_RELOC_V850_17_PCREL", + "BFD_RELOC_V850_23", + "BFD_RELOC_V850_32_PCREL", + "BFD_RELOC_V850_32_ABS", + "BFD_RELOC_V850_16_SPLIT_OFFSET", + "BFD_RELOC_V850_16_S1", + "BFD_RELOC_V850_LO16_S1", + "BFD_RELOC_V850_CALLT_15_16_OFFSET", + "BFD_RELOC_V850_32_GOTPCREL", + "BFD_RELOC_V850_16_GOT", + "BFD_RELOC_V850_32_GOT", + "BFD_RELOC_V850_22_PLT_PCREL", + "BFD_RELOC_V850_32_PLT_PCREL", + "BFD_RELOC_V850_COPY", + "BFD_RELOC_V850_GLOB_DAT", + "BFD_RELOC_V850_JMP_SLOT", + "BFD_RELOC_V850_RELATIVE", + "BFD_RELOC_V850_16_GOTOFF", + "BFD_RELOC_V850_32_GOTOFF", + "BFD_RELOC_V850_CODE", + "BFD_RELOC_V850_DATA", "BFD_RELOC_MN10300_32_PCREL", "BFD_RELOC_MN10300_16_PCREL", "BFD_RELOC_TIC30_LDP", @@ -1667,6 +1705,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_C6000_DSBT_INDEX", "BFD_RELOC_C6000_PREL31", "BFD_RELOC_C6000_COPY", + "BFD_RELOC_C6000_JUMP_SLOT", + "BFD_RELOC_C6000_EHTYPE", + "BFD_RELOC_C6000_PCR_H16", + "BFD_RELOC_C6000_PCR_L16", "BFD_RELOC_C6000_ALIGN", "BFD_RELOC_C6000_FPHEAD", "BFD_RELOC_C6000_NOCMP", @@ -1769,9 +1811,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_RX_GPRELL", "BFD_RELOC_RX_SYM", "BFD_RELOC_RX_OP_SUBTRACT", + "BFD_RELOC_RX_OP_NEG", "BFD_RELOC_RX_ABS8", "BFD_RELOC_RX_ABS16", + "BFD_RELOC_RX_ABS16_REV", "BFD_RELOC_RX_ABS32", + "BFD_RELOC_RX_ABS32_REV", "BFD_RELOC_RX_ABS16U", "BFD_RELOC_RX_ABS16UW", "BFD_RELOC_RX_ABS16UL", diff --git a/contrib/gdb-7/bfd/libcoff.h b/contrib/gdb-7/bfd/libcoff.h index 966f71ee10..4f73f109de 100644 --- a/contrib/gdb-7/bfd/libcoff.h +++ b/contrib/gdb-7/bfd/libcoff.h @@ -30,7 +30,6 @@ /* Object file tdata; access macros. */ #define coff_data(bfd) ((bfd)->tdata.coff_obj_data) -#define exec_hdr(bfd) (coff_data (bfd)->hdr) #define obj_pe(bfd) (coff_data (bfd)->pe) #define obj_symbols(bfd) (coff_data (bfd)->symbols) #define obj_sym_filepos(bfd) (coff_data (bfd)->sym_filepos) diff --git a/contrib/gdb-7/bfd/linker.c b/contrib/gdb-7/bfd/linker.c index 76bc70af09..2b52ba9651 100644 --- a/contrib/gdb-7/bfd/linker.c +++ b/contrib/gdb-7/bfd/linker.c @@ -223,7 +223,10 @@ SUBSUBSECTION archive and decide which elements of the archive should be included in the link. For each such element it must call the <> linker callback, and it must add the - symbols from the object file to the linker hash table. + symbols from the object file to the linker hash table. (The + callback may in fact indicate that a replacement BFD should be + used, in which case the symbols from that BFD should be added + to the linker hash table instead.) @findex _bfd_generic_link_add_archive_symbols In most cases the work of looking through the symbols in the @@ -243,9 +246,13 @@ SUBSUBSECTION element should be included in the link. If the element is to be included, the <> linker callback routine must be called with the element as an argument, and - the elements symbols must be added to the linker hash table + the element's symbols must be added to the linker hash table just as though the element had itself been passed to the - <<_bfd_link_add_symbols>> function. + <<_bfd_link_add_symbols>> function. The <> + callback has the option to indicate that it would like to + replace the element archive with a substitute BFD, in which + case it is the symbols of that substitute BFD that must be + added to the linker hash table instead. When the a.out <<_bfd_link_add_symbols>> function receives an archive, it calls <<_bfd_generic_link_add_archive_symbols>> @@ -257,7 +264,8 @@ SUBSUBSECTION symbol) it calls the <> callback and then <> calls <> to actually add the symbols to the - linker hash table. + linker hash table - possibly those of a substitute BFD, if the + <> callback avails itself of that option. The ECOFF back end is unusual in that it does not normally call <<_bfd_generic_link_add_archive_symbols>>, because ECOFF @@ -957,8 +965,10 @@ archive_hash_table_init included. CHECKFN should set *PNEEDED to TRUE if the object file should be included, and must also call the bfd_link_info add_archive_element callback function and handle adding the symbols - to the global hash table. CHECKFN should only return FALSE if some - sort of error occurs. + to the global hash table. CHECKFN must notice if the callback + indicates a substitute BFD, and arrange to add those symbols instead + if it does so. CHECKFN should only return FALSE if some sort of + error occurs. For some formats, such as a.out, it is possible to look through an object file but not actually include it in the link. The @@ -1213,10 +1223,17 @@ generic_link_check_archive_element (bfd *abfd, { bfd_size_type symcount; asymbol **symbols; + bfd *oldbfd = abfd; /* This object file defines this symbol, so pull it in. */ - if (! (*info->callbacks->add_archive_element) (info, abfd, - bfd_asymbol_name (p))) + if (!(*info->callbacks + ->add_archive_element) (info, abfd, bfd_asymbol_name (p), + &abfd)) + return FALSE; + /* Potentially, the add_archive_element hook may have set a + substitute BFD for us. */ + if (abfd != oldbfd + && !bfd_generic_link_read_symbols (abfd)) return FALSE; symcount = _bfd_generic_link_get_symcount (abfd); symbols = _bfd_generic_link_get_symbols (abfd); @@ -1241,9 +1258,13 @@ generic_link_check_archive_element (bfd *abfd, /* This symbol was created as undefined from outside BFD. We assume that we should link in the object file. This is for the -u option in the linker. */ - if (! (*info->callbacks->add_archive_element) - (info, abfd, bfd_asymbol_name (p))) + if (!(*info->callbacks + ->add_archive_element) (info, abfd, bfd_asymbol_name (p), + &abfd)) return FALSE; + /* Potentially, the add_archive_element hook may have set a + substitute BFD for us. But no symbols are going to get + registered by anything we're returning to from here. */ *pneeded = TRUE; return TRUE; } diff --git a/contrib/gdb-7/bfd/merge.c b/contrib/gdb-7/bfd/merge.c index 7aa088ff94..aef3cf35a5 100644 --- a/contrib/gdb-7/bfd/merge.c +++ b/contrib/gdb-7/bfd/merge.c @@ -348,6 +348,7 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, struct sec_merge_sec_info *secinfo; unsigned int align; bfd_size_type amt; + bfd_byte *contents; if ((abfd->flags & DYNAMIC) != 0 || (sec->flags & SEC_MERGE) == 0) @@ -432,8 +433,8 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, sec->rawsize = sec->size; if (sec->flags & SEC_STRINGS) memset (secinfo->contents + sec->size, 0, sec->entsize); - if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents, - 0, sec->size)) + contents = secinfo->contents; + if (! bfd_get_full_section_contents (sec->owner, sec, &contents)) goto error_return; return TRUE; diff --git a/contrib/gdb-7/bfd/opncls.c b/contrib/gdb-7/bfd/opncls.c index 79c3274bcc..3597daee01 100644 --- a/contrib/gdb-7/bfd/opncls.c +++ b/contrib/gdb-7/bfd/opncls.c @@ -1,6 +1,6 @@ /* opncls.c -- open and close a BFD. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Written by Cygnus Support. @@ -38,9 +38,17 @@ #define S_IXOTH 0001 /* Execute by others. */ #endif -/* Counter used to initialize the bfd identifier. */ +/* Counters used to initialize the bfd identifier. */ -static unsigned int _bfd_id_counter = 0; +static unsigned int bfd_id_counter = 0; +static unsigned int bfd_reserved_id_counter = 0; + +/* +CODE_FRAGMENT +.{* Set to N to open the next N BFDs using an alternate id space. *} +.extern unsigned int bfd_use_reserved_id; +*/ +unsigned int bfd_use_reserved_id = 0; /* fdopen is a loser -- we should use stdio exclusively. Unfortunately if we do that we can't use fcntl. */ @@ -56,7 +64,13 @@ _bfd_new_bfd (void) if (nbfd == NULL) return NULL; - nbfd->id = _bfd_id_counter++; + if (bfd_use_reserved_id) + { + nbfd->id = --bfd_reserved_id_counter; + --bfd_use_reserved_id; + } + else + nbfd->id = bfd_id_counter++; nbfd->memory = objalloc_create (); if (nbfd->memory == NULL) @@ -753,7 +767,7 @@ SYNOPSIS DESCRIPTION Create a new BFD in the manner of <>, but without opening a file. The new BFD takes the target from the target - used by @var{template}. The format is always set to <>. + used by @var{templ}. The format is always set to <>. */ bfd * @@ -878,7 +892,7 @@ bfd_make_readable (bfd *abfd) } /* -INTERNAL_FUNCTION +FUNCTION bfd_alloc SYNOPSIS @@ -946,7 +960,7 @@ bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) } /* -INTERNAL_FUNCTION +FUNCTION bfd_zalloc SYNOPSIS diff --git a/contrib/gdb-7/bfd/reloc.c b/contrib/gdb-7/bfd/reloc.c index 7d16869263..202a34095a 100644 --- a/contrib/gdb-7/bfd/reloc.c +++ b/contrib/gdb-7/bfd/reloc.c @@ -1,6 +1,6 @@ /* BFD support for handling relocation entries. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -1544,14 +1544,15 @@ _bfd_relocate_contents (reloc_howto_type *howto, return flag; } -/* Clear a given location using a given howto, by applying a relocation value - of zero and discarding any in-place addend. This is used for fixed-up +/* Clear a given location using a given howto, by applying a fixed relocation + value and discarding any in-place addend. This is used for fixed-up relocations against discarded symbols, to make ignorable debug or unwind information more obvious. */ void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, + asection *input_section, bfd_byte *location) { int size; @@ -1585,6 +1586,13 @@ _bfd_clear_contents (reloc_howto_type *howto, /* Zero out the unwanted bits of X. */ x &= ~howto->dst_mask; + /* For a range list, use 1 instead of 0 as placeholder. 0 + would terminate the list, hiding any later entries. */ + if (strcmp (bfd_get_section_name (input_bfd, input_section), + ".debug_ranges") == 0 + && (howto->dst_mask & 1) != 0) + x |= 1; + /* Put the relocated value back in the object file. */ switch (size) { @@ -2954,6 +2962,18 @@ ENUMX BFD_RELOC_ARM_TLS_IE32 ENUMX BFD_RELOC_ARM_TLS_LE32 +ENUMX + BFD_RELOC_ARM_TLS_GOTDESC +ENUMX + BFD_RELOC_ARM_TLS_CALL +ENUMX + BFD_RELOC_ARM_THM_TLS_CALL +ENUMX + BFD_RELOC_ARM_TLS_DESCSEQ +ENUMX + BFD_RELOC_ARM_THM_TLS_DESCSEQ +ENUMX + BFD_RELOC_ARM_TLS_DESC ENUMDOC ARM thread-local storage relocations. @@ -3021,6 +3041,11 @@ ENUM ENUMDOC Annotation of BX instructions. +ENUM + BFD_RELOC_ARM_IRELATIVE +ENUMDOC + ARM support for STT_GNU_IFUNC. + ENUM BFD_RELOC_ARM_IMMEDIATE ENUMX @@ -3037,6 +3062,8 @@ ENUMX BFD_RELOC_ARM_SHIFT_IMM ENUMX BFD_RELOC_ARM_SMC +ENUMX + BFD_RELOC_ARM_HVC ENUMX BFD_RELOC_ARM_SWI ENUMX @@ -3722,6 +3749,94 @@ ENUM ENUMDOC This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu instructions. +ENUM + BFD_RELOC_V850_16_PCREL +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_17_PCREL +ENUMDOC + This is a 17-bit reloc. +ENUM + BFD_RELOC_V850_23 +ENUMDOC + This is a 23-bit reloc. +ENUM + BFD_RELOC_V850_32_PCREL +ENUMDOC + This is a 32-bit reloc. +ENUM + BFD_RELOC_V850_32_ABS +ENUMDOC + This is a 32-bit reloc. +ENUM + BFD_RELOC_V850_16_SPLIT_OFFSET +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_16_S1 +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_LO16_S1 +ENUMDOC + Low 16 bits. 16 bit shifted by 1. +ENUM + BFD_RELOC_V850_CALLT_15_16_OFFSET +ENUMDOC + This is a 16 bit offset from the call table base pointer. +ENUM + BFD_RELOC_V850_32_GOTPCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_16_GOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_GOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_22_PLT_PCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_PLT_PCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_COPY +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_GLOB_DAT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_JMP_SLOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_RELATIVE +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_16_GOTOFF +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_GOTOFF +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_CODE +ENUMDOC + start code. +ENUM + BFD_RELOC_V850_DATA +ENUMDOC + start data in text. ENUM BFD_RELOC_MN10300_32_PCREL ENUMDOC @@ -3819,6 +3934,14 @@ ENUMX BFD_RELOC_C6000_PREL31 ENUMX BFD_RELOC_C6000_COPY +ENUMX + BFD_RELOC_C6000_JUMP_SLOT +ENUMX + BFD_RELOC_C6000_EHTYPE +ENUMX + BFD_RELOC_C6000_PCR_H16 +ENUMX + BFD_RELOC_C6000_PCR_L16 ENUMX BFD_RELOC_C6000_ALIGN ENUMX @@ -4159,12 +4282,18 @@ ENUMX BFD_RELOC_RX_SYM ENUMX BFD_RELOC_RX_OP_SUBTRACT +ENUMX + BFD_RELOC_RX_OP_NEG ENUMX BFD_RELOC_RX_ABS8 ENUMX BFD_RELOC_RX_ABS16 +ENUMX + BFD_RELOC_RX_ABS16_REV ENUMX BFD_RELOC_RX_ABS32 +ENUMX + BFD_RELOC_RX_ABS32_REV ENUMX BFD_RELOC_RX_ABS16U ENUMX @@ -5484,7 +5613,7 @@ bfd_default_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) case BFD_RELOC_CTOR: /* The type of reloc used in a ctor, which will be as wide as the address - so either a 64, 32, or 16 bitter. */ - switch (bfd_get_arch_info (abfd)->bits_per_address) + switch (bfd_arch_bits_per_address (abfd)) { case 64: BFD_FAIL (); @@ -5623,15 +5752,13 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, long reloc_size; arelent **reloc_vector; long reloc_count; - bfd_size_type sz; reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); if (reloc_size < 0) return NULL; /* Read in the section. */ - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) + if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) return NULL; if (reloc_size == 0) @@ -5666,7 +5793,8 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, "unused", FALSE, 0, 0, FALSE); p = data + (*parent)->address * bfd_octets_per_byte (input_bfd); - _bfd_clear_contents ((*parent)->howto, input_bfd, p); + _bfd_clear_contents ((*parent)->howto, input_bfd, input_section, + p); (*parent)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; (*parent)->addend = 0; (*parent)->howto = &none_howto; diff --git a/contrib/gdb-7/bfd/section.c b/contrib/gdb-7/bfd/section.c index 6e13fdb10e..bff8adfb07 100644 --- a/contrib/gdb-7/bfd/section.c +++ b/contrib/gdb-7/bfd/section.c @@ -364,6 +364,12 @@ CODE_FRAGMENT . {* Mark flag used by some linker backends for garbage collection. *} . unsigned int gc_mark : 1; . +. {* Section compression status. *} +. unsigned int compress_status : 2; +.#define COMPRESS_SECTION_NONE 0 +.#define COMPRESS_SECTION_DONE 1 +.#define DECOMPRESS_SECTION_SIZED 2 +. . {* The following flags are used by the ELF linker. *} . . {* Mark sections which have been allocated to segments. *} @@ -420,6 +426,9 @@ CODE_FRAGMENT . section size calculated on a previous linker relaxation pass. *} . bfd_size_type rawsize; . +. {* The compressed size of the section in octets. *} +. bfd_size_type compressed_size; +. . {* Relaxation table. *} . struct relax_table *relax; . @@ -653,17 +662,17 @@ CODE_FRAGMENT . {* name, id, index, next, prev, flags, user_set_vma, *} \ . { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ . \ -. {* linker_mark, linker_has_input, gc_mark, segment_mark, *} \ +. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \ . 0, 0, 1, 0, \ . \ -. {* sec_info_type, use_rela_p, *} \ -. 0, 0, \ +. {* segment_mark, sec_info_type, use_rela_p, *} \ +. 0, 0, 0, \ . \ . {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \ . 0, 0, 0, 0, 0, 0, \ . \ -. {* vma, lma, size, rawsize, relax, relax_count, *} \ -. 0, 0, 0, 0, 0, 0, \ +. {* vma, lma, size, rawsize, compressed_size, relax, relax_count, *} \ +. 0, 0, 0, 0, 0, 0, 0, \ . \ . {* output_offset, output_section, alignment_power, *} \ . 0, (struct bfd_section *) &SEC, 0, \ @@ -1204,6 +1213,29 @@ bfd_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED, return TRUE; } +/* +FUNCTION + bfd_rename_section + +SYNOPSIS + void bfd_rename_section + (bfd *abfd, asection *sec, const char *newname); + +DESCRIPTION + Rename section @var{sec} in @var{abfd} to @var{newname}. +*/ + +void +bfd_rename_section (bfd *abfd, sec_ptr sec, const char *newname) +{ + struct section_hash_entry *sh; + + sh = (struct section_hash_entry *) + ((char *) sec - offsetof (struct section_hash_entry, section)); + sh->section.name = newname; + bfd_hash_rename (&abfd->section_htab, newname, &sh->root); +} + /* FUNCTION bfd_map_over_sections @@ -1480,20 +1512,8 @@ DESCRIPTION bfd_boolean bfd_malloc_and_get_section (bfd *abfd, sec_ptr sec, bfd_byte **buf) { - bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size; - bfd_byte *p = NULL; - - *buf = p; - if (sz == 0) - return TRUE; - - p = (bfd_byte *) - bfd_malloc (sec->rawsize > sec->size ? sec->rawsize : sec->size); - if (p == NULL) - return FALSE; - *buf = p; - - return bfd_get_section_contents (abfd, sec, p, 0, sz); + *buf = NULL; + return bfd_get_full_section_contents (abfd, sec, buf); } /* FUNCTION diff --git a/contrib/gdb-7/bfd/simple.c b/contrib/gdb-7/bfd/simple.c index 9a8397f83e..03d1a15885 100644 --- a/contrib/gdb-7/bfd/simple.c +++ b/contrib/gdb-7/bfd/simple.c @@ -167,17 +167,9 @@ bfd_simple_get_relocated_section_contents (bfd *abfd, if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC || ! (sec->flags & SEC_RELOC)) { - bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size; - bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size; - - if (outbuf == NULL) - contents = (bfd_byte *) bfd_malloc (amt); - else - contents = outbuf; - - if (contents) - bfd_get_section_contents (abfd, sec, contents, 0, size); - + contents = outbuf; + if (!bfd_get_full_section_contents (abfd, sec, &contents)) + return NULL; return contents; } diff --git a/contrib/gdb-7/bfd/syms.c b/contrib/gdb-7/bfd/syms.c index 1f25d33815..e819eae16d 100644 --- a/contrib/gdb-7/bfd/syms.c +++ b/contrib/gdb-7/bfd/syms.c @@ -1386,8 +1386,8 @@ _bfd_stab_section_find_nearest_line (bfd *abfd, dirlen = strlen (directory_name); if (info->filename == NULL - || strncmp (info->filename, directory_name, dirlen) != 0 - || strcmp (info->filename + dirlen, file_name) != 0) + || filename_ncmp (info->filename, directory_name, dirlen) != 0 + || filename_cmp (info->filename + dirlen, file_name) != 0) { size_t len; diff --git a/contrib/gdb-7/bfd/targets.c b/contrib/gdb-7/bfd/targets.c index bb20189bfe..e491c93ee8 100644 --- a/contrib/gdb-7/bfd/targets.c +++ b/contrib/gdb-7/bfd/targets.c @@ -314,11 +314,13 @@ BFD_JUMP_TABLE macros. .#define BFD_JUMP_TABLE_CORE(NAME) \ . NAME##_core_file_failing_command, \ . NAME##_core_file_failing_signal, \ -. NAME##_core_file_matches_executable_p +. NAME##_core_file_matches_executable_p, \ +. NAME##_core_file_pid . . char * (*_core_file_failing_command) (bfd *); . int (*_core_file_failing_signal) (bfd *); . bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *); +. int (*_core_file_pid) (bfd *); . . {* Archive entry points. *} .#define BFD_JUMP_TABLE_ARCHIVE(NAME) \ @@ -644,6 +646,8 @@ extern const bfd_target bfd_elf32_nbigmips_vec; extern const bfd_target bfd_elf32_nlittlemips_vec; extern const bfd_target bfd_elf32_ntradbigmips_vec; extern const bfd_target bfd_elf32_ntradlittlemips_vec; +extern const bfd_target bfd_elf32_ntradbigmips_freebsd_vec; +extern const bfd_target bfd_elf32_ntradlittlemips_freebsd_vec; extern const bfd_target bfd_elf32_openrisc_vec; extern const bfd_target bfd_elf32_or32_big_vec; extern const bfd_target bfd_elf32_pj_vec; @@ -674,12 +678,15 @@ extern const bfd_target bfd_elf32_shlvxworks_vec; extern const bfd_target bfd_elf32_shnbsd_vec; extern const bfd_target bfd_elf32_shvxworks_vec; extern const bfd_target bfd_elf32_sparc_vec; +extern const bfd_target bfd_elf32_sparc_sol2_vec; extern const bfd_target bfd_elf32_sparc_vxworks_vec; extern const bfd_target bfd_elf32_spu_vec; extern const bfd_target bfd_elf32_tic6x_be_vec; extern const bfd_target bfd_elf32_tic6x_le_vec; extern const bfd_target bfd_elf32_tradbigmips_vec; extern const bfd_target bfd_elf32_tradlittlemips_vec; +extern const bfd_target bfd_elf32_tradbigmips_freebsd_vec; +extern const bfd_target bfd_elf32_tradlittlemips_freebsd_vec; extern const bfd_target bfd_elf32_us_cris_vec; extern const bfd_target bfd_elf32_v850_vec; extern const bfd_target bfd_elf32_vax_vec; @@ -711,11 +718,15 @@ extern const bfd_target bfd_elf64_sh64lnbsd_vec; extern const bfd_target bfd_elf64_sh64nbsd_vec; extern const bfd_target bfd_elf64_sparc_vec; extern const bfd_target bfd_elf64_sparc_freebsd_vec; +extern const bfd_target bfd_elf64_sparc_sol2_vec; extern const bfd_target bfd_elf64_tradbigmips_vec; extern const bfd_target bfd_elf64_tradlittlemips_vec; +extern const bfd_target bfd_elf64_tradbigmips_freebsd_vec; +extern const bfd_target bfd_elf64_tradlittlemips_freebsd_vec; extern const bfd_target bfd_elf64_x86_64_freebsd_vec; extern const bfd_target bfd_elf64_x86_64_sol2_vec; extern const bfd_target bfd_elf64_x86_64_vec; +extern const bfd_target bfd_elf32_x86_64_vec; extern const bfd_target bfd_elf64_l1om_freebsd_vec; extern const bfd_target bfd_elf64_l1om_vec; extern const bfd_target bfd_mmo_vec; @@ -988,6 +999,8 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_nlittlemips_vec, &bfd_elf32_ntradbigmips_vec, &bfd_elf32_ntradlittlemips_vec, + &bfd_elf32_ntradbigmips_freebsd_vec, + &bfd_elf32_ntradlittlemips_freebsd_vec, #endif &bfd_elf32_openrisc_vec, &bfd_elf32_or32_big_vec, @@ -1023,12 +1036,15 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_sh64blin_vec, #endif &bfd_elf32_sparc_vec, + &bfd_elf32_sparc_sol2_vec, &bfd_elf32_sparc_vxworks_vec, &bfd_elf32_spu_vec, &bfd_elf32_tic6x_be_vec, &bfd_elf32_tic6x_le_vec, &bfd_elf32_tradbigmips_vec, &bfd_elf32_tradlittlemips_vec, + &bfd_elf32_tradbigmips_freebsd_vec, + &bfd_elf32_tradlittlemips_freebsd_vec, &bfd_elf32_us_cris_vec, &bfd_elf32_v850_vec, &bfd_elf32_vax_vec, @@ -1061,11 +1077,15 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf64_sh64blin_vec, &bfd_elf64_sparc_vec, &bfd_elf64_sparc_freebsd_vec, + &bfd_elf64_sparc_sol2_vec, &bfd_elf64_tradbigmips_vec, &bfd_elf64_tradlittlemips_vec, + &bfd_elf64_tradbigmips_freebsd_vec, + &bfd_elf64_tradlittlemips_freebsd_vec, &bfd_elf64_x86_64_freebsd_vec, &bfd_elf64_x86_64_sol2_vec, &bfd_elf64_x86_64_vec, + &bfd_elf32_x86_64_vec, &bfd_elf64_l1om_freebsd_vec, &bfd_elf64_l1om_vec, &bfd_mmo_vec, diff --git a/contrib/gdb-7/bfd/version.h b/contrib/gdb-7/bfd/version.h index ef40e5fca0..23a04383c7 100644 --- a/contrib/gdb-7/bfd/version.h +++ b/contrib/gdb-7/bfd/version.h @@ -1,4 +1,4 @@ -#define BFD_VERSION_DATE 20100707 +#define BFD_VERSION_DATE 20110403 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ diff --git a/contrib/gdb-7/gdb/PROBLEMS b/contrib/gdb-7/gdb/PROBLEMS index 094957e012..974f4f0108 100644 --- a/contrib/gdb-7/gdb/PROBLEMS +++ b/contrib/gdb-7/gdb/PROBLEMS @@ -1,5 +1,5 @@ - Known problems in GDB 7.2 + Known problems in GDB 7.2.50 See also: http://www.gnu.org/software/gdb/bugs/ diff --git a/contrib/gdb-7/gdb/ada-exp.y b/contrib/gdb-7/gdb/ada-exp.y index 722db2fc07..e64d1eb456 100644 --- a/contrib/gdb-7/gdb/ada-exp.y +++ b/contrib/gdb-7/gdb/ada-exp.y @@ -1,6 +1,6 @@ /* YACC parser for Ada expressions, for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003, 2004, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -920,6 +920,7 @@ write_object_renaming (struct block *orig_left_context, break; case 'L': slice_state = LOWER_BOUND; + /* FALLTHROUGH */ case 'S': renaming_expr += 1; if (isdigit (*renaming_expr)) diff --git a/contrib/gdb-7/gdb/ada-lang.c b/contrib/gdb-7/gdb/ada-lang.c index 1d4c38b8d3..d434521be7 100644 --- a/contrib/gdb-7/gdb/ada-lang.c +++ b/contrib/gdb-7/gdb/ada-lang.c @@ -59,17 +59,17 @@ #include "stack.h" #include "psymtab.h" +#include "value.h" +#include "mi/mi-common.h" /* Define whether or not the C operator '/' truncates towards zero for - differently signed operands (truncation direction is undefined in C). + differently signed operands (truncation direction is undefined in C). Copied from valarith.c. */ #ifndef TRUNCATION_TOWARDS_ZERO #define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) #endif -static void modify_general_field (struct type *, char *, LONGEST, int, int); - static struct type *desc_base_type (struct type *); static struct type *desc_bounds_type (struct type *); @@ -102,11 +102,9 @@ static int ada_type_match (struct type *, struct type *, int); static int ada_args_match (struct symbol *, struct value **, int); -static struct value *ensure_lval (struct value *, - struct gdbarch *, CORE_ADDR *); +static int full_match (const char *, const char *); -static struct value *make_array_descriptor (struct type *, struct value *, - struct gdbarch *, CORE_ADDR *); +static struct value *make_array_descriptor (struct type *, struct value *); static void ada_add_block_symbols (struct obstack *, struct block *, const char *, @@ -200,7 +198,9 @@ static int equiv_types (struct type *, struct type *); static int is_name_suffix (const char *); -static int wild_match (const char *, int, const char *); +static int advance_wild_match (const char **, const char *, int); + +static int wild_match (const char *, const char *); static struct value *ada_coerce_ref (struct value *); @@ -229,8 +229,6 @@ static int ada_resolve_function (struct ada_symbol_info *, int, struct value **, int, const char *, struct type *); -static struct value *ada_coerce_to_simple_array (struct value *); - static int ada_is_direct_array_type (struct type *); static void ada_language_arch_info (struct gdbarch *, @@ -242,7 +240,8 @@ static struct value *ada_index_struct_field (int, struct value *, int, struct type *); static struct value *assign_aggregate (struct value *, struct value *, - struct expression *, int *, enum noside); + struct expression *, + int *, enum noside); static void aggregate_assign_from_choices (struct value *, struct value *, struct expression *, @@ -367,6 +366,41 @@ ada_inferior_exit (struct inferior *inf) /* Utilities */ +/* If TYPE is a TYPE_CODE_TYPEDEF type, return the target type after + all typedef layers have been peeled. Otherwise, return TYPE. + + Normally, we really expect a typedef type to only have 1 typedef layer. + In other words, we really expect the target type of a typedef type to be + a non-typedef type. This is particularly true for Ada units, because + the language does not have a typedef vs not-typedef distinction. + In that respect, the Ada compiler has been trying to eliminate as many + typedef definitions in the debugging information, since they generally + do not bring any extra information (we still use typedef under certain + circumstances related mostly to the GNAT encoding). + + Unfortunately, we have seen situations where the debugging information + generated by the compiler leads to such multiple typedef layers. For + instance, consider the following example with stabs: + + .stabs "pck__float_array___XUP:Tt(0,46)=s16P_ARRAY:(0,47)=[...]"[...] + .stabs "pck__float_array___XUP:t(0,36)=(0,46)",128,0,6,0 + + This is an error in the debugging information which causes type + pck__float_array___XUP to be defined twice, and the second time, + it is defined as a typedef of a typedef. + + This is on the fringe of legality as far as debugging information is + concerned, and certainly unexpected. But it is easy to handle these + situations correctly, so we can afford to be lenient in this case. */ + +static struct type * +ada_typedef_target_type (struct type *type) +{ + while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + type = TYPE_TARGET_TYPE (type); + return type; +} + /* Given DECODED_NAME a string holding a symbol name in its decoded form (ie using the Ada dotted notation), returns its unqualified name. */ @@ -523,17 +557,19 @@ coerce_unspec_val_to_type (struct value *val, struct type *type) trying to allocate some memory for it. */ check_size (type); - result = allocate_value (type); + if (value_lazy (val) + || TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val))) + result = allocate_value_lazy (type); + else + { + result = allocate_value (type); + memcpy (value_contents_raw (result), value_contents (val), + TYPE_LENGTH (type)); + } set_value_component_location (result, val); set_value_bitsize (result, value_bitsize (val)); set_value_bitpos (result, value_bitpos (val)); set_value_address (result, value_address (val)); - if (value_lazy (val) - || TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val))) - set_value_lazy (result, 1); - else - memcpy (value_contents_raw (result), value_contents (val), - TYPE_LENGTH (type)); return result; } } @@ -589,7 +625,7 @@ check_size (const struct type *type) error (_("object size is larger than varsize-limit")); } -/* Maximum value of a SIZE-byte signed integer type. */ +/* Maximum value of a SIZE-byte signed integer type. */ static LONGEST max_of_size (int size) { @@ -598,14 +634,14 @@ max_of_size (int size) return top_bit | (top_bit - 1); } -/* Minimum value of a SIZE-byte signed integer type. */ +/* Minimum value of a SIZE-byte signed integer type. */ static LONGEST min_of_size (int size) { return -max_of_size (size) - 1; } -/* Maximum value of a SIZE-byte unsigned integer type. */ +/* Maximum value of a SIZE-byte unsigned integer type. */ static ULONGEST umax_of_size (int size) { @@ -614,7 +650,7 @@ umax_of_size (int size) return top_bit | (top_bit - 1); } -/* Maximum value of integral type T, as a signed quantity. */ +/* Maximum value of integral type T, as a signed quantity. */ static LONGEST max_of_type (struct type *t) { @@ -624,7 +660,7 @@ max_of_type (struct type *t) return max_of_size (TYPE_LENGTH (t)); } -/* Minimum value of integral type T, as a signed quantity. */ +/* Minimum value of integral type T, as a signed quantity. */ static LONGEST min_of_type (struct type *t) { @@ -902,7 +938,7 @@ ada_remove_po_subprogram_suffix (const char *encoded, int *len) /* Protected entry subprograms are broken into two separate subprograms: The first one is unprotected, and has a 'N' suffix; the second is the protected version, and has - the 'P' suffix. The second calls the first one after handling + the 'P' suffix. The second calls the first one after handling the protection. Since the P subprograms are internally generated, we leave these names undecoded, giving the user a clue that this entity is internal. */ @@ -1082,7 +1118,7 @@ ada_decode (const char *encoded) /* Remove _E{DIGITS}+[sb] */ /* Just as for protected object subprograms, there are 2 categories - of subprograms created by the compiler for each entry. The first + of subprograms created by the compiler for each entry. The first one implements the actual entry code, and has a suffix following the convention above; the second one implements the barrier and uses the same convention as above, except that the 'E' is replaced @@ -1200,17 +1236,16 @@ static struct htab *decoded_names_store; previously computed. Tries to save the decoded name in the same obstack as GSYMBOL, if possible, and otherwise on the heap (so that, in any case, the decoded symbol has a lifetime at least that of - GSYMBOL). + GSYMBOL). The GSYMBOL parameter is "mutable" in the C++ sense: logically const, but nevertheless modified to a semantically equivalent form - when a decoded name is cached in it. -*/ + when a decoded name is cached in it. */ char * ada_decode_symbol (const struct general_symbol_info *gsymbol) { char **resultp = - (char **) &gsymbol->language_specific.cplus_specific.demangled_name; + (char **) &gsymbol->language_specific.mangled_lang.demangled_name; if (*resultp == NULL) { @@ -1255,12 +1290,12 @@ ada_la_decode (const char *encoded, int options) either argument is NULL. */ static int -ada_match_name (const char *sym_name, const char *name, int wild) +match_name (const char *sym_name, const char *name, int wild) { if (sym_name == NULL || name == NULL) return 0; else if (wild) - return wild_match (name, strlen (name), sym_name); + return wild_match (sym_name, name) == 0; else { int len_name = strlen (name); @@ -1342,15 +1377,6 @@ static char *bound_name[] = { #define MAX_ADA_DIMENS (sizeof(bound_name) / (2*sizeof(char *))) -/* Like modify_field, but allows bitpos > wordlength. */ - -static void -modify_general_field (struct type *type, char *addr, - LONGEST fieldval, int bitpos, int bitsize) -{ - modify_field (type, addr + bitpos / 8, fieldval, bitpos % 8, bitsize); -} - /* The desc_* routines return primitive portions of array descriptors (fat pointers). */ @@ -1364,6 +1390,9 @@ desc_base_type (struct type *type) if (type == NULL) return NULL; type = ada_check_typedef (type); + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + type = ada_typedef_target_type (type); + if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF)) @@ -1491,8 +1520,26 @@ desc_bounds (struct value *arr) } else if (is_thick_pntr (type)) - return value_struct_elt (&arr, NULL, "P_BOUNDS", NULL, - _("Bad GNAT array descriptor")); + { + struct value *p_bounds = value_struct_elt (&arr, NULL, "P_BOUNDS", NULL, + _("Bad GNAT array descriptor")); + struct type *p_bounds_type = value_type (p_bounds); + + if (p_bounds_type + && TYPE_CODE (p_bounds_type) == TYPE_CODE_PTR) + { + struct type *target_type = TYPE_TARGET_TYPE (p_bounds_type); + + if (TYPE_STUB (target_type)) + p_bounds = value_cast (lookup_pointer_type + (ada_check_typedef (target_type)), + p_bounds); + } + else + error (_("Bad GNAT array descriptor")); + + return p_bounds; + } else return NULL; } @@ -1539,7 +1586,7 @@ desc_data_target_type (struct type *type) if (data_type && TYPE_CODE (ada_check_typedef (data_type)) == TYPE_CODE_PTR) - return TYPE_TARGET_TYPE (data_type); + return ada_check_typedef (TYPE_TARGET_TYPE (data_type)); } return NULL; @@ -1664,7 +1711,7 @@ ada_is_direct_array_type (struct type *type) } /* Non-zero iff TYPE represents any kind of array in Ada, or a pointer - * to one. */ + * to one. */ static int ada_is_array_type (struct type *type) @@ -1686,7 +1733,8 @@ ada_is_simple_array_type (struct type *type) type = ada_check_typedef (type); return (TYPE_CODE (type) == TYPE_CODE_ARRAY || (TYPE_CODE (type) == TYPE_CODE_PTR - && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)); + && TYPE_CODE (ada_check_typedef (TYPE_TARGET_TYPE (type))) + == TYPE_CODE_ARRAY)); } /* Non-zero iff TYPE belongs to a GNAT array descriptor. */ @@ -1777,8 +1825,25 @@ ada_type_of_array (struct value *arr, int bounds) elt_type = create_array_type (array_type, elt_type, range_type); if (ada_is_unconstrained_packed_array_type (value_type (arr))) - TYPE_FIELD_BITSIZE (elt_type, 0) = - decode_packed_array_bitsize (value_type (arr)); + { + /* We need to store the element packed bitsize, as well as + recompute the array size, because it was previously + computed based on the unpacked element size. */ + LONGEST lo = value_as_long (low); + LONGEST hi = value_as_long (high); + + TYPE_FIELD_BITSIZE (elt_type, 0) = + decode_packed_array_bitsize (value_type (arr)); + /* If the array has no element, then the size is already + zero, and does not need to be recomputed. */ + if (lo < hi) + { + int array_bitsize = + (hi - lo + 1) * TYPE_FIELD_BITSIZE (elt_type, 0); + + TYPE_LENGTH (array_type) = (array_bitsize + 7) / 8; + } + } } return lookup_pointer_type (elt_type); @@ -1811,7 +1876,7 @@ ada_coerce_to_simple_array_ptr (struct value *arr) Otherwise, returns a standard GDB array describing ARR (which may be ARR itself if it already is in the proper form). */ -static struct value * +struct value * ada_coerce_to_simple_array (struct value *arr) { if (ada_is_array_descriptor_type (value_type (arr))) @@ -1885,10 +1950,17 @@ ada_is_unconstrained_packed_array_type (struct type *type) static long decode_packed_array_bitsize (struct type *type) { - char *raw_name = ada_type_name (ada_check_typedef (type)); + char *raw_name; char *tail; long bits; + /* Access to arrays implemented as fat pointers are encoded as a typedef + of the fat pointer type. We need the name of the fat pointer type + to do the decoding, so strip the typedef layer. */ + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + type = ada_typedef_target_type (type); + + raw_name = ada_type_name (ada_check_typedef (type)); if (!raw_name) raw_name = ada_type_name (desc_base_type (type)); @@ -1896,6 +1968,7 @@ decode_packed_array_bitsize (struct type *type) return 0; tail = strstr (raw_name, "___XP"); + gdb_assert (tail != NULL); if (sscanf (tail + sizeof ("___XP") - 1, "%ld", &bits) != 1) { @@ -1987,7 +2060,8 @@ decode_constrained_packed_array_type (struct type *type) if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY) { - lim_warning (_("could not understand bounds information on packed array")); + lim_warning (_("could not understand bounds " + "information on packed array")); return NULL; } @@ -2073,7 +2147,8 @@ value_subscript_packed (struct value *arr, int arity, struct value **ind) if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY || TYPE_FIELD_BITSIZE (elt_type, 0) == 0) error - (_("attempt to do packed indexing of something other than a packed array")); + (_("attempt to do packed indexing of " + "something other than a packed array")); else { struct type *range_type = TYPE_INDEX_TYPE (elt_type); @@ -2088,7 +2163,8 @@ value_subscript_packed (struct value *arr, int arity, struct value **ind) idx = pos_atr (ind[i]); if (idx < lowerbound || idx > upperbound) - lim_warning (_("packed array index %ld out of bounds"), (long) idx); + lim_warning (_("packed array index %ld out of bounds"), + (long) idx); bits = TYPE_FIELD_BITSIZE (elt_type, 0); elt_total_bit_offset += (idx - lowerbound) * bits; elt_type = ada_check_typedef (TYPE_TARGET_TYPE (elt_type)); @@ -2122,7 +2198,7 @@ has_negatives (struct type *type) /* Create a new value of type TYPE from the contents of OBJ starting at byte OFFSET, and bit offset BIT_OFFSET within that byte, proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then - assigning through the result will set the field fetched from. + assigning through the result will set the field fetched from. VALADDR is ignored unless OBJ is NULL, in which case, VALADDR+OFFSET must address the start of storage containing the packed value. The value returned in this case is never an lval. @@ -2498,19 +2574,20 @@ ada_value_ptr_subscript (struct value *arr, struct type *type, int arity, /* Given that ARRAY_PTR is a pointer or reference to an array of type TYPE (the actual type of ARRAY_PTR is ignored), returns the Ada slice of HIGH-LOW+1 elements starting at index LOW. The lower bound of this array is LOW, as - per Ada rules. */ + per Ada rules. */ static struct value * ada_value_slice_from_ptr (struct value *array_ptr, struct type *type, int low, int high) { + struct type *type0 = ada_check_typedef (type); CORE_ADDR base = value_as_address (array_ptr) - + ((low - ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type))) - * TYPE_LENGTH (TYPE_TARGET_TYPE (type))); + + ((low - ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0))) + * TYPE_LENGTH (TYPE_TARGET_TYPE (type0))); struct type *index_type = - create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type)), + create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)), low, high); struct type *slice_type = - create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type); + create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type); return value_at_lazy (slice_type, base); } @@ -2519,7 +2596,7 @@ ada_value_slice_from_ptr (struct value *array_ptr, struct type *type, static struct value * ada_value_slice (struct value *array, int low, int high) { - struct type *type = value_type (array); + struct type *type = ada_check_typedef (value_type (array)); struct type *index_type = create_range_type (NULL, TYPE_INDEX_TYPE (type), low, high); struct type *slice_type = @@ -2728,10 +2805,11 @@ ada_array_length (struct value *arr, int n) static struct value * empty_array (struct type *arr_type, int low) { + struct type *arr_type0 = ada_check_typedef (arr_type); struct type *index_type = - create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type)), + create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1); - struct type *elt_type = ada_array_element_type (arr_type, 1); + struct type *elt_type = ada_array_element_type (arr_type0, 1); return allocate_value (create_array_type (NULL, elt_type, index_type)); } @@ -3581,12 +3659,13 @@ replace_operator_with_call (struct expression **expp, int pc, int nargs, /* A new expression, with 6 more elements (3 for funcall, 4 for function symbol, -oplen for operator being replaced). */ struct expression *newexp = (struct expression *) - xmalloc (sizeof (struct expression) + xzalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES ((*expp)->nelts + 7 - oplen)); struct expression *exp = *expp; newexp->nelts = exp->nelts + 7 - oplen; newexp->language_defn = exp->language_defn; + newexp->gdbarch = exp->gdbarch; memcpy (newexp->elts, exp->elts, EXP_ELEM_TO_BYTES (pc)); memcpy (newexp->elts + pc + 7, exp->elts + pc + oplen, EXP_ELEM_TO_BYTES (exp->nelts - pc - oplen)); @@ -3771,7 +3850,7 @@ possible_user_operator_p (enum exp_opcode op, struct value *args[]) sets *LEN to the length of the renamed entity's name, *RENAMED_ENTITY to that name (not null-terminated), and *RENAMING_EXPR to the string describing the subcomponent selected from the renamed - entity. Returns ADA_NOT_RENAMING if SYM does not encode a renaming + entity. Returns ADA_NOT_RENAMING if SYM does not encode a renaming (in which case, the values of *RENAMED_ENTITY, *LEN, and *RENAMING_EXPR are undefined). Otherwise, returns a value indicating the category of entity renamed: an object (ADA_OBJECT_RENAMING), exception @@ -3908,43 +3987,22 @@ parse_old_style_renaming (struct type *type, /* Evaluation: Function Calls */ /* Return an lvalue containing the value VAL. This is the identity on - lvalues, and otherwise has the side-effect of pushing a copy of VAL - on the stack, using and updating *SP as the stack pointer, and - returning an lvalue whose value_address points to the copy. */ + lvalues, and otherwise has the side-effect of allocating memory + in the inferior where a copy of the value contents is copied. */ static struct value * -ensure_lval (struct value *val, struct gdbarch *gdbarch, CORE_ADDR *sp) +ensure_lval (struct value *val) { - if (! VALUE_LVAL (val)) + if (VALUE_LVAL (val) == not_lval + || VALUE_LVAL (val) == lval_internalvar) { int len = TYPE_LENGTH (ada_check_typedef (value_type (val))); + const CORE_ADDR addr = + value_as_long (value_allocate_space_in_inferior (len)); - /* The following is taken from the structure-return code in - call_function_by_hand. FIXME: Therefore, some refactoring seems - indicated. */ - if (gdbarch_inner_than (gdbarch, 1, 2)) - { - /* Stack grows downward. Align SP and value_address (val) after - reserving sufficient space. */ - *sp -= len; - if (gdbarch_frame_align_p (gdbarch)) - *sp = gdbarch_frame_align (gdbarch, *sp); - set_value_address (val, *sp); - } - else - { - /* Stack grows upward. Align the frame, allocate space, and - then again, re-align the frame. */ - if (gdbarch_frame_align_p (gdbarch)) - *sp = gdbarch_frame_align (gdbarch, *sp); - set_value_address (val, *sp); - *sp += len; - if (gdbarch_frame_align_p (gdbarch)) - *sp = gdbarch_frame_align (gdbarch, *sp); - } + set_value_address (val, addr); VALUE_LVAL (val) = lval_memory; - - write_memory (value_address (val), value_contents (val), len); + write_memory (addr, value_contents (val), len); } return val; @@ -3956,8 +4014,7 @@ ensure_lval (struct value *val, struct gdbarch *gdbarch, CORE_ADDR *sp) values not residing in memory, updating it as needed. */ struct value * -ada_convert_actual (struct value *actual, struct type *formal_type0, - struct gdbarch *gdbarch, CORE_ADDR *sp) +ada_convert_actual (struct value *actual, struct type *formal_type0) { struct type *actual_type = ada_check_typedef (value_type (actual)); struct type *formal_type = ada_check_typedef (formal_type0); @@ -3970,7 +4027,7 @@ ada_convert_actual (struct value *actual, struct type *formal_type0, if (ada_is_array_descriptor_type (formal_target) && TYPE_CODE (actual_target) == TYPE_CODE_ARRAY) - return make_array_descriptor (formal_type, actual, gdbarch, sp); + return make_array_descriptor (formal_type, actual); else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR || TYPE_CODE (formal_type) == TYPE_CODE_REF) { @@ -3990,7 +4047,7 @@ ada_convert_actual (struct value *actual, struct type *formal_type0, memcpy ((char *) value_contents_raw (val), (char *) value_contents (actual), TYPE_LENGTH (actual_type)); - actual = ensure_lval (val, gdbarch, sp); + actual = ensure_lval (val); } result = value_addr (actual); } @@ -4031,8 +4088,7 @@ value_pointer (struct value *value, struct type *type) representing a pointer to this descriptor. */ static struct value * -make_array_descriptor (struct type *type, struct value *arr, - struct gdbarch *gdbarch, CORE_ADDR *sp) +make_array_descriptor (struct type *type, struct value *arr) { struct type *bounds_type = desc_bounds_type (type); struct type *desc_type = desc_base_type (type); @@ -4040,37 +4096,36 @@ make_array_descriptor (struct type *type, struct value *arr, struct value *bounds = allocate_value (bounds_type); int i; - for (i = ada_array_arity (ada_check_typedef (value_type (arr))); i > 0; i -= 1) + for (i = ada_array_arity (ada_check_typedef (value_type (arr))); + i > 0; i -= 1) { - modify_general_field (value_type (bounds), - value_contents_writeable (bounds), - ada_array_bound (arr, i, 0), - desc_bound_bitpos (bounds_type, i, 0), - desc_bound_bitsize (bounds_type, i, 0)); - modify_general_field (value_type (bounds), - value_contents_writeable (bounds), - ada_array_bound (arr, i, 1), - desc_bound_bitpos (bounds_type, i, 1), - desc_bound_bitsize (bounds_type, i, 1)); + modify_field (value_type (bounds), value_contents_writeable (bounds), + ada_array_bound (arr, i, 0), + desc_bound_bitpos (bounds_type, i, 0), + desc_bound_bitsize (bounds_type, i, 0)); + modify_field (value_type (bounds), value_contents_writeable (bounds), + ada_array_bound (arr, i, 1), + desc_bound_bitpos (bounds_type, i, 1), + desc_bound_bitsize (bounds_type, i, 1)); } - bounds = ensure_lval (bounds, gdbarch, sp); + bounds = ensure_lval (bounds); - modify_general_field (value_type (descriptor), - value_contents_writeable (descriptor), - value_pointer (ensure_lval (arr, gdbarch, sp), - TYPE_FIELD_TYPE (desc_type, 0)), - fat_pntr_data_bitpos (desc_type), - fat_pntr_data_bitsize (desc_type)); + modify_field (value_type (descriptor), + value_contents_writeable (descriptor), + value_pointer (ensure_lval (arr), + TYPE_FIELD_TYPE (desc_type, 0)), + fat_pntr_data_bitpos (desc_type), + fat_pntr_data_bitsize (desc_type)); - modify_general_field (value_type (descriptor), - value_contents_writeable (descriptor), - value_pointer (bounds, - TYPE_FIELD_TYPE (desc_type, 1)), - fat_pntr_bounds_bitpos (desc_type), - fat_pntr_bounds_bitsize (desc_type)); + modify_field (value_type (descriptor), + value_contents_writeable (descriptor), + value_pointer (bounds, + TYPE_FIELD_TYPE (desc_type, 1)), + fat_pntr_bounds_bitpos (desc_type), + fat_pntr_bounds_bitsize (desc_type)); - descriptor = ensure_lval (descriptor, gdbarch, sp); + descriptor = ensure_lval (descriptor); if (TYPE_CODE (type) == TYPE_CODE_PTR) return value_addr (descriptor); @@ -4079,7 +4134,7 @@ make_array_descriptor (struct type *type, struct value *arr, } /* Dummy definitions for an experimental caching module that is not - * used in the public sources. */ + * used in the public sources. */ static int lookup_cached_symbol (const char *name, domain_enum namespace, @@ -4273,7 +4328,7 @@ ada_lookup_simple_minsym (const char *name) ALL_MSYMBOLS (objfile, msymbol) { - if (ada_match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match) + if (match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match) && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline) return msymbol; } @@ -4380,7 +4435,7 @@ static char * xget_renaming_scope (struct type *renaming_type) { /* The renaming types adhere to the following convention: - _____. + _____. So, to extract the scope, we search for the "___XR" extension, and then backtrack until we find the first "__". */ @@ -4519,7 +4574,7 @@ remove_irrelevant_renamings (struct ada_symbol_info *syms, /* If there is both a renaming foo___XR... encoded as a variable and a simple variable foo in the same block, discard the latter. - First, zero out such symbols, then compress. */ + First, zero out such symbols, then compress. */ is_new_style_renaming = 0; for (i = 0; i < nsyms; i += 1) { @@ -4633,28 +4688,92 @@ ada_add_local_symbols (struct obstack *obstackp, const char *name, } /* An object of this type is used as the user_data argument when - calling the map_ada_symtabs method. */ + calling the map_matching_symbols method. */ -struct ada_psym_data +struct match_data { + struct objfile *objfile; struct obstack *obstackp; - const char *name; - domain_enum domain; - int global; - int wild_match; + struct symbol *arg_sym; + int found_sym; }; -/* Callback function for map_ada_symtabs. */ +/* A callback for add_matching_symbols that adds SYM, found in BLOCK, + to a list of symbols. DATA0 is a pointer to a struct match_data * + containing the obstack that collects the symbol list, the file that SYM + must come from, a flag indicating whether a non-argument symbol has + been found in the current block, and the last argument symbol + passed in SYM within the current block (if any). When SYM is null, + marking the end of a block, the argument symbol is added if no + other has been found. */ -static void -ada_add_psyms (struct objfile *objfile, struct symtab *s, void *user_data) +static int +aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0) { - struct ada_psym_data *data = user_data; - const int block_kind = data->global ? GLOBAL_BLOCK : STATIC_BLOCK; + struct match_data *data = (struct match_data *) data0; + + if (sym == NULL) + { + if (!data->found_sym && data->arg_sym != NULL) + add_defn_to_vec (data->obstackp, + fixup_symbol_section (data->arg_sym, data->objfile), + block); + data->found_sym = 0; + data->arg_sym = NULL; + } + else + { + if (SYMBOL_CLASS (sym) == LOC_UNRESOLVED) + return 0; + else if (SYMBOL_IS_ARGUMENT (sym)) + data->arg_sym = sym; + else + { + data->found_sym = 1; + add_defn_to_vec (data->obstackp, + fixup_symbol_section (sym, data->objfile), + block); + } + } + return 0; +} + +/* Compare STRING1 to STRING2, with results as for strcmp. + Compatible with strcmp_iw in that strcmp_iw (STRING1, STRING2) <= 0 + implies compare_names (STRING1, STRING2) (they may differ as to + what symbols compare equal). */ - ada_add_block_symbols (data->obstackp, - BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind), - data->name, data->domain, objfile, data->wild_match); +static int +compare_names (const char *string1, const char *string2) +{ + while (*string1 != '\0' && *string2 != '\0') + { + if (isspace (*string1) || isspace (*string2)) + return strcmp_iw_ordered (string1, string2); + if (*string1 != *string2) + break; + string1 += 1; + string2 += 1; + } + switch (*string1) + { + case '(': + return strcmp_iw_ordered (string1, string2); + case '_': + if (*string2 == '\0') + { + if (is_name_suffix (string1)) + return 0; + else + return -1; + } + /* FALLTHROUGH */ + default: + if (*string2 == '(') + return strcmp_iw_ordered (string1, string2); + else + return *string1 - *string2; + } } /* Add to OBSTACKP all non-local symbols whose name and domain match @@ -4662,27 +4781,45 @@ ada_add_psyms (struct objfile *objfile, struct symtab *s, void *user_data) symbols if GLOBAL is non-zero, or on STATIC_BLOCK symbols otherwise. */ static void -ada_add_non_local_symbols (struct obstack *obstackp, const char *name, - domain_enum domain, int global, - int is_wild_match) +add_nonlocal_symbols (struct obstack *obstackp, const char *name, + domain_enum domain, int global, + int is_wild_match) { struct objfile *objfile; - struct ada_psym_data data; + struct match_data data; data.obstackp = obstackp; - data.name = name; - data.domain = domain; - data.global = global; - data.wild_match = is_wild_match; + data.arg_sym = NULL; ALL_OBJFILES (objfile) - { - if (objfile->sf) - objfile->sf->qf->map_ada_symtabs (objfile, wild_match, is_name_suffix, - ada_add_psyms, name, - global, domain, - is_wild_match, &data); - } + { + data.objfile = objfile; + + if (is_wild_match) + objfile->sf->qf->map_matching_symbols (name, domain, objfile, global, + aux_add_nonlocal_symbols, &data, + wild_match, NULL); + else + objfile->sf->qf->map_matching_symbols (name, domain, objfile, global, + aux_add_nonlocal_symbols, &data, + full_match, compare_names); + } + + if (num_defns_collected (obstackp) == 0 && global && !is_wild_match) + { + ALL_OBJFILES (objfile) + { + char *name1 = alloca (strlen (name) + sizeof ("_ada_")); + strcpy (name1, "_ada_"); + strcpy (name1 + sizeof ("_ada_") - 1, name); + data.objfile = objfile; + objfile->sf->qf->map_matching_symbols (name1, domain, + objfile, global, + aux_add_nonlocal_symbols, + &data, + full_match, compare_names); + } + } } /* Find symbols in DOMAIN matching NAME0, in BLOCK0 and enclosing @@ -4759,15 +4896,15 @@ ada_lookup_symbol_list (const char *name0, const struct block *block0, /* Search symbols from all global blocks. */ - ada_add_non_local_symbols (&symbol_list_obstack, name, namespace, 1, - wild_match); + add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 1, + wild_match); /* Now add symbols from all per-file blocks if we've gotten no hits (not strictly correct, but perhaps better than an error). */ if (num_defns_collected (&symbol_list_obstack) == 0) - ada_add_non_local_symbols (&symbol_list_obstack, name, namespace, 0, - wild_match); + add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 0, + wild_match); done: ndefns = num_defns_collected (&symbol_list_obstack); @@ -4807,7 +4944,7 @@ ada_lookup_encoded_symbol (const char *name, const struct block *block0, /* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing scope and in global scopes, or NULL if none. NAME is folded and encoded first. Otherwise, the result is as for ada_lookup_symbol_list, - choosing the first symbol if there are multiple choices. + choosing the first symbol if there are multiple choices. *IS_A_FIELD_OF_THIS is set to 0 and *SYMTAB is set to the symbol table in which the symbol was found (in both cases, these assignments occur only if the pointers are non-null). */ @@ -4886,14 +5023,14 @@ is_name_suffix (const char *str) #if 0 /* FIXME: brobecker/2005-09-23: Protected Object subprograms end - with a N at the end. Unfortunately, the compiler uses the same - convention for other internal types it creates. So treating + with a N at the end. Unfortunately, the compiler uses the same + convention for other internal types it creates. So treating all entity names that end with an "N" as a name suffix causes - some regressions. For instance, consider the case of an enumerated - type. To support the 'Image attribute, it creates an array whose + some regressions. For instance, consider the case of an enumerated + type. To support the 'Image attribute, it creates an array whose name ends with N. Having a single character like this as a suffix carrying some - information is a bit risky. Perhaps we should change the encoding + information is a bit risky. Perhaps we should change the encoding to be something like "_N" instead. In the meantime, do not do the following check. */ /* Protected Object Subprograms */ @@ -4994,36 +5131,93 @@ is_valid_name_for_wild_match (const char *name0) return 1; } -/* True if NAME represents a name of the form A1.A2....An, n>=1 and - PATN[0..PATN_LEN-1] = Ak.Ak+1.....An for some k >= 1. Ignores - informational suffixes of NAME (i.e., for which is_name_suffix is - true). */ +/* Advance *NAMEP to next occurrence of TARGET0 in the string NAME0 + that could start a simple name. Assumes that *NAMEP points into + the string beginning at NAME0. */ static int -wild_match (const char *patn0, int patn_len, const char *name0) +advance_wild_match (const char **namep, const char *name0, int target0) { - char* match; - const char* start; + const char *name = *namep; - start = name0; while (1) { - match = strstr (start, patn0); - if (match == NULL) + int t0, t1; + + t0 = *name; + if (t0 == '_') + { + t1 = name[1]; + if ((t1 >= 'a' && t1 <= 'z') || (t1 >= '0' && t1 <= '9')) + { + name += 1; + if (name == name0 + 5 && strncmp (name0, "_ada", 4) == 0) + break; + else + name += 1; + } + else if (t1 == '_' && ((name[2] >= 'a' && name[2] <= 'z') + || name[2] == target0)) + { + name += 2; + break; + } + else + return 0; + } + else if ((t0 >= 'a' && t0 <= 'z') || (t0 >= '0' && t0 <= '9')) + name += 1; + else return 0; - if ((match == name0 - || match[-1] == '.' - || (match > name0 + 1 && match[-1] == '_' && match[-2] == '_') - || (match == name0 + 5 && strncmp ("_ada_", name0, 5) == 0)) - && is_name_suffix (match + patn_len)) - return (match == name0 || is_valid_name_for_wild_match (name0)); - start = match + 1; } + + *namep = name; + return 1; +} + +/* Return 0 iff NAME encodes a name of the form prefix.PATN. Ignores any + informational suffixes of NAME (i.e., for which is_name_suffix is + true). Assumes that PATN is a lower-cased Ada simple name. */ + +static int +wild_match (const char *name, const char *patn) +{ + const char *p, *n; + const char *name0 = name; + + while (1) + { + const char *match = name; + + if (*name == *patn) + { + for (name += 1, p = patn + 1; *p != '\0'; name += 1, p += 1) + if (*p != *name) + break; + if (*p == '\0' && is_name_suffix (name)) + return match != name0 && !is_valid_name_for_wild_match (name0); + + if (name[-1] == '_') + name -= 1; + } + if (!advance_wild_match (&name, name0, *patn)) + return 1; + } +} + +/* Returns 0 iff symbol name SYM_NAME matches SEARCH_NAME, apart from + informational suffix. */ + +static int +full_match (const char *sym_name, const char *search_name) +{ + return !match_name (sym_name, search_name, 0); } + /* Add symbols from BLOCK matching identifier NAME in DOMAIN to vector *defn_symbols, updating the list of symbols in OBSTACKP - (if necessary). If WILD, treat as NAME with a wildcard prefix. + (if necessary). If WILD, treat as NAME with a wildcard prefix. OBJFILE is the section containing BLOCK. SYMTAB is recorded with each symbol added. */ @@ -5045,13 +5239,13 @@ ada_add_block_symbols (struct obstack *obstackp, found_sym = 0; if (wild) { - struct symbol *sym; - - ALL_BLOCK_SYMBOLS (block, iter, sym) + for (sym = dict_iter_match_first (BLOCK_DICT (block), name, + wild_match, &iter); + sym != NULL; sym = dict_iter_match_next (name, wild_match, &iter)) { if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), SYMBOL_DOMAIN (sym), domain) - && wild_match (name, name_len, SYMBOL_LINKAGE_NAME (sym))) + && wild_match (SYMBOL_LINKAGE_NAME (sym), name) == 0) { if (SYMBOL_CLASS (sym) == LOC_UNRESOLVED) continue; @@ -5069,29 +5263,25 @@ ada_add_block_symbols (struct obstack *obstackp, } else { - ALL_BLOCK_SYMBOLS (block, iter, sym) + for (sym = dict_iter_match_first (BLOCK_DICT (block), name, + full_match, &iter); + sym != NULL; sym = dict_iter_match_next (name, full_match, &iter)) { if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), SYMBOL_DOMAIN (sym), domain)) { - int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym), name_len); - - if (cmp == 0 - && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len)) - { - if (SYMBOL_CLASS (sym) != LOC_UNRESOLVED) + if (SYMBOL_CLASS (sym) != LOC_UNRESOLVED) + { + if (SYMBOL_IS_ARGUMENT (sym)) + arg_sym = sym; + else { - if (SYMBOL_IS_ARGUMENT (sym)) - arg_sym = sym; - else - { - found_sym = 1; - add_defn_to_vec (obstackp, - fixup_symbol_section (sym, objfile), - block); - } + found_sym = 1; + add_defn_to_vec (obstackp, + fixup_symbol_section (sym, objfile), + block); } - } + } } } } @@ -5300,7 +5490,7 @@ symbol_completion_add (VEC(char_ptr) **sv, } /* An object of this type is passed as the user_data argument to the - map_partial_symbol_names method. */ + expand_partial_symbol_names method. */ struct add_partial_datum { VEC(char_ptr) **completions; @@ -5312,15 +5502,14 @@ struct add_partial_datum int encoded; }; -/* A callback for map_partial_symbol_names. */ -static void -ada_add_partial_symbol_completions (const char *name, void *user_data) +/* A callback for expand_partial_symbol_names. */ +static int +ada_expand_partial_symbol_name (const char *name, void *user_data) { struct add_partial_datum *data = user_data; - - symbol_completion_add (data->completions, name, - data->text, data->text_len, data->text0, data->word, - data->wild_match, data->encoded); + + return symbol_completion_match (name, data->text, data->text_len, + data->wild_match, data->encoded) != NULL; } /* Return a list of possible symbol names completing TEXT0. The list @@ -5378,7 +5567,7 @@ ada_make_symbol_completion_list (char *text0, char *word) data.word = word; data.wild_match = wild_match; data.encoded = encoded; - map_partial_symbol_names (ada_add_partial_symbol_completions, &data); + expand_partial_symbol_names (ada_expand_partial_symbol_name, &data); } /* At this point scan through the misc symbol vectors and add each @@ -5450,7 +5639,7 @@ ada_make_symbol_completion_list (char *text0, char *word) { const size_t completions_size = VEC_length (char_ptr, completions) * sizeof (char *); - char **result = malloc (completions_size); + char **result = xmalloc (completions_size); memcpy (result, VEC_address (char_ptr, completions), completions_size); @@ -5514,7 +5703,7 @@ ada_is_ignored_field (struct type *type, int field_num) } /* True iff TYPE has a tag field. If REFOK, then TYPE may also be a - pointer or reference type whose ultimate target has a tag field. */ + pointer or reference type whose ultimate target has a tag field. */ int ada_is_tagged_type (struct type *type, int refok) @@ -5556,7 +5745,7 @@ ada_value_tag (struct value *val) /* The value of the tag on the object of type TYPE whose contents are saved at VALADDR, if it is non-null, or is at memory address - ADDRESS. */ + ADDRESS. */ static struct value * value_tag_from_contents_and_address (struct type *type, @@ -5600,7 +5789,7 @@ static int ada_tag_name_1 (void *); static int ada_tag_name_2 (struct tag_args *); /* Wrapper function used by ada_tag_name. Given a struct tag_args* - value ARGS, sets ARGS->name to the tag name of ARGS->tag. + value ARGS, sets ARGS->name to the tag name of ARGS->tag. The value stored in ARGS->name is valid until the next call to ada_tag_name_1. */ @@ -5642,7 +5831,7 @@ ada_get_tsd_type (struct inferior *inf) /* Utility function for ada_tag_name_1 that tries the second representation for the dispatch table (in which there is no explicit 'tsd' field in the referent of the tag pointer, and instead - the tsd pointer is stored just before the dispatch table. */ + the tsd pointer is stored just before the dispatch table. */ static int ada_tag_name_2 (struct tag_args *args) @@ -5933,7 +6122,7 @@ ada_in_variant (LONGEST val, struct type *type, int field_num) } } -/* FIXME: Lots of redundancy below. Try to consolidate. */ +/* FIXME: Lots of redundancy below. Try to consolidate. */ /* Given a value ARG1 (offset by OFFSET bytes) of a struct or union type ARG_TYPE, extract and return the value of one of its (non-static) @@ -5977,7 +6166,7 @@ ada_value_primitive_field (struct value *arg1, int offset, int fieldno, number of fields if not found. A NULL value of NAME never matches; the function just counts visible fields in this case. - Returns 1 if found, 0 otherwise. */ + Returns 1 if found, 0 otherwise. */ static int find_struct_field (char *name, struct type *type, int offset, @@ -6052,7 +6241,7 @@ find_struct_field (char *name, struct type *type, int offset, return 0; } -/* Number of user-visible fields in record type TYPE. */ +/* Number of user-visible fields in record type TYPE. */ static int num_visible_fields (struct type *type) @@ -6089,7 +6278,7 @@ ada_search_struct_field (char *name, struct value *arg, int offset, else if (ada_is_wrapper_field (type, i)) { - struct value *v = /* Do not let indent join lines here. */ + struct value *v = /* Do not let indent join lines here. */ ada_search_struct_field (name, arg, offset + TYPE_FIELD_BITPOS (type, i) / 8, TYPE_FIELD_TYPE (type, i)); @@ -6100,7 +6289,7 @@ ada_search_struct_field (char *name, struct value *arg, int offset, else if (ada_is_variant_part (type, i)) { - /* PNH: Do we ever get here? See find_struct_field. */ + /* PNH: Do we ever get here? See find_struct_field. */ int j; struct type *field_type = ada_check_typedef (TYPE_FIELD_TYPE (type, i)); @@ -6108,7 +6297,8 @@ ada_search_struct_field (char *name, struct value *arg, int offset, for (j = 0; j < TYPE_NFIELDS (field_type); j += 1) { - struct value *v = ada_search_struct_field /* Force line break. */ + struct value *v = ada_search_struct_field /* Force line + break. */ (name, arg, var_offset + TYPE_FIELD_BITPOS (field_type, j) / 8, TYPE_FIELD_TYPE (field_type, j)); @@ -6128,7 +6318,7 @@ static struct value *ada_index_struct_field_1 (int *, struct value *, /* Return field #INDEX in ARG, where the index is that returned by * find_struct_field through its INDEX_P argument. Adjust the address * of ARG by OFFSET bytes, and search in it assuming it has (class) type TYPE. - * If found, return value, else return NULL. */ + * If found, return value, else return NULL. */ static struct value * ada_index_struct_field (int index, struct value *arg, int offset, @@ -6140,7 +6330,7 @@ ada_index_struct_field (int index, struct value *arg, int offset, /* Auxiliary function for ada_index_struct_field. Like * ada_index_struct_field, but takes index from *INDEX_P and modifies - * *INDEX_P. */ + * *INDEX_P. */ static struct value * ada_index_struct_field_1 (int *index_p, struct value *arg, int offset, @@ -6155,7 +6345,7 @@ ada_index_struct_field_1 (int *index_p, struct value *arg, int offset, continue; else if (ada_is_wrapper_field (type, i)) { - struct value *v = /* Do not let indent join lines here. */ + struct value *v = /* Do not let indent join lines here. */ ada_index_struct_field_1 (index_p, arg, offset + TYPE_FIELD_BITPOS (type, i) / 8, TYPE_FIELD_TYPE (type, i)); @@ -6167,7 +6357,7 @@ ada_index_struct_field_1 (int *index_p, struct value *arg, int offset, else if (ada_is_variant_part (type, i)) { /* PNH: Do we ever get here? See ada_search_struct_field, - find_struct_field. */ + find_struct_field. */ error (_("Cannot assign this kind of variant record")); } else if (*index_p == 0) @@ -6271,7 +6461,8 @@ ada_value_struct_elt (struct value *arg, char *name, int no_err) if (no_err) return NULL; else - error (_("Attempt to extract a component of a value that is not a record.")); + error (_("Attempt to extract a component of " + "a value that is not a record.")); } /* Given a type TYPE, look up the type of the component of type named NAME. @@ -6282,7 +6473,7 @@ ada_value_struct_elt (struct value *arg, char *name, int no_err) Matches any field whose name has NAME as a prefix, possibly followed by "___". - TYPE can be either a struct or union. If REFOK, TYPE may also + TYPE can be either a struct or union. If REFOK, TYPE may also be a (pointer or reference)+ to a struct or union, and the ultimate target type will be searched. @@ -6374,14 +6565,15 @@ ada_lookup_struct_elt_type (struct type *type, char *name, int refok, /* FIXME pnh 2008/01/26: We check for a field that is NOT wrapped in a struct, since the compiler sometimes generates these for unchecked variant types. Revisit - if the compiler changes this practice. */ + if the compiler changes this practice. */ char *v_field_name = TYPE_FIELD_NAME (field_type, j); disp = 0; if (v_field_name != NULL && field_name_match (v_field_name, name)) t = ada_check_typedef (TYPE_FIELD_TYPE (field_type, j)); else - t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, j), + t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, + j), name, 0, 1, &disp); if (t != NULL) @@ -6422,7 +6614,7 @@ BadName: /* Assuming that VAR_TYPE is the type of a variant part of a record (a union), within a value of type OUTER_TYPE, return true iff VAR_TYPE represents an unchecked union (that is, the variant part of a - record that is named in an Unchecked_Union pragma). */ + record that is named in an Unchecked_Union pragma). */ static int is_unchecked_variant (struct type *var_type, struct type *outer_type) @@ -6620,7 +6812,7 @@ ada_find_renaming_symbol (const char *name, struct block *block) if (sym != NULL) return sym; - /* Not right yet. FIXME pnh 7/20/2007. */ + /* Not right yet. FIXME pnh 7/20/2007. */ sym = ada_find_any_symbol (name); if (sym != NULL && strstr (SYMBOL_LINKAGE_NAME (sym), "___XR") != NULL) return sym; @@ -6915,7 +7107,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, int nfields, bit_len; int variant_field; long off; - int fld_bit_len, bit_incr; + int fld_bit_len; int f; /* Compute the number of fields in this record type that are going @@ -6957,7 +7149,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, if (ada_is_variant_part (type, f)) { variant_field = f; - fld_bit_len = bit_incr = 0; + fld_bit_len = 0; } else if (is_dynamic_field (type, f)) { @@ -6971,7 +7163,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, /* rtype's length is computed based on the run-time value of discriminants. If the discriminants are not initialized, the type size may be completely bogus and - GDB may fail to allocate a value for it. So check the + GDB may fail to allocate a value for it. So check the size first before creating the value. */ check_size (rtype); dval = value_from_contents_and_address (rtype, valaddr, address); @@ -7007,28 +7199,51 @@ ada_template_to_fixed_record_type_1 (struct type *type, field_type = ada_get_base_type (field_type); field_type = ada_to_fixed_type (field_type, field_valaddr, field_address, dval, 0); + /* If the field size is already larger than the maximum + object size, then the record itself will necessarily + be larger than the maximum object size. We need to make + this check now, because the size might be so ridiculously + large (due to an uninitialized variable in the inferior) + that it would cause an overflow when adding it to the + record size. */ + check_size (field_type); TYPE_FIELD_TYPE (rtype, f) = field_type; TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f); - bit_incr = fld_bit_len = + /* The multiplication can potentially overflow. But because + the field length has been size-checked just above, and + assuming that the maximum size is a reasonable value, + an overflow should not happen in practice. So rather than + adding overflow recovery code to this already complex code, + we just assume that it's not going to happen. */ + fld_bit_len = TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT; } else { struct type *field_type = TYPE_FIELD_TYPE (type, f); + /* If our field is a typedef type (most likely a typedef of + a fat pointer, encoding an array access), then we need to + look at its target type to determine its characteristics. + In particular, we would miscompute the field size if we took + the size of the typedef (zero), instead of the size of + the target type. */ + if (TYPE_CODE (field_type) == TYPE_CODE_TYPEDEF) + field_type = ada_typedef_target_type (field_type); + TYPE_FIELD_TYPE (rtype, f) = field_type; TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f); if (TYPE_FIELD_BITSIZE (type, f) > 0) - bit_incr = fld_bit_len = + fld_bit_len = TYPE_FIELD_BITSIZE (rtype, f) = TYPE_FIELD_BITSIZE (type, f); else - bit_incr = fld_bit_len = + fld_bit_len = TYPE_LENGTH (ada_check_typedef (field_type)) * TARGET_CHAR_BIT; } if (off + fld_bit_len > bit_len) bit_len = off + fld_bit_len; - off += bit_incr; + off += fld_bit_len; TYPE_LENGTH (rtype) = align_value (bit_len, TARGET_CHAR_BIT) / TARGET_CHAR_BIT; } @@ -7077,7 +7292,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, should contain the alignment of that record, which should be a strictly positive value. If null or negative, then something is wrong, most probably in the debug info. In that case, we don't round up the size - of the resulting type. If this record is not part of another structure, + of the resulting type. If this record is not part of another structure, the current RTYPE length might be good enough for our purposes. */ if (TYPE_LENGTH (type) <= 0) { @@ -7283,7 +7498,7 @@ to_fixed_record_type (struct type *type0, const gdb_byte *valaddr, a record value. That is, this routine selects the appropriate branch of the union at ADDR according to the discriminant value indicated in the union's type name. Returns VAR_TYPE0 itself if - it represents a variant subject to a pragma Unchecked_Union. */ + it represents a variant subject to a pragma Unchecked_Union. */ static struct type * to_fixed_variant_branch_type (struct type *var_type0, const gdb_byte *valaddr, @@ -7339,6 +7554,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, struct type *result; int constrained_packed_array_p; + type0 = ada_check_typedef (type0); if (TYPE_FIXED_INSTANCE (type0)) return type0; @@ -7460,7 +7676,7 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr, /* If STATIC_TYPE is a tagged type and we know the object's address, then we can determine its tag, and compute the object's actual - type from there. Note that we have to use the fixed record + type from there. Note that we have to use the fixed record type (the parent part of the record may have dynamic fields and the way the location of _tag is expressed may depend on them). */ @@ -7508,7 +7724,7 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr, when using this type to create new types targeting it. Indeed, the associated creation routines often check whether the target type is a stub and will try to replace - it, thus using a type with the wrong size. This, in turn, + it, thus using a type with the wrong size. This, in turn, might cause the new type to have the wrong size too. Consider the case of an array, for instance, where the size of the array is computed from the number of elements in @@ -7530,7 +7746,23 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr, /* The same as ada_to_fixed_type_1, except that it preserves the type if it is a TYPE_CODE_TYPEDEF of a type that is already fixed. - ada_to_fixed_type_1 would return the type referenced by TYPE. */ + + The typedef layer needs be preserved in order to differentiate between + arrays and array pointers when both types are implemented using the same + fat pointer. In the array pointer case, the pointer is encoded as + a typedef of the pointer type. For instance, considering: + + type String_Access is access String; + S1 : String_Access := null; + + To the debugger, S1 is defined as a typedef of type String. But + to the user, it is a pointer. So if the user tries to print S1, + we should not dereference the array, but print the array address + instead. + + If we didn't preserve the typedef layer, we would lose the fact that + the type is to be presented as a pointer (needs de-reference before + being printed). And we would also use the source-level type name. */ struct type * ada_to_fixed_type (struct type *type, const gdb_byte *valaddr, @@ -7540,8 +7772,26 @@ ada_to_fixed_type (struct type *type, const gdb_byte *valaddr, struct type *fixed_type = ada_to_fixed_type_1 (type, valaddr, address, dval, check_tag); + /* If TYPE is a typedef and its target type is the same as the FIXED_TYPE, + then preserve the typedef layer. + + Implementation note: We can only check the main-type portion of + the TYPE and FIXED_TYPE, because eliminating the typedef layer + from TYPE now returns a type that has the same instance flags + as TYPE. For instance, if TYPE is a "typedef const", and its + target type is a "struct", then the typedef elimination will return + a "const" version of the target type. See check_typedef for more + details about how the typedef layer elimination is done. + + brobecker/2010-11-19: It seems to me that the only case where it is + useful to preserve the typedef layer is when dealing with fat pointers. + Perhaps, we could add a check for that and preserve the typedef layer + only in that situation. But this seems unecessary so far, probably + because we call check_typedef/ada_check_typedef pretty much everywhere. + */ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF - && TYPE_TARGET_TYPE (type) == fixed_type) + && (TYPE_MAIN_TYPE (ada_typedef_target_type (type)) + == TYPE_MAIN_TYPE (fixed_type))) return type; return fixed_type; @@ -7626,6 +7876,15 @@ ada_check_typedef (struct type *type) if (type == NULL) return NULL; + /* If our type is a typedef type of a fat pointer, then we're done. + We don't want to strip the TYPE_CODE_TYPDEF layer, because this is + what allows us to distinguish between fat pointers that represent + array types, and fat pointers that represent array access types + (in both cases, the compiler implements them as fat pointers). */ + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF + && is_thick_pntr (ada_typedef_target_type (type))) + return type; + CHECK_TYPEDEF (type); if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM || !TYPE_STUB (type) @@ -7636,7 +7895,17 @@ ada_check_typedef (struct type *type) char *name = TYPE_TAG_NAME (type); struct type *type1 = ada_find_any_type (name); - return (type1 == NULL) ? type : type1; + if (type1 == NULL) + return type; + + /* TYPE1 might itself be a TYPE_CODE_TYPEDEF (this can happen with + stubs pointing to arrays, as we don't create symbols for array + types, only for the typedef-to-array types). If that's the case, + strip the typedef layer. */ + if (TYPE_CODE (type1) == TYPE_CODE_TYPEDEF) + type1 = ada_check_typedef (type1); + + return type1; } } @@ -8180,7 +8449,7 @@ ada_value_equal (struct value *arg1, struct value *arg2) /* Total number of component associations in the aggregate starting at index PC in EXP. Assumes that index PC is the start of an - OP_AGGREGATE. */ + OP_AGGREGATE. */ static int num_component_specs (struct expression *exp, int pc) @@ -8248,7 +8517,7 @@ assign_component (struct value *container, struct value *lhs, LONGEST index, aggregate. NOSIDE is as for evaluate_subexp. CONTAINER is an lvalue containing LHS (possibly LHS itself). Does not modify the inferior's memory, nor does it modify the contents of - LHS (unless == CONTAINER). Returns the modified CONTAINER. */ + LHS (unless == CONTAINER). Returns the modified CONTAINER. */ static struct value * assign_aggregate (struct value *container, @@ -8339,7 +8608,7 @@ assign_aggregate (struct value *container, the positions are relative to lower bound LOW, where HIGH is the upper bound. Record the position in INDICES[0 .. MAX_INDICES-1] updating *NUM_INDICES as needed. CONTAINER is as for - assign_aggregate. */ + assign_aggregate. */ static void aggregate_assign_positional (struct value *container, struct value *lhs, struct expression *exp, @@ -8364,7 +8633,7 @@ aggregate_assign_positional (struct value *container, construct at *POS, updating *POS past the construct, given that the allowable indices are LOW..HIGH. Record the indices assigned to in INDICES[0 .. MAX_INDICES-1], updating *NUM_INDICES as - needed. CONTAINER is as for assign_aggregate. */ + needed. CONTAINER is as for assign_aggregate. */ static void aggregate_assign_from_choices (struct value *container, struct value *lhs, struct expression *exp, @@ -8446,7 +8715,7 @@ aggregate_assign_from_choices (struct value *container, EXP at *POS into the components of LHS indexed from LOW .. HIGH that have not been previously assigned. The index intervals already assigned are in INDICES[0 .. NUM_INDICES-1]. Updates *POS to after the - OP_OTHERS clause. CONTAINER is as for assign_aggregate*/ + OP_OTHERS clause. CONTAINER is as for assign_aggregate. */ static void aggregate_assign_others (struct value *container, struct value *lhs, struct expression *exp, @@ -8454,7 +8723,7 @@ aggregate_assign_others (struct value *container, LONGEST low, LONGEST high) { int i; - int expr_pc = *pos+1; + int expr_pc = *pos + 1; for (i = 0; i < num_indices - 2; i += 2) { @@ -8462,10 +8731,10 @@ aggregate_assign_others (struct value *container, for (ind = indices[i + 1] + 1; ind < indices[i + 2]; ind += 1) { - int pos; + int localpos; - pos = expr_pc; - assign_component (container, lhs, ind, exp, &pos); + localpos = expr_pc; + assign_component (container, lhs, ind, exp, &localpos); } } ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP); @@ -8911,7 +9180,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, if ((ada_is_fixed_point_type (value_type (arg1)) || ada_is_fixed_point_type (value_type (arg2))) && value_type (arg1) != value_type (arg2)) - error (_("Operands of fixed-point subtraction must have the same type")); + error (_("Operands of fixed-point subtraction " + "must have the same type")); /* Do the substraction, and cast the result to the type of the first argument. We cannot cast the result to a reference type, so if ARG1 is a reference type, find its underlying type. */ @@ -9109,6 +9379,13 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, argvec[0] = value_addr (argvec[0]); type = ada_check_typedef (value_type (argvec[0])); + + /* Ada allows us to implicitly dereference arrays when subscripting + them. So, if this is an typedef (encoding use for array access + types encoded as fat pointers), strip it now. */ + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + type = ada_typedef_target_type (type); + if (TYPE_CODE (type) == TYPE_CODE_PTR) { switch (TYPE_CODE (ada_check_typedef (TYPE_TARGET_TYPE (type)))) @@ -9621,7 +9898,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, else error (_("Attempt to take contents of a non-pointer value.")); } - arg1 = ada_coerce_ref (arg1); /* FIXME: What is this for?? */ + arg1 = ada_coerce_ref (arg1); /* FIXME: What is this for?? */ type = ada_check_typedef (value_type (arg1)); if (TYPE_CODE (type) == TYPE_CODE_INT) @@ -9662,7 +9939,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, /* In this case, we assume that the field COULD exist in some extension of the type. Return an object of "type" void, which will match any formal - (see ada_type_match). */ + (see ada_type_match). */ return value_zero (builtin_type (exp->gdbarch)->builtin_void, lval_memory); } @@ -9704,7 +9981,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, case OP_AGGREGATE: error (_("Aggregates only allowed on the right of an assignment")); default: - internal_error (__FILE__, __LINE__, _("aggregate apparently mangled")); + internal_error (__FILE__, __LINE__, + _("aggregate apparently mangled")); } ada_forward_operator_length (exp, pc, &oplen, &nargs); @@ -9987,7 +10265,7 @@ to_fixed_range_type (struct type *raw_type, struct value *dval) return raw_type; if (bounds_str[n] == '_') n += 2; - else if (bounds_str[n] == '.') /* FIXME? SGI Workshop kludge. */ + else if (bounds_str[n] == '.') /* FIXME? SGI Workshop kludge. */ n += 1; subtype_info += 1; } @@ -10258,7 +10536,7 @@ ada_exception_support_info_sniffer (void) /* At this point, we know that we are debugging an Ada program and that the inferior has been started, but we still are not able to - find the run-time symbols. That can mean that we are in + find the run-time symbols. That can mean that we are in configurable run time mode, or that a-except as been optimized out by the linker... In any case, at this point it is not worth supporting this feature. */ @@ -10325,7 +10603,7 @@ is_known_support_routine (struct frame_info *frame) /* Check whether the function is a GNAT-generated entity. */ - find_frame_funname (frame, &func_name, &func_lang); + find_frame_funname (frame, &func_name, &func_lang, NULL); if (func_name == NULL) return 1; @@ -10393,7 +10671,7 @@ ada_unhandled_exception_name_addr_from_raise (void) char *func_name; enum language func_lang; - find_frame_funname (fi, &func_name, &func_lang); + find_frame_funname (fi, &func_name, &func_lang, NULL); if (func_name != NULL && strcmp (func_name, exception_info->catch_exception_sym) == 0) break; /* We found the frame we were looking for... */ @@ -10471,40 +10749,63 @@ ada_exception_name_addr (enum exception_catchpoint_kind ex, static enum print_stop_action print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) { - const CORE_ADDR addr = ada_exception_name_addr (ex, b); - char exception_name[256]; + annotate_catchpoint (b->number); - if (addr != 0) + if (ui_out_is_mi_like_p (uiout)) { - read_memory (addr, exception_name, sizeof (exception_name) - 1); - exception_name [sizeof (exception_name) - 1] = '\0'; + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); } - ada_find_printable_frame (get_current_frame ()); + ui_out_text (uiout, "\nCatchpoint "); + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); - annotate_catchpoint (b->number); switch (ex) { case ex_catch_exception: - if (addr != 0) - printf_filtered (_("\nCatchpoint %d, %s at "), - b->number, exception_name); - else - printf_filtered (_("\nCatchpoint %d, exception at "), b->number); - break; case ex_catch_exception_unhandled: - if (addr != 0) - printf_filtered (_("\nCatchpoint %d, unhandled %s at "), - b->number, exception_name); - else - printf_filtered (_("\nCatchpoint %d, unhandled exception at "), - b->number); - break; + { + const CORE_ADDR addr = ada_exception_name_addr (ex, b); + char exception_name[256]; + + if (addr != 0) + { + read_memory (addr, exception_name, sizeof (exception_name) - 1); + exception_name [sizeof (exception_name) - 1] = '\0'; + } + else + { + /* For some reason, we were unable to read the exception + name. This could happen if the Runtime was compiled + without debugging info, for instance. In that case, + just replace the exception name by the generic string + "exception" - it will read as "an exception" in the + notification we are about to print. */ + sprintf (exception_name, "exception"); + } + /* In the case of unhandled exception breakpoints, we print + the exception name as "unhandled EXCEPTION_NAME", to make + it clearer to the user which kind of catchpoint just got + hit. We used ui_out_text to make sure that this extra + info does not pollute the exception name in the MI case. */ + if (ex == ex_catch_exception_unhandled) + ui_out_text (uiout, "unhandled "); + ui_out_field_string (uiout, "exception-name", exception_name); + } + break; case ex_catch_assert: - printf_filtered (_("\nCatchpoint %d, failed assertion at "), - b->number); - break; + /* In this case, the name of the exception is not really + important. Just print "failed assertion" to make it clearer + that his program just hit an assertion-failure catchpoint. + We used ui_out_text because this info does not belong in + the MI output. */ + ui_out_text (uiout, "failed assertion"); + break; } + ui_out_text (uiout, " at "); + ada_find_printable_frame (get_current_frame ()); return PRINT_SRC_AND_LOC; } @@ -10648,8 +10949,10 @@ static struct breakpoint_ops catch_exception_breakpoint_ops = NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ + NULL, /* resources_needed */ print_it_catch_exception, print_one_catch_exception, + NULL, /* print_one_detail */ print_mention_catch_exception, print_recreate_catch_exception }; @@ -10686,8 +10989,10 @@ static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ + NULL, /* resources_needed */ print_it_catch_exception_unhandled, print_one_catch_exception_unhandled, + NULL, /* print_one_detail */ print_mention_catch_exception_unhandled, print_recreate_catch_exception_unhandled }; @@ -10722,8 +11027,10 @@ static struct breakpoint_ops catch_assert_breakpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ + NULL, /* resources_needed */ print_it_catch_assert, print_one_catch_assert, + NULL, /* print_one_detail */ print_mention_catch_assert, print_recreate_catch_assert }; @@ -10886,17 +11193,17 @@ ada_exception_catchpoint_cond_string (const char *exp_string) { int i; - /* The standard exceptions are a special case. They are defined in + /* The standard exceptions are a special case. They are defined in runtime units that have been compiled without debugging info; if EXP_STRING is the not-fully-qualified name of a standard exception (e.g. "constraint_error") then, during the evaluation of the condition expression, the symbol lookup on this name would - *not* return this standard exception. The catchpoint condition + *not* return this standard exception. The catchpoint condition may then be set only on user-defined exceptions which have the same not-fully-qualified name (e.g. my_package.constraint_error). To avoid this unexcepted behavior, these standard exceptions are - systematically prefixed by "standard". This means that "catch + systematically prefixed by "standard". This means that "catch exception constraint_error" is rewritten into "catch exception standard.constraint_error". @@ -11563,7 +11870,8 @@ const struct language_defn ada_language_defn = { ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */ basic_lookup_transparent_type, /* lookup_transparent_type */ ada_la_decode, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ ada_op_print_tab, /* expression operators for printing */ 0, /* c-style arrays */ 1, /* String lower bound */ diff --git a/contrib/gdb-7/gdb/ada-lang.h b/contrib/gdb-7/gdb/ada-lang.h index d1e8ca50c5..7902124c07 100644 --- a/contrib/gdb-7/gdb/ada-lang.h +++ b/contrib/gdb-7/gdb/ada-lang.h @@ -1,7 +1,7 @@ /* Ada language support definitions for GDB, the GNU debugger. Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -30,7 +30,7 @@ struct frame_info; /* Names of specific files known to be part of the runtime system and that might consider (confusing) debugging information. Each name (a basic regular expression string) is followed by a - comma. FIXME: Should be part of a configuration file. */ + comma. FIXME: Should be part of a configuration file. */ #if defined(__alpha__) && defined(__osf__) #define ADA_KNOWN_RUNTIME_FILE_NAME_PATTERNS \ "^[agis]-.*\\.ad[bs]$", \ @@ -48,25 +48,26 @@ struct frame_info; #endif /* Names of compiler-generated auxiliary functions probably of no - interest to users. Each name (a basic regular expression string) - is followed by a comma. */ + interest to users. Each name (a basic regular expression string) + is followed by a comma. */ #define ADA_KNOWN_AUXILIARY_FUNCTION_NAME_PATTERNS \ - "___clean[.$a-zA-Z0-9_]*$", + "___clean[.$a-zA-Z0-9_]*$", \ + "___finalizer[.$a-zA-Z0-9_]*$", /* The maximum number of frame levels searched for non-local, * non-global symbols. This limit exists as a precaution to prevent - * infinite search loops when the stack is screwed up. */ + * infinite search loops when the stack is screwed up. */ #define MAX_ENCLOSING_FRAME_LEVELS 7 /* Maximum number of steps followed in looking for the ultimate referent of a renaming. This prevents certain infinite loops that - can otherwise result. */ + can otherwise result. */ #define MAX_RENAMING_CHAIN_LENGTH 10 struct block; /* Corresponding encoded/decoded names and opcodes for Ada user-definable - operators. */ + operators. */ struct ada_opname_map { const char *encoded; @@ -74,12 +75,12 @@ struct ada_opname_map enum exp_opcode op; }; -/* Table of Ada operators in encoded and decoded forms. */ +/* Table of Ada operators in encoded and decoded forms. */ /* Defined in ada-lang.c */ extern const struct ada_opname_map ada_opname_table[]; /* A tuple, (symbol, block), representing one instance of a - * symbol-lookup operation. */ + * symbol-lookup operation. */ struct ada_symbol_info { struct symbol* sym; struct block* block; @@ -140,9 +141,9 @@ struct ada_task_info }; /* Assuming V points to an array of S objects, make sure that it contains at - least M objects, updating V and S as necessary. */ + least M objects, updating V and S as necessary. */ -#define GROW_VECT(v, s, m) \ +#define GROW_VECT(v, s, m) \ if ((s) < (m)) (v) = grow_vect (v, &(s), m, sizeof *(v)); extern void *grow_vect (void *, size_t *, size_t, int); @@ -181,9 +182,7 @@ extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *, const struct value_print_options *); struct value *ada_convert_actual (struct value *actual, - struct type *formal_type0, - struct gdbarch *gdbarch, - CORE_ADDR *sp); + struct type *formal_type0); extern struct value *ada_value_subscript (struct value *, int, struct value **); @@ -198,6 +197,8 @@ struct type *ada_type_of_array (struct value *, int); extern struct value *ada_coerce_to_simple_array_ptr (struct value *); +struct value *ada_coerce_to_simple_array (struct value *); + extern int ada_is_simple_array_type (struct type *); extern int ada_is_array_descriptor_type (struct type *); @@ -378,6 +379,10 @@ extern int valid_task_id (int); extern int ada_get_task_number (ptid_t); +typedef void (ada_task_list_iterator_ftype) (struct ada_task_info *task); +extern void iterate_over_live_ada_tasks + (ada_task_list_iterator_ftype *iterator); + extern int ada_build_task_list (int warn_if_null); extern int ada_exception_catchpoint_p (struct breakpoint *b); diff --git a/contrib/gdb-7/gdb/ada-lex.c b/contrib/gdb-7/gdb/ada-lex.c index dc76ff27b3..aea4684c50 100644 --- a/contrib/gdb-7/gdb/ada-lex.c +++ b/contrib/gdb-7/gdb/ada-lex.c @@ -609,7 +609,7 @@ char *yytext; #define INITIAL 0 /* FLEX lexer for Ada expressions, for GDB. Copyright (C) 1994, 1997, 1998, 2000, 2001, 2002, 2003, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ada-operator.def b/contrib/gdb-7/gdb/ada-operator.def new file mode 100644 index 0000000000..c3dc8e1716 --- /dev/null +++ b/contrib/gdb-7/gdb/ada-operator.def @@ -0,0 +1,99 @@ +/* Ada language operator definitions for GDB, the GNU debugger. + + Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* X IN A'RANGE(N). N is an immediate operand, surrounded by + BINOP_IN_BOUNDS before and after. A is an array, X an index + value. Evaluates to true iff X is within range of the Nth + dimension (1-based) of A. (A multi-dimensional array + type is represented as array of array of ...) */ +OP (BINOP_IN_BOUNDS) + +/* X IN L .. U. True iff L <= X <= U. */ +OP (TERNOP_IN_RANGE) + +/* Ada attributes ('Foo). */ +OP (OP_ATR_FIRST) +OP (OP_ATR_LAST) +OP (OP_ATR_LENGTH) +OP (OP_ATR_IMAGE) +OP (OP_ATR_MAX) +OP (OP_ATR_MIN) +OP (OP_ATR_MODULUS) +OP (OP_ATR_POS) +OP (OP_ATR_SIZE) +OP (OP_ATR_TAG) +OP (OP_ATR_VAL) + +/* Ada type qualification. It is encoded as for UNOP_CAST, above, + and denotes the TYPE'(EXPR) construct. */ +OP (UNOP_QUAL) + +/* X IN TYPE. The `TYPE' argument is immediate, with + UNOP_IN_RANGE before and after it. True iff X is a member of + type TYPE (typically a subrange). */ +OP (UNOP_IN_RANGE) + +/* An aggregate. A single immediate operand, N>0, gives + the number of component specifications that follow. The + immediate operand is followed by a second OP_AGGREGATE. + Next come N component specifications. A component + specification is either an OP_OTHERS (others=>...), an + OP_CHOICES (for named associations), or other expression (for + positional aggregates only). Aggregates currently + occur only as the right sides of assignments. */ +OP (OP_AGGREGATE) + +/* An others clause. Followed by a single expression. */ +OP (OP_OTHERS) + +/* An aggregate component association. A single immediate operand, N, + gives the number of choices that follow. This is followed by a second + OP_CHOICES operator. Next come N operands, each of which is an + expression, an OP_DISCRETE_RANGE, or an OP_NAME---the latter + for a simple name that must be a record component name and does + not correspond to a single existing symbol. After the N choice + indicators comes an expression giving the value. + + In an aggregate such as (X => E1, ...), where X is a simple + name, X could syntactically be either a component_selector_name + or an expression used as a discrete_choice, depending on the + aggregate's type context. Since this is not known at parsing + time, we don't attempt to disambiguate X if it has multiple + definitions, but instead supply an OP_NAME. If X has a single + definition, we represent it with an OP_VAR_VALUE, even though + it may turn out to be within a record aggregate. Aggregate + evaluation can use either OP_NAMEs or OP_VAR_VALUEs to get a + record field name, and can evaluate OP_VAR_VALUE normally to + get its value as an expression. Unfortunately, we lose out in + cases where X has multiple meanings and is part of an array + aggregate. I hope these are not common enough to annoy users, + who can work around the problem in any case by putting + parentheses around X. */ +OP (OP_CHOICES) + +/* A positional aggregate component association. The operator is + followed by a single integer indicating the position in the + aggregate (0-based), followed by a second OP_POSITIONAL. Next + follows a single expression giving the component value. */ +OP (OP_POSITIONAL) + +/* A range of values. Followed by two expressions giving the + upper and lower bounds of the range. */ +OP (OP_DISCRETE_RANGE) diff --git a/contrib/gdb-7/gdb/ada-tasks.c b/contrib/gdb-7/gdb/ada-tasks.c index f57f44ff96..2cf62b9326 100644 --- a/contrib/gdb-7/gdb/ada-tasks.c +++ b/contrib/gdb-7/gdb/ada-tasks.c @@ -1,5 +1,5 @@ /* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -29,7 +29,7 @@ Block of each task is stored. */ #define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks" -/* The maximum number of tasks known to the Ada runtime */ +/* The maximum number of tasks known to the Ada runtime. */ static const int MAX_NUMBER_OF_KNOWN_TASKS = 1000; enum task_states @@ -126,7 +126,7 @@ struct tcb_fieldnos }; /* The type description for the ATCB record and subrecords, and - the associated tcb_fieldnos. For efficiency reasons, these are made + the associated tcb_fieldnos. For efficiency reasons, these are made static globals so that we can compute them only once the first time and reuse them later. Set to NULL if the types haven't been computed yet, or if they may be obsolete (for instance after having loaded @@ -212,6 +212,27 @@ ada_task_is_alive (struct ada_task_info *task_info) return (task_info->state != Terminated); } +/* Call the ITERATOR function once for each Ada task that hasn't been + terminated yet. */ + +void +iterate_over_live_ada_tasks (ada_task_list_iterator_ftype *iterator) +{ + int i, nb_tasks; + struct ada_task_info *task; + + ada_build_task_list (0); + nb_tasks = VEC_length (ada_task_info_s, task_list); + + for (i = 0; i < nb_tasks; i++) + { + task = VEC_index (ada_task_info_s, task_list, i); + if (!ada_task_is_alive (task)) + continue; + iterator (task); + } +} + /* Extract the contents of the value as a string whose length is LENGTH, and store the result in DEST. */ @@ -279,12 +300,12 @@ read_fat_string_value (char *dest, struct value *val, int max_len) } /* Return the address of the Known_Tasks array maintained in - the Ada Runtime. Return NULL if the array could not be found, + the Ada Runtime. Return zero if the array could not be found, meaning that the inferior program probably does not use tasking. In order to provide a fast response time, this function caches the Known_Tasks array address after the lookup during the first - call. Subsequent calls will simply return this cached address. */ + call. Subsequent calls will simply return this cached address. */ static CORE_ADDR get_known_tasks_addr (void) @@ -296,31 +317,27 @@ get_known_tasks_addr (void) struct minimal_symbol *msym; msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL); - if (msym != NULL) - known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym); - else - { - if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0) - return 0; - } + if (msym == NULL) + return 0; + known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym); /* FIXME: brobecker 2003-03-05: Here would be a much better place to attach the ada-tasks observers, instead of doing this - unconditionaly in _initialize_tasks. This would avoid an + unconditionaly in _initialize_tasks. This would avoid an unecessary notification when the inferior does not use tasking or as long as the user does not use the ada-tasks commands. Unfortunately, this is not possible for the moment: the current code resets ada__tasks_check_symbol_table back to 1 whenever - symbols for a new program are being loaded. If we place the + symbols for a new program are being loaded. If we place the observers intialization here, we will end up adding new observers everytime we do the check for Ada tasking-related symbols - above. This would currently have benign effects, but is still - undesirable. The cleanest approach is probably to create a new + above. This would currently have benign effects, but is still + undesirable. The cleanest approach is probably to create a new observer to notify us when the user is debugging a new program. We would then reset ada__tasks_check_symbol_table back to 1 during the notification, but also detach all observers. BTW: observers are probably not reentrant, so detaching during - a notification may not be the safest thing to do... Sigh... + a notification may not be the safest thing to do... Sigh... But creating the new observer would be a good idea in any case, since this allow us to make ada__tasks_check_symbol_table static, which is a good bonus. */ @@ -359,20 +376,29 @@ get_tcb_types_info (struct type **atcb_type, const char *private_data_name = "system__task_primitives__private_data"; const char *entry_call_record_name = "system__tasking__entry_call_record"; + /* ATCB symbols may be found in several compilation units. As we + are only interested in one instance, use standard (literal, + C-like) lookups to get the first match. */ + struct symbol *atcb_sym = - lookup_symbol (atcb_name, NULL, VAR_DOMAIN, NULL); + lookup_symbol_in_language (atcb_name, NULL, VAR_DOMAIN, + language_c, NULL); const struct symbol *common_atcb_sym = - lookup_symbol (common_atcb_name, NULL, VAR_DOMAIN, NULL); + lookup_symbol_in_language (common_atcb_name, NULL, VAR_DOMAIN, + language_c, NULL); const struct symbol *private_data_sym = - lookup_symbol (private_data_name, NULL, VAR_DOMAIN, NULL); + lookup_symbol_in_language (private_data_name, NULL, VAR_DOMAIN, + language_c, NULL); const struct symbol *entry_call_record_sym = - lookup_symbol (entry_call_record_name, NULL, VAR_DOMAIN, NULL); + lookup_symbol_in_language (entry_call_record_name, NULL, VAR_DOMAIN, + language_c, NULL); if (atcb_sym == NULL || atcb_sym->type == NULL) { /* In Ravenscar run-time libs, the ATCB does not have a dynamic size, so the symbol name differs. */ - atcb_sym = lookup_symbol (atcb_name_fixed, NULL, VAR_DOMAIN, NULL); + atcb_sym = lookup_symbol_in_language (atcb_name_fixed, NULL, VAR_DOMAIN, + language_c, NULL); if (atcb_sym == NULL || atcb_sym->type == NULL) error (_("Cannot find Ada_Task_Control_Block type. Aborting")); @@ -491,14 +517,14 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) Depending on the GNAT version used, the task image is either a fat string, or a thin array of characters. Older versions of GNAT used to use fat strings, and therefore did not need an extra field in - the ATCB to store the string length. For efficiency reasons, newer + the ATCB to store the string length. For efficiency reasons, newer versions of GNAT replaced the fat string by a static buffer, but this also required the addition of a new field named "Image_Len" containing - the length of the task name. The method used to extract the task name + the length of the task name. The method used to extract the task name is selected depending on the existence of this field. In some run-time libs (e.g. Ravenscar), the name is not in the ATCB; - we may want to get it from the first user frame of the stack. For now, + we may want to get it from the first user frame of the stack. For now, we just give a dummy name. */ if (fieldno.image_len == -1) @@ -583,9 +609,18 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) } } - /* And finally, compute the task ptid. */ - - if (ada_task_is_alive (task_info)) + /* And finally, compute the task ptid. Note that there are situations + where this cannot be determined: + - The task is no longer alive - the ptid is irrelevant; + - We are debugging a core file - the thread is not always + completely preserved for us to link back a task to its + underlying thread. Since we do not support task switching + when debugging core files anyway, we don't need to compute + that task ptid. + In either case, we don't need that ptid, and it is just good enough + to set it to null_ptid. */ + + if (target_has_execution && ada_task_is_alive (task_info)) task_info->ptid = ptid_from_atcb_common (common_value); else task_info->ptid = null_ptid; @@ -723,7 +758,7 @@ short_task_info (int taskno) } /* Print a list containing a short description of all Ada tasks. */ -/* FIXME: Shouldn't we be using ui_out??? */ +/* FIXME: Shouldn't we be using ui_out??? */ static void info_tasks (int from_tty) diff --git a/contrib/gdb-7/gdb/ada-typeprint.c b/contrib/gdb-7/gdb/ada-typeprint.c index a02c8d4fec..737e09730f 100644 --- a/contrib/gdb-7/gdb/ada-typeprint.c +++ b/contrib/gdb-7/gdb/ada-typeprint.c @@ -1,6 +1,6 @@ /* Support for printing Ada types for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -38,13 +38,17 @@ #include "gdb_string.h" #include +static int print_selected_record_field_types (struct type *, struct type *, + int, int, + struct ui_file *, int, int); + static int print_record_field_types (struct type *, struct type *, struct ui_file *, int, int); static void print_array_type (struct type *, struct ui_file *, int, int); -static void print_choices (struct type *, int, struct ui_file *, - struct type *); +static int print_choices (struct type *, int, struct ui_file *, + struct type *); static void print_range (struct type *, struct ui_file *); @@ -397,9 +401,13 @@ print_array_type (struct type *type, struct ui_file *stream, int show, } /* Print the choices encoded by field FIELD_NUM of variant-part TYPE on - STREAM, assuming that VAL_TYPE (if non-NULL) is the type of the values. */ + STREAM, assuming that VAL_TYPE (if non-NULL) is the type of the + values. Return non-zero if the field is an encoding of + discriminant values, as in a standard variant record, and 0 if the + field is not so encoded (as happens with single-component variants + in types annotated with pragma Unchecked_Variant). */ -static void +static int print_choices (struct type *type, int field_num, struct ui_file *stream, struct type *val_type) { @@ -423,7 +431,11 @@ print_choices (struct type *type, int field_num, struct ui_file *stream, switch (name[p]) { default: - return; + goto Huh; + case '_': + case '\0': + fprintf_filtered (stream, " =>"); + return 1; case 'S': case 'R': case 'O': @@ -464,18 +476,17 @@ print_choices (struct type *type, int field_num, struct ui_file *stream, } Huh: - fprintf_filtered (stream, "??"); - + fprintf_filtered (stream, "?? =>"); + return 0; } -/* Assuming that field FIELD_NUM of TYPE is a VARIANTS field whose - discriminant is contained in OUTER_TYPE, print its variants on STREAM. - LEVEL is the recursion - (indentation) level, in case any of the fields themselves have - nested structure, and SHOW is the number of levels of internal structure - to show (see ada_print_type). For this purpose, fields nested in a - variant part are taken to be at the same level as the fields - immediately outside the variant part. */ +/* Assuming that field FIELD_NUM of TYPE represents variants whose + discriminant is contained in OUTER_TYPE, print its components on STREAM. + LEVEL is the recursion (indentation) level, in case any of the fields + themselves have nested structure, and SHOW is the number of levels of + internal structure to show (see ada_print_type). For this purpose, + fields nested in a variant part are taken to be at the same level as + the fields immediately outside the variant part. */ static void print_variant_clauses (struct type *type, int field_num, @@ -503,11 +514,16 @@ print_variant_clauses (struct type *type, int field_num, for (i = 0; i < TYPE_NFIELDS (var_type); i += 1) { fprintf_filtered (stream, "\n%*swhen ", level + 4, ""); - print_choices (var_type, i, stream, discr_type); - fprintf_filtered (stream, " =>"); - if (print_record_field_types (TYPE_FIELD_TYPE (var_type, i), - outer_type, stream, show, level + 4) <= 0) - fprintf_filtered (stream, " null;"); + if (print_choices (var_type, i, stream, discr_type)) + { + if (print_record_field_types (TYPE_FIELD_TYPE (var_type, i), + outer_type, stream, show, level + 4) + <= 0) + fprintf_filtered (stream, " null;"); + } + else + print_selected_record_field_types (var_type, outer_type, i, i, + stream, show, level + 4); } } @@ -531,28 +547,28 @@ print_variant_part (struct type *type, int field_num, struct type *outer_type, fprintf_filtered (stream, "\n%*send case;", level + 4, ""); } -/* Print a description on STREAM of the fields in record type TYPE, whose - discriminants are in OUTER_TYPE. LEVEL is the recursion (indentation) - level, in case any of the fields themselves have nested structure, - and SHOW is the number of levels of internal structure to show - (see ada_print_type). Does not print parent type information of TYPE. - Returns 0 if no fields printed, -1 for an incomplete type, else > 0. - Prints each field beginning on a new line, but does not put a new line at - end. */ +/* Print a description on STREAM of the fields FLD0 through FLD1 in + record or union type TYPE, whose discriminants are in OUTER_TYPE. + LEVEL is the recursion (indentation) level, in case any of the + fields themselves have nested structure, and SHOW is the number of + levels of internal structure to show (see ada_print_type). Does + not print parent type information of TYPE. Returns 0 if no fields + printed, -1 for an incomplete type, else > 0. Prints each field + beginning on a new line, but does not put a new line at end. */ static int -print_record_field_types (struct type *type, struct type *outer_type, - struct ui_file *stream, int show, int level) +print_selected_record_field_types (struct type *type, struct type *outer_type, + int fld0, int fld1, + struct ui_file *stream, int show, int level) { - int len, i, flds; + int i, flds; flds = 0; - len = TYPE_NFIELDS (type); - if (len == 0 && TYPE_STUB (type)) + if (fld0 > fld1 && TYPE_STUB (type)) return -1; - for (i = 0; i < len; i += 1) + for (i = fld0; i <= fld1; i += 1) { QUIT; @@ -580,6 +596,19 @@ print_record_field_types (struct type *type, struct type *outer_type, return flds; } +/* Print a description on STREAM of all fields of record or union type + TYPE, as for print_selected_record_field_types, above. */ + +static int +print_record_field_types (struct type *type, struct type *outer_type, + struct ui_file *stream, int show, int level) +{ + return print_selected_record_field_types (type, outer_type, + 0, TYPE_NFIELDS (type) - 1, + stream, show, level); +} + + /* Print record type TYPE on STREAM. LEVEL is the recursion (indentation) level, in case the element type itself has nested structure, and SHOW is the number of levels of internal structure to show (see ada_print_type). */ @@ -767,6 +796,7 @@ ada_print_type (struct type *type0, const char *varstring, fprintf_filtered (stream, ">"); break; case TYPE_CODE_PTR: + case TYPE_CODE_TYPEDEF: fprintf_filtered (stream, "access "); ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level); break; diff --git a/contrib/gdb-7/gdb/ada-valprint.c b/contrib/gdb-7/gdb/ada-valprint.c index 2ab2ba2f3d..09266ceb6b 100644 --- a/contrib/gdb-7/gdb/ada-valprint.c +++ b/contrib/gdb-7/gdb/ada-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Ada values for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1997, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -36,17 +36,18 @@ #include "exceptions.h" #include "objfiles.h" -static void print_record (struct type *, const gdb_byte *, struct ui_file *, +static void print_record (struct type *, const gdb_byte *, int, + struct ui_file *, int, const struct value *, const struct value_print_options *); static int print_field_values (struct type *, const gdb_byte *, + int, struct ui_file *, int, const struct value *, const struct value_print_options *, - int, struct type *, - const gdb_byte *); + int, struct type *, int); static void adjust_type_signedness (struct type *); @@ -134,6 +135,7 @@ print_optional_low_bound (struct ui_file *stream, struct type *type, static void val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, + int offset, int bitoffset, struct ui_file *stream, int recurse, const struct value *val, @@ -185,7 +187,7 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, maybe_print_array_index (index_type, i + low, stream, options); i0 = i; - v0 = ada_value_primitive_packed_val (NULL, valaddr, + v0 = ada_value_primitive_packed_val (NULL, valaddr + offset, (i0 * bitsize) / HOST_CHAR_BIT, (i0 * bitsize) % HOST_CHAR_BIT, bitsize, elttype); @@ -194,11 +196,13 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, i += 1; if (i >= len) break; - v1 = ada_value_primitive_packed_val (NULL, valaddr, + v1 = ada_value_primitive_packed_val (NULL, valaddr + offset, (i * bitsize) / HOST_CHAR_BIT, (i * bitsize) % HOST_CHAR_BIT, bitsize, elttype); - if (memcmp (value_contents (v0), value_contents (v1), eltlen) != 0) + if (!value_available_contents_eq (v0, value_embedded_offset (v0), + v1, value_embedded_offset (v1), + eltlen)) break; } @@ -207,8 +211,9 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, struct value_print_options opts = *options; opts.deref_ref = 0; - val_print (elttype, value_contents (v0), 0, 0, stream, - recurse + 1, val, &opts, current_language); + val_print (elttype, value_contents_for_printing (v0), + value_embedded_offset (v0), 0, stream, + recurse + 1, v0, &opts, current_language); annotate_elt_rep (i - i0); fprintf_filtered (stream, _(" "), i - i0); annotate_elt_rep_end (); @@ -237,8 +242,9 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, maybe_print_array_index (index_type, j + low, stream, options); } - val_print (elttype, value_contents (v0), 0, 0, stream, - recurse + 1, val, &opts, current_language); + val_print (elttype, value_contents_for_printing (v0), + value_embedded_offset (v0), 0, stream, + recurse + 1, v0, &opts, current_language); annotate_elt (); } } @@ -261,18 +267,19 @@ printable_val_type (struct type *type, const gdb_byte *valaddr) /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. TYPE_LEN is the length in bytes - (1 or 2) of the character. */ + of the character. */ void ada_emit_char (int c, struct type *type, struct ui_file *stream, int quoter, int type_len) { - if (type_len != 2) - type_len = 1; - - c &= (1 << (type_len * TARGET_CHAR_BIT)) - 1; - - if (isascii (c) && isprint (c)) + /* If this character fits in the normal ASCII range, and is + a printable character, then print the character as if it was + an ASCII character, even if this is a wide character. + The UCHAR_MAX check is necessary because the isascii function + requires that its argument have a value of an unsigned char, + or EOF (EOF is obviously not printable). */ + if (c <= UCHAR_MAX && isascii (c) && isprint (c)) { if (c == quoter && c == '"') fprintf_filtered (stream, "\"\""); @@ -283,8 +290,8 @@ ada_emit_char (int c, struct type *type, struct ui_file *stream, fprintf_filtered (stream, "[\"%0*x\"]", type_len * 2, c); } -/* Character #I of STRING, given that TYPE_LEN is the size in bytes (1 - or 2) of a character. */ +/* Character #I of STRING, given that TYPE_LEN is the size in bytes + of a character. */ static int char_at (const gdb_byte *string, int i, int type_len, @@ -293,10 +300,11 @@ char_at (const gdb_byte *string, int i, int type_len, if (type_len == 1) return string[i]; else - return (int) extract_unsigned_integer (string + 2 * i, 2, byte_order); + return (int) extract_unsigned_integer (string + type_len * i, + type_len, byte_order); } -/* Wrapper around memcpy to make it legal argument to ui_file_put */ +/* Wrapper around memcpy to make it legal argument to ui_file_put. */ static void ui_memcpy (void *dest, const char *buffer, long len) { @@ -366,7 +374,7 @@ void ada_printchar (int c, struct type *type, struct ui_file *stream) { fputs_filtered ("'", stream); - ada_emit_char (c, type, stream, '\'', 1); + ada_emit_char (c, type, stream, '\'', TYPE_LENGTH (type)); fputs_filtered ("'", stream); } @@ -415,7 +423,7 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream) break; case TYPE_CODE_CHAR: - LA_PRINT_CHAR ((unsigned char) val, type, stream); + LA_PRINT_CHAR (val, type, stream); break; case TYPE_CODE_BOOL: @@ -453,9 +461,8 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream) /* Print the character string STRING, printing at most LENGTH characters. Printing stops early if the number hits print_max; repeat counts are printed as appropriate. Print ellipses at the end if we - had to stop before printing LENGTH characters, or if - FORCE_ELLIPSES. TYPE_LEN is the length (1 or 2) of the character type. - */ + had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. + TYPE_LEN is the length (1 or 2) of the character type. */ static void printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string, @@ -549,8 +556,9 @@ printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string, } void -ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, - unsigned int length, const char *encoding, int force_ellipses, +ada_printstr (struct ui_file *stream, struct type *type, + const gdb_byte *string, unsigned int length, + const char *encoding, int force_ellipses, const struct value_print_options *options) { printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type), @@ -558,18 +566,12 @@ ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, } -/* Print data of type TYPE located at VALADDR (within GDB), which came from - the inferior at address ADDRESS, onto stdio stream STREAM according to - OPTIONS. The data at VALADDR is in target byte order. - - If the data is printed as a string, returns the number of string characters - printed. - - RECURSE indicates the amount of indentation to supply before - continuation lines; this amount is roughly twice the value of RECURSE. */ +/* See val_print for a description of the various parameters of this + function; they are identical. The semantics of the return value is + also identical to val_print. */ int -ada_val_print (struct type *type, const gdb_byte *valaddr0, +ada_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, @@ -578,9 +580,10 @@ ada_val_print (struct type *type, const gdb_byte *valaddr0, volatile struct gdb_exception except; int result = 0; + /* XXX: this catches QUIT/ctrl-c as well. Isn't that busted? */ TRY_CATCH (except, RETURN_MASK_ALL) { - result = ada_val_print_1 (type, valaddr0, embedded_offset, address, + result = ada_val_print_1 (type, valaddr, embedded_offset, address, stream, recurse, val, options); } @@ -591,35 +594,37 @@ ada_val_print (struct type *type, const gdb_byte *valaddr0, } /* Assuming TYPE is a simple array, print the value of this array located - at VALADDR. See ada_val_print for a description of the various + at VALADDR + OFFSET. See ada_val_print for a description of the various parameters of this function; they are identical. The semantics of the return value is also identical to ada_val_print. */ static int ada_val_print_array (struct type *type, const gdb_byte *valaddr, - CORE_ADDR address, struct ui_file *stream, int recurse, + int offset, CORE_ADDR address, + struct ui_file *stream, int recurse, const struct value *val, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - struct type *elttype = TYPE_TARGET_TYPE (type); - unsigned int eltlen; - unsigned int len; int result = 0; - if (elttype == NULL) - eltlen = 0; - else - eltlen = TYPE_LENGTH (elttype); - if (eltlen == 0) - len = 0; - else - len = TYPE_LENGTH (type) / eltlen; - /* For an array of chars, print with string syntax. */ if (ada_is_string_type (type) && (options->format == 0 || options->format == 's')) { + enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + struct type *elttype = TYPE_TARGET_TYPE (type); + unsigned int eltlen; + unsigned int len; + + /* We know that ELTTYPE cannot possibly be null, because we found + that TYPE is a string-like type. Similarly, the size of ELTTYPE + should also be non-null, since it's a character-like type. */ + gdb_assert (elttype != NULL); + gdb_assert (TYPE_LENGTH (elttype) != 0); + + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; + if (options->prettyprint_arrays) print_spaces_filtered (2 + 2 * recurse, stream); @@ -633,12 +638,13 @@ ada_val_print_array (struct type *type, const gdb_byte *valaddr, for (temp_len = 0; (temp_len < len && temp_len < options->print_max - && char_at (valaddr, temp_len, eltlen, byte_order) != 0); + && char_at (valaddr + offset, + temp_len, eltlen, byte_order) != 0); temp_len += 1); len = temp_len; } - printstr (stream, elttype, valaddr, len, 0, eltlen, options); + printstr (stream, elttype, valaddr + offset, len, 0, eltlen, options); result = len; } else @@ -646,11 +652,11 @@ ada_val_print_array (struct type *type, const gdb_byte *valaddr, fprintf_filtered (stream, "("); print_optional_low_bound (stream, type, options); if (TYPE_FIELD_BITSIZE (type, 0) > 0) - val_print_packed_array_elements (type, valaddr, 0, stream, - recurse, val, options); + val_print_packed_array_elements (type, valaddr, offset, + 0, stream, recurse, val, options); else - val_print_array_elements (type, valaddr, address, stream, - recurse, val, options, 0); + val_print_array_elements (type, valaddr, offset, address, + stream, recurse, val, options, 0); fprintf_filtered (stream, ")"); } @@ -661,8 +667,8 @@ ada_val_print_array (struct type *type, const gdb_byte *valaddr, does not catch evaluation errors (leaving that to ada_val_print). */ static int -ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, - int embedded_offset, CORE_ADDR address, +ada_val_print_1 (struct type *type, const gdb_byte *valaddr, + int offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *original_value, const struct value_print_options *options) @@ -671,7 +677,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, int i; struct type *elttype; LONGEST val; - const gdb_byte *valaddr = valaddr0 + embedded_offset; + int offset_aligned; type = ada_check_typedef (type); @@ -682,40 +688,47 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, struct value *mark = value_mark (); struct value *val; - val = value_from_contents_and_address (type, valaddr, address); - val = ada_coerce_to_simple_array_ptr (val); + val = value_from_contents_and_address (type, valaddr + offset, address); + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) /* array access type. */ + val = ada_coerce_to_simple_array_ptr (val); + else + val = ada_coerce_to_simple_array (val); if (val == NULL) { - fprintf_filtered (stream, "(null)"); + gdb_assert (TYPE_CODE (type) == TYPE_CODE_TYPEDEF); + fprintf_filtered (stream, "0x0"); retn = 0; } else - retn = ada_val_print_1 (value_type (val), value_contents (val), 0, + retn = ada_val_print_1 (value_type (val), + value_contents_for_printing (val), + value_embedded_offset (val), value_address (val), stream, recurse, - NULL, options); + val, options); value_free_to_mark (mark); return retn; } - valaddr = ada_aligned_value_addr (type, valaddr); - embedded_offset -= valaddr - valaddr0 - embedded_offset; - type = printable_val_type (type, valaddr); + offset_aligned = offset + ada_aligned_value_addr (type, valaddr) - valaddr; + type = printable_val_type (type, valaddr + offset_aligned); switch (TYPE_CODE (type)) { default: - return c_val_print (type, valaddr0, embedded_offset, address, stream, + return c_val_print (type, valaddr, offset, address, stream, recurse, original_value, options); case TYPE_CODE_PTR: { - int ret = c_val_print (type, valaddr0, embedded_offset, address, + int ret = c_val_print (type, valaddr, offset, address, stream, recurse, original_value, options); if (ada_is_tag_type (type)) { - struct value *val = - value_from_contents_and_address (type, valaddr, address); + struct value *val = + value_from_contents_and_address (type, + valaddr + offset_aligned, + address + offset_aligned); const char *name = ada_tag_name (val); if (name != NULL) @@ -729,7 +742,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, case TYPE_CODE_RANGE: if (ada_is_fixed_point_type (type)) { - LONGEST v = unpack_long (type, valaddr); + LONGEST v = unpack_long (type, valaddr + offset_aligned); int len = TYPE_LENGTH (type); fprintf_filtered (stream, len < 4 ? "%.11g" : "%.17g", @@ -746,17 +759,20 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, its base type. Perform a conversion, or we will get a nonsense value. Actually, we could use the same code regardless of lengths; I'm just avoiding a cast. */ - struct value *v = value_cast (target_type, - value_from_contents_and_address - (type, valaddr, 0)); - - return ada_val_print_1 (target_type, value_contents (v), 0, 0, - stream, recurse + 1, NULL, options); + struct value *v1 + = value_from_contents_and_address (type, valaddr + offset, 0); + struct value *v = value_cast (target_type, v1); + + return ada_val_print_1 (target_type, + value_contents_for_printing (v), + value_embedded_offset (v), 0, + stream, recurse + 1, v, options); } else return ada_val_print_1 (TYPE_TARGET_TYPE (type), - valaddr0, embedded_offset, - address, stream, recurse, original_value, options); + valaddr, offset, + address, stream, recurse, + original_value, options); } else { @@ -768,7 +784,8 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, struct value_print_options opts = *options; opts.format = format; - print_scalar_formatted (valaddr, type, &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, offset_aligned, + original_value, &opts, 0, stream); } else if (ada_is_system_address_type (type)) { @@ -780,7 +797,8 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, struct gdbarch *gdbarch = get_type_arch (type); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; - CORE_ADDR addr = extract_typed_address (valaddr, ptr_type); + CORE_ADDR addr = extract_typed_address (valaddr + offset_aligned, + ptr_type); fprintf_filtered (stream, "("); type_print (type, "", stream, -1); @@ -789,12 +807,14 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, } else { - val_print_type_code_int (type, valaddr, stream); + val_print_type_code_int (type, valaddr + offset_aligned, stream); if (ada_is_character_type (type)) { + LONGEST c; + fputs_filtered (" ", stream); - ada_printchar ((unsigned char) unpack_long (type, valaddr), - type, stream); + c = unpack_long (type, valaddr + offset_aligned); + ada_printchar (c, type, stream); } } return 0; @@ -803,11 +823,12 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, case TYPE_CODE_ENUM: if (options->format) { - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, offset_aligned, + original_value, options, 0, stream); break; } len = TYPE_NFIELDS (type); - val = unpack_long (type, valaddr); + val = unpack_long (type, valaddr + offset_aligned); for (i = 0; i < len; i++) { QUIT; @@ -833,17 +854,18 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, case TYPE_CODE_FLAGS: if (options->format) - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, offset_aligned, + original_value, options, 0, stream); else - val_print_type_code_flags (type, valaddr, stream); + val_print_type_code_flags (type, valaddr + offset_aligned, stream); break; case TYPE_CODE_FLT: if (options->format) - return c_val_print (type, valaddr0, embedded_offset, address, stream, + return c_val_print (type, valaddr, offset, address, stream, recurse, original_value, options); else - ada_print_floating (valaddr0 + embedded_offset, type, stream); + ada_print_floating (valaddr + offset, type, stream); break; case TYPE_CODE_UNION: @@ -855,14 +877,15 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, } else { - print_record (type, valaddr, stream, recurse, original_value, - options); + print_record (type, valaddr, offset_aligned, + stream, recurse, original_value, options); return 0; } case TYPE_CODE_ARRAY: - return ada_val_print_array (type, valaddr, address, stream, - recurse, original_value, options); + return ada_val_print_array (type, valaddr, offset_aligned, + address, stream, recurse, original_value, + options); case TYPE_CODE_REF: /* For references, the debugger is expected to print the value as @@ -874,19 +897,21 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) { - LONGEST deref_val_int = (LONGEST) unpack_pointer (type, valaddr); + CORE_ADDR deref_val_int + = unpack_pointer (type, valaddr + offset_aligned); if (deref_val_int != 0) { struct value *deref_val = - ada_value_ind (value_from_longest + ada_value_ind (value_from_pointer (lookup_pointer_type (elttype), deref_val_int)); val_print (value_type (deref_val), - value_contents (deref_val), 0, + value_contents_for_printing (deref_val), + value_embedded_offset (deref_val), value_address (deref_val), stream, recurse + 1, - original_value, options, current_language); + deref_val, options, current_language); } else fputs_filtered ("(null)", stream); @@ -901,24 +926,28 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, } static int -print_variant_part (struct type *type, int field_num, const gdb_byte *valaddr, +print_variant_part (struct type *type, int field_num, + const gdb_byte *valaddr, int offset, struct ui_file *stream, int recurse, const struct value *val, - const struct value_print_options *options, int comma_needed, - struct type *outer_type, const gdb_byte *outer_valaddr) + const struct value_print_options *options, + int comma_needed, + struct type *outer_type, int outer_offset) { struct type *var_type = TYPE_FIELD_TYPE (type, field_num); - int which = ada_which_variant_applies (var_type, outer_type, outer_valaddr); + int which = ada_which_variant_applies (var_type, outer_type, + valaddr + outer_offset); if (which < 0) return 0; else return print_field_values (TYPE_FIELD_TYPE (var_type, which), - valaddr + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT + valaddr, + offset + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT + TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT, stream, recurse, val, options, - comma_needed, outer_type, outer_valaddr); + comma_needed, outer_type, outer_offset); } int @@ -946,9 +975,15 @@ ada_value_print (struct value *val0, struct ui_file *stream, } else if (ada_is_array_descriptor_type (type)) { - fprintf_filtered (stream, "("); - type_print (type, "", stream, -1); - fprintf_filtered (stream, ") "); + /* We do not print the type description unless TYPE is an array + access type (this is encoded by the compiler as a typedef to + a fat pointer - hence the check against TYPE_CODE_TYPEDEF). */ + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + { + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") "); + } } else if (ada_is_bogus_array_descriptor (type)) { @@ -960,12 +995,14 @@ ada_value_print (struct value *val0, struct ui_file *stream, opts = *options; opts.deref_ref = 1; - return (val_print (type, value_contents (val), 0, address, + return (val_print (type, value_contents_for_printing (val), + value_embedded_offset (val), address, stream, 0, val, &opts, current_language)); } static void print_record (struct type *type, const gdb_byte *valaddr, + int offset, struct ui_file *stream, int recurse, const struct value *val, const struct value_print_options *options) @@ -974,8 +1011,9 @@ print_record (struct type *type, const gdb_byte *valaddr, fprintf_filtered (stream, "("); - if (print_field_values (type, valaddr, stream, recurse, val, options, - 0, type, valaddr) != 0 && options->pretty) + if (print_field_values (type, valaddr, offset, + stream, recurse, val, options, + 0, type, offset) != 0 && options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); @@ -984,13 +1022,14 @@ print_record (struct type *type, const gdb_byte *valaddr, fprintf_filtered (stream, ")"); } -/* Print out fields of value at VALADDR having structure type TYPE. +/* Print out fields of value at VALADDR + OFFSET having structure type TYPE. - TYPE, VALADDR, STREAM, RECURSE, and OPTIONS have the - same meanings as in ada_print_value and ada_val_print. + TYPE, VALADDR, OFFSET, STREAM, RECURSE, and OPTIONS have the same + meanings as in ada_print_value and ada_val_print. - OUTER_TYPE and OUTER_VALADDR give type and address of enclosing record - (used to get discriminant values when printing variant parts). + OUTER_TYPE and OUTER_OFFSET give type and address of enclosing + record (used to get discriminant values when printing variant + parts). COMMA_NEEDED is 1 if fields have been printed at the current recursion level, so that a comma is needed before any field printed by this @@ -1000,11 +1039,11 @@ print_record (struct type *type, const gdb_byte *valaddr, static int print_field_values (struct type *type, const gdb_byte *valaddr, - struct ui_file *stream, int recurse, + int offset, struct ui_file *stream, int recurse, const struct value *val, const struct value_print_options *options, int comma_needed, - struct type *outer_type, const gdb_byte *outer_valaddr) + struct type *outer_type, int outer_offset) { int i, len; @@ -1019,18 +1058,20 @@ print_field_values (struct type *type, const gdb_byte *valaddr, { comma_needed = print_field_values (TYPE_FIELD_TYPE (type, i), - valaddr - + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT, + valaddr, + (offset + + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT), stream, recurse, val, options, - comma_needed, type, valaddr); + comma_needed, type, offset); continue; } else if (ada_is_variant_part (type, i)) { comma_needed = print_variant_part (type, i, valaddr, - stream, recurse, val, options, comma_needed, - outer_type, outer_valaddr); + offset, stream, recurse, val, + options, comma_needed, + outer_type, outer_offset); continue; } @@ -1088,14 +1129,16 @@ print_field_values (struct type *type, const gdb_byte *valaddr, struct value_print_options opts; adjust_type_signedness (TYPE_FIELD_TYPE (type, i)); - v = ada_value_primitive_packed_val (NULL, valaddr, - bit_pos / HOST_CHAR_BIT, - bit_pos % HOST_CHAR_BIT, - bit_size, - TYPE_FIELD_TYPE (type, i)); + v = ada_value_primitive_packed_val + (NULL, valaddr, + offset + bit_pos / HOST_CHAR_BIT, + bit_pos % HOST_CHAR_BIT, + bit_size, TYPE_FIELD_TYPE (type, i)); opts = *options; opts.deref_ref = 0; - val_print (TYPE_FIELD_TYPE (type, i), value_contents (v), 0, 0, + val_print (TYPE_FIELD_TYPE (type, i), + value_contents_for_printing (v), + value_embedded_offset (v), 0, stream, recurse + 1, v, &opts, current_language); } @@ -1106,8 +1149,10 @@ print_field_values (struct type *type, const gdb_byte *valaddr, opts.deref_ref = 0; ada_val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT, - 0, 0, stream, recurse + 1, val, &opts); + valaddr, + (offset + + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT), + 0, stream, recurse + 1, val, &opts); } annotate_field_end (); } diff --git a/contrib/gdb-7/gdb/addrmap.c b/contrib/gdb-7/gdb/addrmap.c index 30ec1ef57b..917790e2f3 100644 --- a/contrib/gdb-7/gdb/addrmap.c +++ b/contrib/gdb-7/gdb/addrmap.c @@ -1,6 +1,6 @@ /* addrmap.c --- implementation of address map data structure. - Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -41,6 +41,7 @@ struct addrmap_funcs struct addrmap *(*create_fixed) (struct addrmap *this, struct obstack *obstack); void (*relocate) (struct addrmap *this, CORE_ADDR offset); + int (*foreach) (struct addrmap *this, addrmap_foreach_fn fn, void *data); }; @@ -82,6 +83,11 @@ addrmap_relocate (struct addrmap *map, CORE_ADDR offset) } +int +addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn, void *data) +{ + return map->funcs->foreach (map, fn, data); +} /* Fixed address maps. */ @@ -175,12 +181,32 @@ addrmap_fixed_relocate (struct addrmap *this, CORE_ADDR offset) } +static int +addrmap_fixed_foreach (struct addrmap *this, addrmap_foreach_fn fn, + void *data) +{ + struct addrmap_fixed *map = (struct addrmap_fixed *) this; + size_t i; + + for (i = 0; i < map->num_transitions; i++) + { + int res = fn (data, map->transitions[i].addr, map->transitions[i].value); + + if (res != 0) + return res; + } + + return 0; +} + + static const struct addrmap_funcs addrmap_fixed_funcs = { addrmap_fixed_set_empty, addrmap_fixed_find, addrmap_fixed_create_fixed, - addrmap_fixed_relocate + addrmap_fixed_relocate, + addrmap_fixed_foreach }; @@ -281,7 +307,8 @@ addrmap_node_set_value (splay_tree_node node, void *value) static void -addrmap_splay_tree_insert (struct addrmap_mutable *map, CORE_ADDR key, void *value) +addrmap_splay_tree_insert (struct addrmap_mutable *map, + CORE_ADDR key, void *value) { splay_tree_insert (map->tree, allocate_key (map, key), @@ -444,12 +471,48 @@ addrmap_mutable_relocate (struct addrmap *this, CORE_ADDR offset) } +/* Struct to map addrmap's foreach function to splay_tree's version. */ +struct mutable_foreach_data +{ + addrmap_foreach_fn fn; + void *data; +}; + + +/* This is a splay_tree_foreach_fn. */ + +static int +addrmap_mutable_foreach_worker (splay_tree_node node, void *data) +{ + struct mutable_foreach_data *foreach_data = data; + + return foreach_data->fn (foreach_data->data, + addrmap_node_key (node), + addrmap_node_value (node)); +} + + +static int +addrmap_mutable_foreach (struct addrmap *this, addrmap_foreach_fn fn, + void *data) +{ + struct addrmap_mutable *mutable = (struct addrmap_mutable *) this; + struct mutable_foreach_data foreach_data; + + foreach_data.fn = fn; + foreach_data.data = data; + return splay_tree_foreach (mutable->tree, addrmap_mutable_foreach_worker, + &foreach_data); +} + + static const struct addrmap_funcs addrmap_mutable_funcs = { addrmap_mutable_set_empty, addrmap_mutable_find, addrmap_mutable_create_fixed, - addrmap_mutable_relocate + addrmap_mutable_relocate, + addrmap_mutable_foreach }; diff --git a/contrib/gdb-7/gdb/addrmap.h b/contrib/gdb-7/gdb/addrmap.h index 96d4e08a80..2169e30f08 100644 --- a/contrib/gdb-7/gdb/addrmap.h +++ b/contrib/gdb-7/gdb/addrmap.h @@ -1,6 +1,6 @@ /* addrmap.h --- interface to address map data structure. - Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -91,4 +91,15 @@ struct addrmap *addrmap_create_fixed (struct addrmap *original, to either mutable or immutable maps.) */ void addrmap_relocate (struct addrmap *map, CORE_ADDR offset); +/* The type of a function used to iterate over the map. + OBJ is NULL for unmapped regions. */ +typedef int (*addrmap_foreach_fn) (void *data, CORE_ADDR start_addr, + void *obj); + +/* Call FN, passing it DATA, for every address in MAP, following an + in-order traversal. If FN ever returns a non-zero value, the + iteration ceases immediately, and the value is returned. + Otherwise, this function returns 0. */ +int addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn, void *data); + #endif /* ADDRMAP_H */ diff --git a/contrib/gdb-7/gdb/amd64-nat.c b/contrib/gdb-7/gdb/amd64-nat.c index bcf303e588..db72ee1069 100644 --- a/contrib/gdb-7/gdb/amd64-nat.c +++ b/contrib/gdb-7/gdb/amd64-nat.c @@ -1,6 +1,6 @@ /* Native-dependent code for AMD64. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/amd64-nat.h b/contrib/gdb-7/gdb/amd64-nat.h index d1f91992d1..84e13c47aa 100644 --- a/contrib/gdb-7/gdb/amd64-nat.h +++ b/contrib/gdb-7/gdb/amd64-nat.h @@ -1,6 +1,6 @@ /* Native-dependent code for AMD64. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/amd64-tdep.c b/contrib/gdb-7/gdb/amd64-tdep.c index 9feed905a6..9b5d5bb43a 100644 --- a/contrib/gdb-7/gdb/amd64-tdep.c +++ b/contrib/gdb-7/gdb/amd64-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -38,7 +38,7 @@ #include "symfile.h" #include "disasm.h" #include "gdb_assert.h" - +#include "exceptions.h" #include "amd64-tdep.h" #include "i387-tdep.h" @@ -257,19 +257,6 @@ static const char *amd64_dword_names[] = "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }; -/* Return the name of register REGNUM, or the empty string if it is - an anonymous register. */ - -static const char * -amd64_register_name (struct gdbarch *gdbarch, int regnum) -{ - /* Hide the upper YMM registers. */ - if (i386_ymmh_regnum_p (gdbarch, regnum)) - return ""; - - return tdesc_register_name (gdbarch, regnum); -} - /* Return the name of register REGNUM. */ static const char * @@ -288,13 +275,14 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) return i386_pseudo_register_name (gdbarch, regnum); } -static void +static enum register_status amd64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, gdb_byte *buf) { gdb_byte raw_buf[MAX_REGISTER_SIZE]; struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum register_status status; if (i386_byte_regnum_p (gdbarch, regnum)) { @@ -304,25 +292,33 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch, if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) { /* Special handling for AH, BH, CH, DH. */ - regcache_raw_read (regcache, - gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf); - memcpy (buf, raw_buf + 1, 1); + status = regcache_raw_read (regcache, + gpnum - AMD64_NUM_LOWER_BYTE_REGS, + raw_buf); + if (status == REG_VALID) + memcpy (buf, raw_buf + 1, 1); } else { - regcache_raw_read (regcache, gpnum, raw_buf); - memcpy (buf, raw_buf, 1); + status = regcache_raw_read (regcache, gpnum, raw_buf); + if (status == REG_VALID) + memcpy (buf, raw_buf, 1); } + + return status; } else if (i386_dword_regnum_p (gdbarch, regnum)) { int gpnum = regnum - tdep->eax_regnum; /* Extract (always little endian). */ - regcache_raw_read (regcache, gpnum, raw_buf); - memcpy (buf, raw_buf, 4); + status = regcache_raw_read (regcache, gpnum, raw_buf); + if (status == REG_VALID) + memcpy (buf, raw_buf, 4); + + return status; } else - i386_pseudo_register_read (gdbarch, regcache, regnum, buf); + return i386_pseudo_register_read (gdbarch, regcache, regnum, buf); } static void @@ -600,7 +596,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct type *func_type, /* 2. If the type has class MEMORY, then the caller provides space for the return value and passes the address of this storage in - %rdi as if it were the first argument to the function. In effect, + %rdi as if it were the first argument to the function. In effect, this address becomes a hidden first argument. On return %rax will contain the address that has been passed in @@ -1577,7 +1573,7 @@ amd64_relocate_instruction (struct gdbarch *gdbarch, /* Where "ret" in the original code will return to. */ ret_addr = oldloc + insn_length; - push_buf[0] = 0x68; /* pushq $... */ + push_buf[0] = 0x68; /* pushq $... */ memcpy (&push_buf[1], &ret_addr, 4); /* Push the push. */ append_insns (to, 5, push_buf); @@ -1588,7 +1584,14 @@ amd64_relocate_instruction (struct gdbarch *gdbarch, /* Adjust the destination offset. */ rel32 = extract_signed_integer (insn + 1, 4, byte_order); newrel = (oldloc - *to) + rel32; - store_signed_integer (insn + 1, 4, newrel, byte_order); + store_signed_integer (insn + 1, 4, byte_order, newrel); + + if (debug_displaced) + fprintf_unfiltered (gdb_stdlog, + "Adjusted insn rel32=%s at %s to" + " rel32=%s at %s\n", + hex_string (rel32), paddress (gdbarch, oldloc), + hex_string (newrel), paddress (gdbarch, *to)); /* Write the adjusted jump into its displaced location. */ append_insns (to, 5, insn); @@ -1611,11 +1614,11 @@ amd64_relocate_instruction (struct gdbarch *gdbarch, { rel32 = extract_signed_integer (insn + offset, 4, byte_order); newrel = (oldloc - *to) + rel32; - store_signed_integer (insn + offset, 4, newrel, byte_order); + store_signed_integer (insn + offset, 4, byte_order, newrel); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, - "Adjusted insn rel32=0x%s at 0x%s to" - " rel32=0x%s at 0x%s\n", + "Adjusted insn rel32=%s at %s to" + " rel32=%s at %s\n", hex_string (rel32), paddress (gdbarch, oldloc), hex_string (newrel), paddress (gdbarch, *to)); } @@ -1632,6 +1635,7 @@ struct amd64_frame_cache { /* Base address. */ CORE_ADDR base; + int base_p; CORE_ADDR sp_offset; CORE_ADDR pc; @@ -1653,6 +1657,7 @@ amd64_init_frame_cache (struct amd64_frame_cache *cache) /* Base address. */ cache->base = 0; + cache->base_p = 0; cache->sp_offset = -8; cache->pc = 0; @@ -1910,33 +1915,20 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) /* Normal frames. */ -static struct amd64_frame_cache * -amd64_frame_cache (struct frame_info *this_frame, void **this_cache) +static void +amd64_frame_cache_1 (struct frame_info *this_frame, + struct amd64_frame_cache *cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct amd64_frame_cache *cache; gdb_byte buf[8]; int i; - if (*this_cache) - return *this_cache; - - cache = amd64_alloc_frame_cache (); - *this_cache = cache; - cache->pc = get_frame_func (this_frame); if (cache->pc != 0) amd64_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame), cache); - if (cache->saved_sp_reg != -1) - { - /* Stack pointer has been saved. */ - get_frame_register (this_frame, cache->saved_sp_reg, buf); - cache->saved_sp = extract_unsigned_integer(buf, 8, byte_order); - } - if (cache->frameless_p) { /* We didn't find a valid frame. If we're at the start of a @@ -1948,6 +1940,10 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_sp_reg != -1) { + /* Stack pointer has been saved. */ + get_frame_register (this_frame, cache->saved_sp_reg, buf); + cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order); + /* We're halfway aligning the stack. */ cache->base = ((cache->saved_sp - 8) & 0xfffffffffffffff0LL) - 8; cache->saved_regs[AMD64_RIP_REGNUM] = cache->saved_sp - 8; @@ -1985,9 +1981,48 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_regs[i] != -1) cache->saved_regs[i] += cache->base; + cache->base_p = 1; +} + +static struct amd64_frame_cache * +amd64_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct amd64_frame_cache *cache; + + if (*this_cache) + return *this_cache; + + cache = amd64_alloc_frame_cache (); + *this_cache = cache; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + amd64_frame_cache_1 (this_frame, cache); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + return cache; } +static enum unwind_stop_reason +amd64_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct amd64_frame_cache *cache = + amd64_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + /* This marks the outermost frame. */ + if (cache->base == 0) + return UNWIND_OUTERMOST; + + return UNWIND_NO_REASON; +} + static void amd64_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -1995,6 +2030,9 @@ amd64_frame_this_id (struct frame_info *this_frame, void **this_cache, struct amd64_frame_cache *cache = amd64_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + /* This marks the outermost frame. */ if (cache->base == 0) return; @@ -2025,6 +2063,7 @@ amd64_frame_prev_register (struct frame_info *this_frame, void **this_cache, static const struct frame_unwind amd64_frame_unwind = { NORMAL_FRAME, + amd64_frame_unwind_stop_reason, amd64_frame_this_id, amd64_frame_prev_register, NULL, @@ -2044,6 +2083,7 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct amd64_frame_cache *cache; CORE_ADDR addr; gdb_byte buf[8]; @@ -2054,20 +2094,40 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); - get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8; - addr = tdep->sigcontext_addr (this_frame); - gdb_assert (tdep->sc_reg_offset); - gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS); - for (i = 0; i < tdep->sc_num_regs; i++) - if (tdep->sc_reg_offset[i] != -1) - cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + addr = tdep->sigcontext_addr (this_frame); + gdb_assert (tdep->sc_reg_offset); + gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS); + for (i = 0; i < tdep->sc_num_regs; i++) + if (tdep->sc_reg_offset[i] != -1) + cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); *this_cache = cache; return cache; } +static enum unwind_stop_reason +amd64_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct amd64_frame_cache *cache = + amd64_sigtramp_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void amd64_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -2075,6 +2135,9 @@ amd64_sigtramp_frame_this_id (struct frame_info *this_frame, struct amd64_frame_cache *cache = amd64_sigtramp_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame)); } @@ -2121,6 +2184,7 @@ amd64_sigtramp_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind amd64_sigtramp_frame_unwind = { SIGTRAMP_FRAME, + amd64_sigtramp_frame_unwind_stop_reason, amd64_sigtramp_frame_this_id, amd64_sigtramp_frame_prev_register, NULL, @@ -2182,6 +2246,7 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct amd64_frame_cache *cache; gdb_byte buf[8]; @@ -2191,23 +2256,43 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); *this_cache = cache; - /* Cache base will be %esp plus cache->sp_offset (-8). */ - get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 8, - byte_order) + cache->sp_offset; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* Cache base will be %esp plus cache->sp_offset (-8). */ + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 8, + byte_order) + cache->sp_offset; - /* Cache pc will be the frame func. */ - cache->pc = get_frame_pc (this_frame); + /* Cache pc will be the frame func. */ + cache->pc = get_frame_pc (this_frame); - /* The saved %esp will be at cache->base plus 16. */ - cache->saved_sp = cache->base + 16; + /* The saved %esp will be at cache->base plus 16. */ + cache->saved_sp = cache->base + 16; - /* The saved %eip will be at cache->base plus 8. */ - cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8; + /* The saved %eip will be at cache->base plus 8. */ + cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8; + + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); return cache; } +static enum unwind_stop_reason +amd64_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct amd64_frame_cache *cache + = amd64_epilogue_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void amd64_epilogue_frame_this_id (struct frame_info *this_frame, void **this_cache, @@ -2216,12 +2301,16 @@ amd64_epilogue_frame_this_id (struct frame_info *this_frame, struct amd64_frame_cache *cache = amd64_epilogue_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + (*this_id) = frame_id_build (cache->base + 8, cache->pc); } static const struct frame_unwind amd64_epilogue_frame_unwind = { NORMAL_FRAME, + amd64_epilogue_frame_unwind_stop_reason, amd64_epilogue_frame_this_id, amd64_frame_prev_register, NULL, @@ -2407,8 +2496,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_tdesc_pseudo_register_name (gdbarch, amd64_pseudo_register_name); - set_gdbarch_register_name (gdbarch, amd64_register_name); - /* AMD64 has an FPU and 16 SSE registers. */ tdep->st0_regnum = AMD64_ST0_REGNUM; tdep->num_xmm_regs = 16; diff --git a/contrib/gdb-7/gdb/amd64-tdep.h b/contrib/gdb-7/gdb/amd64-tdep.h index e67106d1c7..b96a58abb5 100644 --- a/contrib/gdb-7/gdb/amd64-tdep.h +++ b/contrib/gdb-7/gdb/amd64-tdep.h @@ -1,6 +1,6 @@ /* Target-dependent definitions for AMD64. - Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. diff --git a/contrib/gdb-7/gdb/amd64bsd-nat.c b/contrib/gdb-7/gdb/amd64bsd-nat.c index fa73776f5c..7821f2b5d6 100644 --- a/contrib/gdb-7/gdb/amd64bsd-nat.c +++ b/contrib/gdb-7/gdb/amd64bsd-nat.c @@ -1,6 +1,6 @@ /* Native-dependent code for AMD64 BSD's. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/annotate.c b/contrib/gdb-7/gdb/annotate.c index 66774b0199..d24120cf12 100644 --- a/contrib/gdb-7/gdb/annotate.c +++ b/contrib/gdb-7/gdb/annotate.c @@ -1,6 +1,6 @@ /* Annotation routines for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1998, 1999, - 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -26,7 +26,7 @@ #include "observer.h" -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ extern void _initialize_annotate (void); @@ -57,7 +57,7 @@ breakpoints_changed (void) target_terminal_ours (); printf_unfiltered (("\n\032\032breakpoints-invalid\n")); if (ignore_count_changed) - ignore_count_changed = 0; /* Avoid multiple break annotations. */ + ignore_count_changed = 0; /* Avoid multiple break annotations. */ } } @@ -65,7 +65,7 @@ breakpoints_changed (void) want to provide successive multiple breakpoints-invalid messages that are all caused by the fact that the ignore count is changing (which could keep the GUI very busy). One is enough, after the - target actually "stops". */ + target actually "stops". */ void annotate_ignore_count_change (void) diff --git a/contrib/gdb-7/gdb/annotate.h b/contrib/gdb-7/gdb/annotate.h index e5dba73a83..9aa6c62dec 100644 --- a/contrib/gdb-7/gdb/annotate.h +++ b/contrib/gdb-7/gdb/annotate.h @@ -1,6 +1,6 @@ /* Annotation routines for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1994, 1998, 1999, 2000, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/arch-utils.c b/contrib/gdb-7/gdb/arch-utils.c index e8836d2d63..db79b9ab3d 100644 --- a/contrib/gdb-7/gdb/arch-utils.c +++ b/contrib/gdb-7/gdb/arch-utils.c @@ -1,7 +1,7 @@ /* Dynamic architecture support for GDB, the GNU debugger. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ #include "arch-utils.h" #include "buildsym.h" #include "gdbcmd.h" -#include "inferior.h" /* enum CALL_DUMMY_LOCATION et.al. */ +#include "inferior.h" /* enum CALL_DUMMY_LOCATION et al. */ #include "gdb_string.h" #include "regcache.h" #include "gdb_assert.h" @@ -146,7 +146,7 @@ core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs) return (lhs > rhs); } -/* Misc helper functions for targets. */ +/* Misc helper functions for targets. */ CORE_ADDR core_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr) @@ -186,8 +186,8 @@ cannot_register_not (struct gdbarch *gdbarch, int regnum) } /* Legacy version of target_virtual_frame_pointer(). Assumes that - there is an gdbarch_deprecated_fp_regnum and that it is the same, cooked or - raw. */ + there is an gdbarch_deprecated_fp_regnum and that it is the same, + cooked or raw. */ void legacy_virtual_frame_pointer (struct gdbarch *gdbarch, @@ -211,7 +211,8 @@ legacy_virtual_frame_pointer (struct gdbarch *gdbarch, else /* Should this be an internal error? I guess so, it is reflecting an architectural limitation in the current design. */ - internal_error (__FILE__, __LINE__, _("No virtual frame pointer available")); + internal_error (__FILE__, __LINE__, + _("No virtual frame pointer available")); *frame_offset = 0; } @@ -278,7 +279,7 @@ show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c, "(currently big endian)\n")); else fprintf_unfiltered (file, _("The target endianness is set automatically " - "(currently little endian)\n")); + "(currently little endian)\n")); else if (target_byte_order_user == BFD_ENDIAN_BIG) fprintf_unfiltered (file, @@ -373,8 +374,9 @@ choose_architecture_for_target (const struct target_desc *target_desc, if (compat1 == NULL && compat2 == NULL) { - /* BFD considers the architectures incompatible. Check our target - description whether it accepts SELECTED as compatible anyway. */ + /* BFD considers the architectures incompatible. Check our + target description whether it accepts SELECTED as compatible + anyway. */ if (tdesc_compatible_p (target_desc, selected)) return from_target; @@ -391,10 +393,10 @@ choose_architecture_for_target (const struct target_desc *target_desc, if (compat1 == compat2) return compat1; - /* If the two didn't match, but one of them was a default architecture, - assume the more specific one is correct. This handles the case - where an executable or target description just says "mips", but - the other knows which MIPS variant. */ + /* If the two didn't match, but one of them was a default + architecture, assume the more specific one is correct. This + handles the case where an executable or target description just + says "mips", but the other knows which MIPS variant. */ if (compat1->the_default) return compat2; if (compat2->the_default) @@ -408,7 +410,7 @@ choose_architecture_for_target (const struct target_desc *target_desc, return selected; } -/* Functions to manipulate the architecture of the target */ +/* Functions to manipulate the architecture of the target. */ enum set_arch { set_arch_auto, set_arch_manual }; @@ -426,24 +428,24 @@ selected_architecture_name (void) } /* Called if the user enters ``show architecture'' without an - argument. */ + argument. */ static void show_architecture (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { if (target_architecture_user == NULL) - fprintf_filtered (file, _("\ -The target architecture is set automatically (currently %s)\n"), - gdbarch_bfd_arch_info (get_current_arch ())->printable_name); + fprintf_filtered (file, _("The target architecture is set " + "automatically (currently %s)\n"), + gdbarch_bfd_arch_info (get_current_arch ())->printable_name); else - fprintf_filtered (file, _("\ -The target architecture is assumed to be %s\n"), set_architecture_string); + fprintf_filtered (file, _("The target architecture is assumed to be %s\n"), + set_architecture_string); } /* Called if the user enters ``set architecture'' with or without an - argument. */ + argument. */ static void set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c) @@ -583,14 +585,14 @@ initialize_current_architecture (void) const char **arches = gdbarch_printable_names (); struct gdbarch_info info; - /* determine a default architecture and byte order. */ + /* determine a default architecture and byte order. */ gdbarch_info_init (&info); - /* Find a default architecture. */ + /* Find a default architecture. */ if (default_bfd_arch == NULL) { /* Choose the architecture by taking the first one - alphabetically. */ + alphabetically. */ const char *chosen = arches[0]; const char **arch; for (arch = arches; *arch != NULL; arch++) @@ -613,7 +615,7 @@ initialize_current_architecture (void) if (default_byte_order == BFD_ENDIAN_UNKNOWN && default_bfd_vec != NULL) { - /* Extract BFD's default vector's byte order. */ + /* Extract BFD's default vector's byte order. */ switch (default_bfd_vec->byteorder) { case BFD_ENDIAN_BIG: @@ -628,7 +630,7 @@ initialize_current_architecture (void) } if (default_byte_order == BFD_ENDIAN_UNKNOWN) { - /* look for ``*el-*'' in the target name. */ + /* look for ``*el-*'' in the target name. */ const char *chp; chp = strchr (target_name, '-'); if (chp != NULL @@ -651,18 +653,18 @@ initialize_current_architecture (void) "initial architecture failed")); /* Create the ``set architecture'' command appending ``auto'' to the - list of architectures. */ + list of architectures. */ { - /* Append ``auto''. */ + /* Append ``auto''. */ int nr; for (nr = 0; arches[nr] != NULL; nr++); arches = xrealloc (arches, sizeof (char*) * (nr + 2)); arches[nr + 0] = "auto"; arches[nr + 1] = NULL; add_setshow_enum_cmd ("architecture", class_support, - arches, &set_architecture_string, _("\ -Set architecture of target."), _("\ -Show architecture of target."), NULL, + arches, &set_architecture_string, + _("Set architecture of target."), + _("Show architecture of target."), NULL, set_architecture, show_architecture, &setlist, &showlist); add_alias_cmd ("processor", "architecture", class_support, 1, &setlist); @@ -742,12 +744,13 @@ gdbarch_info_fill (struct gdbarch_info *info) gdb_assert (info->bfd_arch_info != NULL); } -/* Return "current" architecture. If the target is running, this is the - architecture of the selected frame. Otherwise, the "current" architecture - defaults to the target architecture. +/* Return "current" architecture. If the target is running, this is + the architecture of the selected frame. Otherwise, the "current" + architecture defaults to the target architecture. - This function should normally be called solely by the command interpreter - routines to determine the architecture to execute a command in. */ + This function should normally be called solely by the command + interpreter routines to determine the architecture to execute a + command in. */ struct gdbarch * get_current_arch (void) { @@ -785,15 +788,16 @@ default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, /* */ -extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_gdbarch_utils; void _initialize_gdbarch_utils (void) { add_setshow_enum_cmd ("endian", class_support, - endian_enum, &set_endian_string, _("\ -Set endianness of target."), _("\ -Show endianness of target."), NULL, - set_endian, show_endian, + endian_enum, &set_endian_string, + _("Set endianness of target."), + _("Show endianness of target."), + NULL, set_endian, show_endian, &setlist, &showlist); } diff --git a/contrib/gdb-7/gdb/arch-utils.h b/contrib/gdb-7/gdb/arch-utils.h index dbeb67f737..5d05535828 100644 --- a/contrib/gdb-7/gdb/arch-utils.h +++ b/contrib/gdb-7/gdb/arch-utils.h @@ -1,7 +1,7 @@ /* Dynamic architecture support for GDB, the GNU debugger. - Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -51,15 +51,15 @@ extern void /* Default implementation of gdbarch_displaced_hw_singlestep. */ extern int - default_displaced_step_hw_singlestep (struct gdbarch *gdbarch, - struct displaced_step_closure *closure); + default_displaced_step_hw_singlestep (struct gdbarch *, + struct displaced_step_closure *); /* Possible value for gdbarch_displaced_step_location: Place displaced instructions at the program's entry point, leaving space for inferior function call return breakpoints. */ extern CORE_ADDR displaced_step_at_entry_point (struct gdbarch *gdbarch); -/* The only possible cases for inner_than. */ +/* The only possible cases for inner_than. */ extern int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs); extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs); @@ -68,20 +68,21 @@ extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs); extern CORE_ADDR core_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr); extern gdbarch_convert_from_func_ptr_addr_ftype convert_from_func_ptr_addr_identity; -/* No-op conversion of reg to regnum. */ +/* No-op conversion of reg to regnum. */ extern int no_op_reg_to_regnum (struct gdbarch *gdbarch, int reg); -/* Do nothing version of elf_make_msymbol_special. */ +/* Do nothing version of elf_make_msymbol_special. */ -void default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym); +void default_elf_make_msymbol_special (asymbol *sym, + struct minimal_symbol *msym); -/* Do nothing version of coff_make_msymbol_special. */ +/* Do nothing version of coff_make_msymbol_special. */ void default_coff_make_msymbol_special (int val, struct minimal_symbol *msym); /* Version of cannot_fetch_register() / cannot_store_register() that - always fails. */ + always fails. */ int cannot_register_not (struct gdbarch *gdbarch, int regnum); @@ -100,7 +101,8 @@ extern CORE_ADDR generic_skip_solib_resolver (struct gdbarch *gdbarch, extern int generic_in_solib_return_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc, char *name); -extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc); +extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, + CORE_ADDR pc); /* By default, registers are not convertible. */ extern int generic_convert_register_p (struct gdbarch *gdbarch, int regnum, diff --git a/contrib/gdb-7/gdb/auxv.c b/contrib/gdb-7/gdb/auxv.c index 593b0c8059..28196b4e27 100644 --- a/contrib/gdb-7/gdb/auxv.c +++ b/contrib/gdb-7/gdb/auxv.c @@ -1,6 +1,6 @@ /* Auxiliary vector support for GDB, the GNU debugger. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -34,8 +34,8 @@ #include -/* This function handles access via /proc/PID/auxv, which is a common method - for native targets. */ +/* This function handles access via /proc/PID/auxv, which is a common + method for native targets. */ static LONGEST procfs_xfer_auxv (gdb_byte *readbuf, @@ -90,35 +90,39 @@ ld_so_xfer_auxv (gdb_byte *readbuf, if (MSYMBOL_SIZE (msym) != ptr_size) return -1; - /* POINTER_ADDRESS is a location where the `_dl_auxv' variable resides. - DATA_ADDRESS is the inferior value present in `_dl_auxv', therefore the - real inferior AUXV address. */ + /* POINTER_ADDRESS is a location where the `_dl_auxv' variable + resides. DATA_ADDRESS is the inferior value present in + `_dl_auxv', therefore the real inferior AUXV address. */ pointer_address = SYMBOL_VALUE_ADDRESS (msym); /* The location of the _dl_auxv symbol may no longer be correct if - ld.so runs at a different address than the one present in the file. - This is very common case - for unprelinked ld.so or with a PIE executable. - PIE executable forces random address even for libraries already being - prelinked to some address. PIE executables themselves are never prelinked - even on prelinked systems. Prelinking of a PIE executable would block - their purpose of randomizing load of everything including the executable. - - If the memory read fails, return -1 to fallback on another mechanism for - retrieving the AUXV. - - In most cases of a PIE running under valgrind there is no way to find - out the base addresses of any of ld.so, executable or AUXV as everything - is randomized and /proc information is not relevant for the virtual - executable running under valgrind. We think that we might need a valgrind - extension to make it work. This is PR 11440. */ + ld.so runs at a different address than the one present in the + file. This is very common case - for unprelinked ld.so or with a + PIE executable. PIE executable forces random address even for + libraries already being prelinked to some address. PIE + executables themselves are never prelinked even on prelinked + systems. Prelinking of a PIE executable would block their + purpose of randomizing load of everything including the + executable. + + If the memory read fails, return -1 to fallback on another + mechanism for retrieving the AUXV. + + In most cases of a PIE running under valgrind there is no way to + find out the base addresses of any of ld.so, executable or AUXV + as everything is randomized and /proc information is not relevant + for the virtual executable running under valgrind. We think that + we might need a valgrind extension to make it work. This is PR + 11440. */ if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0) return -1; data_address = extract_typed_address (ptr_buf, ptr_type); - /* Possibly still not initialized such as during an inferior startup. */ + /* Possibly still not initialized such as during an inferior + startup. */ if (data_address == 0) return -1; @@ -132,8 +136,8 @@ ld_so_xfer_auxv (gdb_byte *readbuf, return -1; } - /* Stop if trying to read past the existing AUXV block. The final AT_NULL - was already returned before. */ + /* Stop if trying to read past the existing AUXV block. The final + AT_NULL was already returned before. */ if (offset >= auxv_pair_size) { @@ -154,9 +158,10 @@ ld_so_xfer_auxv (gdb_byte *readbuf, if (block > len) block = len; - /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported. Tails - unaligned to AUXV_PAIR_SIZE will not be read during a call (they - should be completed during next read with new/extended buffer). */ + /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported. + Tails unaligned to AUXV_PAIR_SIZE will not be read during a + call (they should be completed during next read with + new/extended buffer). */ block &= -auxv_pair_size; if (block == 0) @@ -174,8 +179,9 @@ ld_so_xfer_auxv (gdb_byte *readbuf, data_address += block; len -= block; - /* Check terminal AT_NULL. This function is being called indefinitely - being extended its READBUF until it returns EOF (0). */ + /* Check terminal AT_NULL. This function is being called + indefinitely being extended its READBUF until it returns EOF + (0). */ while (block >= auxv_pair_size) { @@ -207,10 +213,11 @@ memory_xfer_auxv (struct target_ops *ops, gdb_assert (object == TARGET_OBJECT_AUXV); gdb_assert (readbuf || writebuf); - /* ld_so_xfer_auxv is the only function safe for virtual executables being - executed by valgrind's memcheck. Using ld_so_xfer_auxv during inferior - startup is problematic, because ld.so symbol tables have not yet been - relocated. So GDB uses this function only when attaching to a process. + /* ld_so_xfer_auxv is the only function safe for virtual + executables being executed by valgrind's memcheck. Using + ld_so_xfer_auxv during inferior startup is problematic, because + ld.so symbol tables have not yet been relocated. So GDB uses + this function only when attaching to a process. */ if (current_inferior ()->attach_flag != 0) @@ -308,7 +315,7 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) } -/* Print the contents of the target's AUXV on the specified file. */ +/* Print the contents of the target's AUXV on the specified file. */ int fprint_target_auxv (struct ui_file *file, struct target_ops *ops) { @@ -401,7 +408,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) if (opts.addressprint) fprintf_filtered (file, "%s", paddress (target_gdbarch, val)); val_print_string (builtin_type (target_gdbarch)->builtin_char, - val, -1, file, &opts); + NULL, val, -1, file, &opts); fprintf_filtered (file, "\n"); } break; diff --git a/contrib/gdb-7/gdb/auxv.h b/contrib/gdb-7/gdb/auxv.h index 679bf17cec..02cc0b9c77 100644 --- a/contrib/gdb-7/gdb/auxv.h +++ b/contrib/gdb-7/gdb/auxv.h @@ -1,6 +1,6 @@ /* Auxiliary vector support for GDB, the GNU debugger. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -40,7 +40,7 @@ extern int target_auxv_parse (struct target_ops *ops, extern int target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp); -/* Print the contents of the target's AUXV on the specified file. */ +/* Print the contents of the target's AUXV on the specified file. */ extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops); extern LONGEST memory_xfer_auxv (struct target_ops *ops, diff --git a/contrib/gdb-7/gdb/ax-gdb.c b/contrib/gdb-7/gdb/ax-gdb.c index e01f359bd3..d1736e144c 100644 --- a/contrib/gdb-7/gdb/ax-gdb.c +++ b/contrib/gdb-7/gdb/ax-gdb.c @@ -1,6 +1,6 @@ /* GDB-specific functions for operating on agent expressions. - Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -59,7 +59,7 @@ -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ /* There's a standard order to the arguments of these functions: union exp_element ** --- pointer into expression @@ -70,7 +70,8 @@ static struct value *const_var_ref (struct symbol *var); static struct value *const_expr (union exp_element **pc); static struct value *maybe_const_expr (union exp_element **pc); -static void gen_traced_pop (struct gdbarch *, struct agent_expr *, struct axs_value *); +static void gen_traced_pop (struct gdbarch *, struct agent_expr *, + struct axs_value *); static void gen_sign_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *); @@ -614,7 +615,7 @@ static void gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, struct symbol *var) { - /* Dereference any typedefs. */ + /* Dereference any typedefs. */ value->type = check_typedef (SYMBOL_TYPE (var)); value->optimized_out = 0; @@ -633,7 +634,8 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, case LOC_CONST_BYTES: internal_error (__FILE__, __LINE__, - _("gen_var_ref: LOC_CONST_BYTES symbols are not supported")); + _("gen_var_ref: LOC_CONST_BYTES " + "symbols are not supported")); /* Variable at a fixed location in memory. Easy. */ case LOC_STATIC: @@ -986,7 +988,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) /* GCC does allow casts to yield lvalues, so this should be fixed before merging these changes into the trunk. */ require_rvalue (ax, value); - /* Dereference typedefs. */ + /* Dereference typedefs. */ type = check_typedef (type); switch (TYPE_CODE (type)) @@ -1138,8 +1140,9 @@ gen_less (struct agent_expr *ax, struct axs_value *value, operator, used in error messages */ static void gen_binop (struct agent_expr *ax, struct axs_value *value, - struct axs_value *value1, struct axs_value *value2, enum agent_op op, - enum agent_op op_unsigned, int may_carry, char *name) + struct axs_value *value1, struct axs_value *value2, + enum agent_op op, enum agent_op op_unsigned, + int may_carry, char *name) { /* We only handle INT op INT. */ if ((TYPE_CODE (value1->type) != TYPE_CODE_INT) @@ -1289,7 +1292,7 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, equal to the number of `one' bits in bytesize, but who cares? */ int fragment_count; - /* Dereference any typedefs. */ + /* Dereference any typedefs. */ type = check_typedef (type); /* Can we fetch the number of bits requested at all? */ @@ -1447,7 +1450,8 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, { gen_static_field (exp->gdbarch, ax, value, type, i); if (value->optimized_out) - error (_("static field `%s' has been optimized out, cannot use"), + error (_("static field `%s' has been " + "optimized out, cannot use"), field); return 1; } @@ -1469,7 +1473,8 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); rslt = gen_struct_ref_recursive (exp, ax, value, field, - offset + TYPE_BASECLASS_BITPOS (type, i) / TARGET_CHAR_BIT, + offset + TYPE_BASECLASS_BITPOS (type, i) + / TARGET_CHAR_BIT, basetype); if (rslt) return 1; @@ -1587,7 +1592,8 @@ gen_struct_elt_for_reference (struct expression *exp, { gen_static_field (exp->gdbarch, ax, value, t, i); if (value->optimized_out) - error (_("static field `%s' has been optimized out, cannot use"), + error (_("static field `%s' has been " + "optimized out, cannot use"), fieldname); return 1; } @@ -1677,7 +1683,7 @@ gen_aggregate_elt_ref (struct expression *exp, return 0; } -/* Generate code for GDB's magical `repeat' operator. +/* Generate code for GDB's magical `repeat' operator. LVALUE @ INT creates an array INT elements long, and whose elements have the same type as LVALUE, located in memory so that LVALUE is its first element. For example, argv[0]@argc gives you the array @@ -1706,7 +1712,8 @@ gen_repeat (struct expression *exp, union exp_element **pc, int length; if (!v) - error (_("Right operand of `@' must be a constant, in agent expressions.")); + error (_("Right operand of `@' must be a " + "constant, in agent expressions.")); if (TYPE_CODE (value_type (v)) != TYPE_CODE_INT) error (_("Right operand of `@' must be an integer.")); length = value_as_long (v); @@ -1890,7 +1897,8 @@ gen_expr (struct expression *exp, union exp_element **pc, ax_tsv (ax, aop_tracev, tsv->number); } else - error (_("$%s is not a trace state variable, may not assign to it"), name); + error (_("$%s is not a trace state variable, " + "may not assign to it"), name); } else error (_("May only assign to trace state variables")); @@ -1925,7 +1933,8 @@ gen_expr (struct expression *exp, union exp_element **pc, ax_tsv (ax, aop_tracev, tsv->number); } else - error (_("$%s is not a trace state variable, may not assign to it"), name); + error (_("$%s is not a trace state variable, " + "may not assign to it"), name); } else error (_("May only assign to trace state variables")); @@ -1978,9 +1987,11 @@ gen_expr (struct expression *exp, union exp_element **pc, if (reg == -1) internal_error (__FILE__, __LINE__, _("Register $%s not available"), name); - if (reg >= gdbarch_num_regs (exp->gdbarch)) - error (_("'%s' is a pseudo-register; " - "GDB cannot yet trace pseudoregister contents."), + /* No support for tracing user registers yet. */ + if (reg >= gdbarch_num_regs (exp->gdbarch) + + gdbarch_num_pseudo_regs (exp->gdbarch)) + error (_("'%s' is a user-register; " + "GDB cannot yet trace user-register contents."), name); value->kind = axs_lvalue_register; value->u.reg = reg; @@ -2005,7 +2016,8 @@ gen_expr (struct expression *exp, union exp_element **pc, value->type = builtin_type (exp->gdbarch)->builtin_long_long; } else - error (_("$%s is not a trace state variable; GDB agent expressions cannot use convenience variables."), name); + error (_("$%s is not a trace state variable; GDB agent " + "expressions cannot use convenience variables."), name); } break; @@ -2032,14 +2044,13 @@ gen_expr (struct expression *exp, union exp_element **pc, (*pc) += 3; gen_expr (exp, pc, ax, value); - /* I'm not sure I understand UNOP_MEMVAL entirely. I think - it's just a hack for dealing with minsyms; you take some - integer constant, pretend it's the address of an lvalue of - the given type, and dereference it. */ - if (value->kind != axs_rvalue) - /* This would be weird. */ - internal_error (__FILE__, __LINE__, - _("gen_expr: OP_MEMVAL operand isn't an rvalue???")); + + /* If we have an axs_rvalue or an axs_lvalue_memory, then we + already have the right value on the stack. For + axs_lvalue_register, we must convert. */ + if (value->kind == axs_lvalue_register) + require_rvalue (ax, value); + value->type = type; value->kind = axs_lvalue_memory; } @@ -2047,7 +2058,7 @@ gen_expr (struct expression *exp, union exp_element **pc, case UNOP_PLUS: (*pc)++; - /* + FOO is equivalent to 0 + FOO, which can be optimized. */ + /* + FOO is equivalent to 0 + FOO, which can be optimized. */ gen_expr (exp, pc, ax, value); gen_usual_unary (exp, ax, value); break; @@ -2245,8 +2256,8 @@ gen_expr_binop_rest (struct expression *exp, if (binop_types_user_defined_p (op, value1->type, value2->type)) { - error (_("\ -cannot subscript requested type: cannot call user defined functions")); + error (_("cannot subscript requested type: " + "cannot call user defined functions")); } else { @@ -2266,7 +2277,8 @@ cannot subscript requested type: cannot call user defined functions")); } if (!is_integral_type (value2->type)) - error (_("Argument to arithmetic operation not a number or boolean.")); + error (_("Argument to arithmetic operation " + "not a number or boolean.")); gen_ptradd (ax, value, value1, value2); gen_deref (ax, value); @@ -2509,10 +2521,12 @@ void _initialize_ax_gdb (void) { add_cmd ("agent", class_maintenance, agent_command, - _("Translate an expression into remote agent bytecode for tracing."), + _("Translate an expression into " + "remote agent bytecode for tracing."), &maintenancelist); add_cmd ("agent-eval", class_maintenance, agent_eval_command, - _("Translate an expression into remote agent bytecode for evaluation."), + _("Translate an expression into remote " + "agent bytecode for evaluation."), &maintenancelist); } diff --git a/contrib/gdb-7/gdb/ax-gdb.h b/contrib/gdb-7/gdb/ax-gdb.h index 924df0891a..a2367a67e3 100644 --- a/contrib/gdb-7/gdb/ax-gdb.h +++ b/contrib/gdb-7/gdb/ax-gdb.h @@ -1,5 +1,5 @@ /* GDB-specific functions for operating on agent expressions - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010 + Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -78,7 +78,7 @@ struct axs_value /* The type of the subexpression. Even if lvalue == axs_lvalue_memory, this is the type of the value itself; the value on the stack is a - "pointer to" an object of this type. */ + "pointer to" an object of this type. */ struct type *type; /* If nonzero, this is a variable which does not actually exist in diff --git a/contrib/gdb-7/gdb/ax-general.c b/contrib/gdb-7/gdb/ax-general.c index ab4591fa08..889fac9f0d 100644 --- a/contrib/gdb-7/gdb/ax-general.c +++ b/contrib/gdb-7/gdb/ax-general.c @@ -1,5 +1,5 @@ /* Functions for manipulating expressions designed to be executed on the agent - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010 + Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,8 @@ #include "value.h" #include "gdb_string.h" +#include "user-regs.h" + static void grow_expr (struct agent_expr *x, int n); static void append_const (struct agent_expr *x, LONGEST val, int n); @@ -141,6 +143,18 @@ ax_simple (struct agent_expr *x, enum agent_op op) x->buf[x->len++] = op; } +/* Append a pick operator to EXPR. DEPTH is the stack item to pick, + with 0 being top of stack. */ + +void +ax_pick (struct agent_expr *x, int depth) +{ + if (depth < 0 || depth > 255) + error (_("GDB bug: ax-general.c (ax_pick): stack depth out of range")); + ax_simple (x, aop_pick); + append_const (x, 1, depth); +} + /* Append a sign-extension or zero-extension instruction to EXPR, to extend an N-bit value. */ @@ -152,7 +166,8 @@ generic_ext (struct agent_expr *x, enum agent_op op, int n) error (_("GDB bug: ax-general.c (generic_ext): bit count out of range")); /* That had better be enough range. */ if (sizeof (LONGEST) * 8 > 255) - error (_("GDB bug: ax-general.c (generic_ext): opcode has inadequate range")); + error (_("GDB bug: ax-general.c (generic_ext): " + "opcode has inadequate range")); grow_expr (x, 2); x->buf[x->len++] = op; @@ -182,7 +197,8 @@ ax_trace_quick (struct agent_expr *x, int n) { /* N must fit in a byte. */ if (n < 0 || n > 255) - error (_("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick")); + error (_("GDB bug: ax-general.c (ax_trace_quick): " + "size out of range for trace_quick")); grow_expr (x, 2); x->buf[x->len++] = aop_trace_quick; @@ -246,7 +262,7 @@ ax_const_l (struct agent_expr *x, LONGEST l) break; } - /* Emit the right opcode... */ + /* Emit the right opcode... */ ax_simple (x, ops[op]); /* Emit the low SIZE bytes as an unsigned number. We know that @@ -263,7 +279,8 @@ void ax_const_d (struct agent_expr *x, LONGEST d) { /* FIXME: floating-point support not present yet. */ - error (_("GDB bug: ax-general.c (ax_const_d): floating point not supported yet")); + error (_("GDB bug: ax-general.c (ax_const_d): " + "floating point not supported yet")); } @@ -272,14 +289,29 @@ ax_const_d (struct agent_expr *x, LONGEST d) void ax_reg (struct agent_expr *x, int reg) { - /* Make sure the register number is in range. */ - if (reg < 0 || reg > 0xffff) - error (_("GDB bug: ax-general.c (ax_reg): register number out of range")); - grow_expr (x, 3); - x->buf[x->len] = aop_reg; - x->buf[x->len + 1] = (reg >> 8) & 0xff; - x->buf[x->len + 2] = (reg) & 0xff; - x->len += 3; + if (reg >= gdbarch_num_regs (x->gdbarch)) + { + /* This is a pseudo-register. */ + if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch)) + error (_("'%s' is a pseudo-register; " + "GDB cannot yet trace its contents."), + user_reg_map_regnum_to_name (x->gdbarch, reg)); + if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg)) + error (_("Trace '%s' failed."), + user_reg_map_regnum_to_name (x->gdbarch, reg)); + } + else + { + /* Make sure the register number is in range. */ + if (reg < 0 || reg > 0xffff) + error (_("GDB bug: ax-general.c (ax_reg): " + "register number out of range")); + grow_expr (x, 3); + x->buf[x->len] = aop_reg; + x->buf[x->len + 1] = (reg >> 8) & 0xff; + x->buf[x->len + 2] = (reg) & 0xff; + x->len += 3; + } } /* Assemble code to operate on a trace state variable. */ @@ -289,7 +321,9 @@ ax_tsv (struct agent_expr *x, enum agent_op op, int num) { /* Make sure the tsv number is in range. */ if (num < 0 || num > 0xffff) - internal_error (__FILE__, __LINE__, _("ax-general.c (ax_tsv): variable number is %d, out of range"), num); + internal_error (__FILE__, __LINE__, + _("ax-general.c (ax_tsv): variable " + "number is %d, out of range"), num); grow_expr (x, 3); x->buf[x->len] = op; @@ -305,55 +339,11 @@ ax_tsv (struct agent_expr *x, enum agent_op op, int num) struct aop_map aop_map[] = { - {0, 0, 0, 0, 0}, - {"float", 0, 0, 0, 0}, /* 0x01 */ - {"add", 0, 0, 2, 1}, /* 0x02 */ - {"sub", 0, 0, 2, 1}, /* 0x03 */ - {"mul", 0, 0, 2, 1}, /* 0x04 */ - {"div_signed", 0, 0, 2, 1}, /* 0x05 */ - {"div_unsigned", 0, 0, 2, 1}, /* 0x06 */ - {"rem_signed", 0, 0, 2, 1}, /* 0x07 */ - {"rem_unsigned", 0, 0, 2, 1}, /* 0x08 */ - {"lsh", 0, 0, 2, 1}, /* 0x09 */ - {"rsh_signed", 0, 0, 2, 1}, /* 0x0a */ - {"rsh_unsigned", 0, 0, 2, 1}, /* 0x0b */ - {"trace", 0, 0, 2, 0}, /* 0x0c */ - {"trace_quick", 1, 0, 1, 1}, /* 0x0d */ - {"log_not", 0, 0, 1, 1}, /* 0x0e */ - {"bit_and", 0, 0, 2, 1}, /* 0x0f */ - {"bit_or", 0, 0, 2, 1}, /* 0x10 */ - {"bit_xor", 0, 0, 2, 1}, /* 0x11 */ - {"bit_not", 0, 0, 1, 1}, /* 0x12 */ - {"equal", 0, 0, 2, 1}, /* 0x13 */ - {"less_signed", 0, 0, 2, 1}, /* 0x14 */ - {"less_unsigned", 0, 0, 2, 1}, /* 0x15 */ - {"ext", 1, 0, 1, 1}, /* 0x16 */ - {"ref8", 0, 8, 1, 1}, /* 0x17 */ - {"ref16", 0, 16, 1, 1}, /* 0x18 */ - {"ref32", 0, 32, 1, 1}, /* 0x19 */ - {"ref64", 0, 64, 1, 1}, /* 0x1a */ - {"ref_float", 0, 0, 1, 1}, /* 0x1b */ - {"ref_double", 0, 0, 1, 1}, /* 0x1c */ - {"ref_long_double", 0, 0, 1, 1}, /* 0x1d */ - {"l_to_d", 0, 0, 1, 1}, /* 0x1e */ - {"d_to_l", 0, 0, 1, 1}, /* 0x1f */ - {"if_goto", 2, 0, 1, 0}, /* 0x20 */ - {"goto", 2, 0, 0, 0}, /* 0x21 */ - {"const8", 1, 8, 0, 1}, /* 0x22 */ - {"const16", 2, 16, 0, 1}, /* 0x23 */ - {"const32", 4, 32, 0, 1}, /* 0x24 */ - {"const64", 8, 64, 0, 1}, /* 0x25 */ - {"reg", 2, 0, 0, 1}, /* 0x26 */ - {"end", 0, 0, 0, 0}, /* 0x27 */ - {"dup", 0, 0, 1, 2}, /* 0x28 */ - {"pop", 0, 0, 1, 0}, /* 0x29 */ - {"zero_ext", 1, 0, 1, 1}, /* 0x2a */ - {"swap", 0, 0, 2, 2}, /* 0x2b */ - {"getv", 2, 0, 0, 1}, /* 0x2c */ - {"setv", 2, 0, 0, 1}, /* 0x2d */ - {"tracev", 2, 0, 0, 1}, /* 0x2e */ - {0, 0, 0, 0, 0}, /* 0x2f */ - {"trace16", 2, 0, 1, 1}, /* 0x30 */ + {0, 0, 0, 0, 0} +#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ + , { # NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED } +#include "ax.def" +#undef DEFOP }; @@ -413,23 +403,38 @@ ax_print (struct ui_file *f, struct agent_expr *x) void ax_reg_mask (struct agent_expr *ax, int reg) { - int byte = reg / 8; - - /* Grow the bit mask if necessary. */ - if (byte >= ax->reg_mask_len) + if (reg >= gdbarch_num_regs (ax->gdbarch)) { - /* It's not appropriate to double here. This isn't a - string buffer. */ - int new_len = byte + 1; - unsigned char *new_reg_mask = xrealloc (ax->reg_mask, - new_len * sizeof (ax->reg_mask[0])); - memset (new_reg_mask + ax->reg_mask_len, 0, - (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0])); - ax->reg_mask_len = new_len; - ax->reg_mask = new_reg_mask; + /* This is a pseudo-register. */ + if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch)) + error (_("'%s' is a pseudo-register; " + "GDB cannot yet trace its contents."), + user_reg_map_regnum_to_name (ax->gdbarch, reg)); + if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg)) + error (_("Trace '%s' failed."), + user_reg_map_regnum_to_name (ax->gdbarch, reg)); + } + else + { + int byte = reg / 8; + + /* Grow the bit mask if necessary. */ + if (byte >= ax->reg_mask_len) + { + /* It's not appropriate to double here. This isn't a + string buffer. */ + int new_len = byte + 1; + unsigned char *new_reg_mask = xrealloc (ax->reg_mask, + new_len + * sizeof (ax->reg_mask[0])); + memset (new_reg_mask + ax->reg_mask_len, 0, + (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0])); + ax->reg_mask_len = new_len; + ax->reg_mask = new_reg_mask; + } + + ax->reg_mask[byte] |= 1 << (reg % 8); } - - ax->reg_mask[byte] |= 1 << (reg % 8); } /* Given an agent expression AX, fill in requirements and other descriptive diff --git a/contrib/gdb-7/gdb/ax.h b/contrib/gdb-7/gdb/ax.h index 6ff18aaf4a..a124575010 100644 --- a/contrib/gdb-7/gdb/ax.h +++ b/contrib/gdb-7/gdb/ax.h @@ -1,5 +1,5 @@ /* Definitions for expressions designed to be executed on the agent - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010 + Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -145,65 +145,14 @@ struct agent_expr unsigned char *reg_mask; }; -/* The actual values of the various bytecode operations. - - Other independent implementations of the agent bytecode engine will - rely on the exact values of these enums, and may not be recompiled - when we change this table. The numeric values should remain fixed - whenever possible. Thus, we assign them values explicitly here (to - allow gaps to form safely), and the disassembly table in - agentexpr.h behaves like an opcode map. If you want to see them - grouped logically, see doc/agentexpr.texi. */ +/* The actual values of the various bytecode operations. */ enum agent_op { - aop_float = 0x01, - aop_add = 0x02, - aop_sub = 0x03, - aop_mul = 0x04, - aop_div_signed = 0x05, - aop_div_unsigned = 0x06, - aop_rem_signed = 0x07, - aop_rem_unsigned = 0x08, - aop_lsh = 0x09, - aop_rsh_signed = 0x0a, - aop_rsh_unsigned = 0x0b, - aop_trace = 0x0c, - aop_trace_quick = 0x0d, - aop_log_not = 0x0e, - aop_bit_and = 0x0f, - aop_bit_or = 0x10, - aop_bit_xor = 0x11, - aop_bit_not = 0x12, - aop_equal = 0x13, - aop_less_signed = 0x14, - aop_less_unsigned = 0x15, - aop_ext = 0x16, - aop_ref8 = 0x17, - aop_ref16 = 0x18, - aop_ref32 = 0x19, - aop_ref64 = 0x1a, - aop_ref_float = 0x1b, - aop_ref_double = 0x1c, - aop_ref_long_double = 0x1d, - aop_l_to_d = 0x1e, - aop_d_to_l = 0x1f, - aop_if_goto = 0x20, - aop_goto = 0x21, - aop_const8 = 0x22, - aop_const16 = 0x23, - aop_const32 = 0x24, - aop_const64 = 0x25, - aop_reg = 0x26, - aop_end = 0x27, - aop_dup = 0x28, - aop_pop = 0x29, - aop_zero_ext = 0x2a, - aop_swap = 0x2b, - aop_getv = 0x2c, - aop_setv = 0x2d, - aop_tracev = 0x2e, - aop_trace16 = 0x30, +#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ + aop_ ## NAME = VALUE, +#include "ax.def" +#undef DEFOP aop_last }; @@ -221,6 +170,10 @@ extern struct cleanup *make_cleanup_free_agent_expr (struct agent_expr *); /* Append a simple operator OP to EXPR. */ extern void ax_simple (struct agent_expr *EXPR, enum agent_op OP); +/* Append a pick operator to EXPR. DEPTH is the stack item to pick, + with 0 being top of stack. */ +extern void ax_pick (struct agent_expr *EXPR, int DEPTH); + /* Append the floating-point prefix, for the next bytecode. */ #define ax_float(EXPR) (ax_simple ((EXPR), aop_float)) @@ -274,7 +227,7 @@ struct aop_map /* The name of the opcode. Null means that this entry is not a valid opcode --- a hole in the opcode space. */ - char *name; + const char *name; /* All opcodes take no operands from the bytecode stream, or take unsigned integers of various sizes. If this is a positive number diff --git a/contrib/gdb-7/gdb/bcache.c b/contrib/gdb-7/gdb/bcache.c index 7d9180cbec..76e3893647 100644 --- a/contrib/gdb-7/gdb/bcache.c +++ b/contrib/gdb-7/gdb/bcache.c @@ -2,7 +2,7 @@ Written by Fred Fish Rewritten by Jim Blandy - Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -89,21 +89,33 @@ struct bcache 16 bits of hash values) hit, but the corresponding combined length/data compare missed. */ unsigned long half_hash_miss_count; + + /* Hash function to be used for this bcache object. */ + unsigned long (*hash_function)(const void *addr, int length); + + /* Compare function to be used for this bcache object. */ + int (*compare_function)(const void *, const void *, int length); }; -/* The old hash function was stolen from SDBM. This is what DB 3.0 uses now, - * and is better than the old one. - */ +/* The old hash function was stolen from SDBM. This is what DB 3.0 + uses now, and is better than the old one. */ unsigned long hash(const void *addr, int length) +{ + return hash_continue (addr, length, 0); +} + +/* Continue the calculation of the hash H at the given address. */ + +unsigned long +hash_continue (const void *addr, int length, unsigned long h) { const unsigned char *k, *e; - unsigned long h; k = (const unsigned char *)addr; e = k+length; - for (h=0; k< e;++k) + for (; k< e;++k) { h *=16777619; h ^= *k; @@ -171,7 +183,8 @@ expand_hash_table (struct bcache *bcache) struct bstring **new_bucket; next = s->next; - new_bucket = &new_buckets[(hash (&s->d.data, s->length) + new_bucket = &new_buckets[(bcache->hash_function (&s->d.data, + s->length) % new_num_buckets)]; s->next = *new_bucket; *new_bucket = s; @@ -235,7 +248,8 @@ bcache_full (const void *addr, int length, struct bcache *bcache, int *added) bcache->total_count++; bcache->total_size += length; - full_hash = hash (addr, length); + full_hash = bcache->hash_function (addr, length); + half_hash = (full_hash >> 16); hash_index = full_hash % bcache->num_buckets; @@ -247,7 +261,7 @@ bcache_full (const void *addr, int length, struct bcache *bcache, int *added) if (s->half_hash == half_hash) { if (s->length == length - && ! memcmp (&s->d.data, addr, length)) + && bcache->compare_function (&s->d.data, addr, length)) return &s->d.data; else bcache->half_hash_miss_count++; @@ -276,14 +290,41 @@ bcache_full (const void *addr, int length, struct bcache *bcache, int *added) } } + +/* Compare the byte string at ADDR1 of lenght LENGHT to the + string at ADDR2. Return 1 if they are equal. */ + +static int +bcache_compare (const void *addr1, const void *addr2, int length) +{ + return memcmp (addr1, addr2, length) == 0; +} + /* Allocating and freeing bcaches. */ +/* Allocated a bcache. HASH_FUNCTION and COMPARE_FUNCTION can be used + to pass in custom hash, and compare functions to be used by this + bcache. If HASH_FUNCTION is NULL hash() is used and if + COMPARE_FUNCTION is NULL memcmp() is used. */ + struct bcache * -bcache_xmalloc (void) +bcache_xmalloc (unsigned long (*hash_function)(const void *, int length), + int (*compare_function)(const void *, + const void *, + int length)) { /* Allocate the bcache pre-zeroed. */ struct bcache *b = XCALLOC (1, struct bcache); + if (hash_function) + b->hash_function = hash_function; + else + b->hash_function = hash; + + if (compare_function) + b->compare_function = compare_function; + else + b->compare_function = bcache_compare; return b; } @@ -308,7 +349,7 @@ static void print_percentage (int portion, int total) { if (total == 0) - /* i18n: Like "Percentage of duplicates, by count: (not applicable)" */ + /* i18n: Like "Percentage of duplicates, by count: (not applicable)". */ printf_filtered (_("(not applicable)\n")); else printf_filtered ("%3d%%\n", (int) (portion * 100.0 / total)); @@ -359,7 +400,8 @@ print_bcache_statistics (struct bcache *c, char *type) } } - /* To compute the median, we need the set of chain lengths sorted. */ + /* To compute the median, we need the set of chain lengths + sorted. */ qsort (chain_length, c->num_buckets, sizeof (chain_length[0]), compare_positive_ints); qsort (entry_size, c->unique_count, sizeof (entry_size[0]), @@ -408,12 +450,13 @@ print_bcache_statistics (struct bcache *c, char *type) if (c->unique_count > 0) printf_filtered ("%ld\n", c->unique_size / c->unique_count); else - /* i18n: "Average entry size: (not applicable)" */ + /* i18n: "Average entry size: (not applicable)". */ printf_filtered (_("(not applicable)\n")); printf_filtered (_(" Median entry size: %d\n"), median_entry_size); printf_filtered ("\n"); - printf_filtered (_(" Total memory used by bcache, including overhead: %ld\n"), + printf_filtered (_(" \ +Total memory used by bcache, including overhead: %ld\n"), c->structure_size); printf_filtered (_(" Percentage memory overhead: ")); print_percentage (c->structure_size - c->unique_size, c->unique_size); @@ -421,7 +464,8 @@ print_bcache_statistics (struct bcache *c, char *type) print_percentage (c->total_size - c->structure_size, c->total_size); printf_filtered ("\n"); - printf_filtered (_(" Hash table size: %3d\n"), c->num_buckets); + printf_filtered (_(" Hash table size: %3d\n"), + c->num_buckets); printf_filtered (_(" Hash table expands: %lu\n"), c->expand_count); printf_filtered (_(" Hash table hashes: %lu\n"), @@ -436,9 +480,10 @@ print_bcache_statistics (struct bcache *c, char *type) if (c->num_buckets > 0) printf_filtered ("%3lu\n", c->unique_count / c->num_buckets); else - /* i18n: "Average hash chain length: (not applicable)" */ + /* i18n: "Average hash chain length: (not applicable)". */ printf_filtered (_("(not applicable)\n")); - printf_filtered (_(" Maximum hash chain length: %3d\n"), max_chain_length); + printf_filtered (_(" Maximum hash chain length: %3d\n"), + max_chain_length); printf_filtered ("\n"); } diff --git a/contrib/gdb-7/gdb/bcache.h b/contrib/gdb-7/gdb/bcache.h index da69a2da42..66106e767d 100644 --- a/contrib/gdb-7/gdb/bcache.h +++ b/contrib/gdb-7/gdb/bcache.h @@ -2,7 +2,7 @@ Written by Fred Fish Rewritten by Jim Blandy - Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -158,7 +158,9 @@ extern const void *bcache_full (const void *addr, int length, extern void bcache_xfree (struct bcache *bcache); /* Create a new bcache object. */ -extern struct bcache *bcache_xmalloc (void); +extern struct bcache *bcache_xmalloc ( + unsigned long (*hash_function)(const void *, int length), + int (*compare_function)(const void *, const void *, int length)); /* Print statistics on BCACHE's memory usage and efficacity at eliminating duplication. TYPE should be a string describing the @@ -167,7 +169,9 @@ extern struct bcache *bcache_xmalloc (void); extern void print_bcache_statistics (struct bcache *bcache, char *type); extern int bcache_memory_used (struct bcache *bcache); -/* The hash function */ +/* The hash functions */ extern unsigned long hash(const void *addr, int length); +extern unsigned long hash_continue (const void *addr, int length, + unsigned long h); #endif /* BCACHE_H */ diff --git a/contrib/gdb-7/gdb/bfd-target.c b/contrib/gdb-7/gdb/bfd-target.c index 476035094b..cfeb0b12f6 100644 --- a/contrib/gdb-7/gdb/bfd-target.c +++ b/contrib/gdb-7/gdb/bfd-target.c @@ -1,6 +1,6 @@ /* Very simple "bfd" target, for GDB, the GNU debugger. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bfd-target.h b/contrib/gdb-7/gdb/bfd-target.h index d7e0f19db0..9771151052 100644 --- a/contrib/gdb-7/gdb/bfd-target.h +++ b/contrib/gdb-7/gdb/bfd-target.h @@ -1,6 +1,7 @@ /* Very simple "bfd" target, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/block.c b/contrib/gdb-7/gdb/block.c index 48ac21bd62..776ae53f5a 100644 --- a/contrib/gdb-7/gdb/block.c +++ b/contrib/gdb-7/gdb/block.c @@ -1,6 +1,7 @@ /* Block-related functions for the GNU debugger, GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -40,7 +41,7 @@ static void block_initialize_namespace (struct block *block, /* Return Nonzero if block a is lexically nested within block b, or if a and b have the same pc range. - Return zero otherwise. */ + Return zero otherwise. */ int contained_in (const struct block *a, const struct block *b) diff --git a/contrib/gdb-7/gdb/block.h b/contrib/gdb-7/gdb/block.h index 7eedb6c8fe..07d5bc7220 100644 --- a/contrib/gdb-7/gdb/block.h +++ b/contrib/gdb-7/gdb/block.h @@ -1,6 +1,7 @@ /* Code dealing with blocks for GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/blockframe.c b/contrib/gdb-7/gdb/blockframe.c index 0348bf4247..3b546a7875 100644 --- a/contrib/gdb-7/gdb/blockframe.c +++ b/contrib/gdb-7/gdb/blockframe.c @@ -3,7 +3,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -39,8 +39,8 @@ #include "inline-frame.h" #include "psymtab.h" -/* Return the innermost lexical block in execution - in a specified stack frame. The frame address is assumed valid. +/* Return the innermost lexical block in execution in a specified + stack frame. The frame address is assumed valid. If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the exact code address we used to choose the block. We use this to find a source @@ -58,10 +58,13 @@ struct block * get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block) { - const CORE_ADDR pc = get_frame_address_in_block (frame); + CORE_ADDR pc; struct block *bl; int inline_count; + if (!get_frame_address_in_block_if_available (frame, &pc)) + return NULL; + if (addr_in_block) *addr_in_block = pc; @@ -144,7 +147,8 @@ find_pc_sect_function (CORE_ADDR pc, struct obj_section *section) } /* Return the function containing pc value PC. - Returns 0 if function is not known. Backward compatibility, no section */ + Returns 0 if function is not known. + Backward compatibility, no section */ struct symbol * find_pc_function (CORE_ADDR pc) @@ -153,14 +157,15 @@ find_pc_function (CORE_ADDR pc) } /* These variables are used to cache the most recent result - * of find_pc_partial_function. */ + of find_pc_partial_function. */ static CORE_ADDR cache_pc_function_low = 0; static CORE_ADDR cache_pc_function_high = 0; static char *cache_pc_function_name = 0; static struct obj_section *cache_pc_function_section = NULL; +static int cache_pc_function_is_gnu_ifunc = 0; -/* Clear cache, e.g. when symbol table is discarded. */ +/* Clear cache, e.g. when symbol table is discarded. */ void clear_pc_function_cache (void) @@ -169,6 +174,7 @@ clear_pc_function_cache (void) cache_pc_function_high = 0; cache_pc_function_name = (char *) 0; cache_pc_function_section = NULL; + cache_pc_function_is_gnu_ifunc = 0; } /* Finds the "function" (text symbol) that is smaller than PC but @@ -176,17 +182,19 @@ clear_pc_function_cache (void) *NAME and/or *ADDRESS conditionally if that pointer is non-null. If ENDADDR is non-null, then set *ENDADDR to be the end of the function (exclusive), but passing ENDADDR as non-null means that - the function might cause symbols to be read. This function either - succeeds or fails (not halfway succeeds). If it succeeds, it sets - *NAME, *ADDRESS, and *ENDADDR to real information and returns 1. - If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero and - returns 0. */ + the function might cause symbols to be read. If IS_GNU_IFUNC_P is provided + *IS_GNU_IFUNC_P is set to 1 on return if the function is STT_GNU_IFUNC. + This function either succeeds or fails (not halfway succeeds). If it + succeeds, it sets *NAME, *ADDRESS, and *ENDADDR to real information and + returns 1. If it fails, it sets *NAME, *ADDRESS, *ENDADDR and + *IS_GNU_IFUNC_P to zero and returns 0. */ /* Backward compatibility, no section argument. */ int -find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, - CORE_ADDR *endaddr) +find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, char **name, + CORE_ADDR *address, CORE_ADDR *endaddr, + int *is_gnu_ifunc_p) { struct obj_section *section; struct symbol *f; @@ -236,14 +244,15 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_name = SYMBOL_LINKAGE_NAME (f); cache_pc_function_section = section; + cache_pc_function_is_gnu_ifunc = TYPE_GNU_IFUNC (SYMBOL_TYPE (f)); goto return_cached_value; } } - /* Not in the normal symbol tables, see if the pc is in a known section. - If it's not, then give up. This ensures that anything beyond the end - of the text seg doesn't appear to be part of the last function in the - text segment. */ + /* Not in the normal symbol tables, see if the pc is in a known + section. If it's not, then give up. This ensures that anything + beyond the end of the text seg doesn't appear to be part of the + last function in the text segment. */ if (!section) msymbol = NULL; @@ -258,12 +267,15 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *address = 0; if (endaddr != NULL) *endaddr = 0; + if (is_gnu_ifunc_p != NULL) + *is_gnu_ifunc_p = 0; return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = SYMBOL_LINKAGE_NAME (msymbol); cache_pc_function_section = section; + cache_pc_function_is_gnu_ifunc = MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; /* If the minimal symbol has a size, use it for the cache. Otherwise use the lesser of the next minimal symbol in the same @@ -280,13 +292,16 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { - if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol) - && SYMBOL_OBJ_SECTION (msymbol + i) == SYMBOL_OBJ_SECTION (msymbol)) + if (SYMBOL_VALUE_ADDRESS (msymbol + i) + != SYMBOL_VALUE_ADDRESS (msymbol) + && SYMBOL_OBJ_SECTION (msymbol + i) + == SYMBOL_OBJ_SECTION (msymbol)) break; } if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL - && SYMBOL_VALUE_ADDRESS (msymbol + i) < obj_section_endaddr (section)) + && SYMBOL_VALUE_ADDRESS (msymbol + i) + < obj_section_endaddr (section)) cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. @@ -314,7 +329,7 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and - then add one to that. */ + then add one to that. */ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); @@ -323,11 +338,24 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *endaddr = cache_pc_function_high; } + if (is_gnu_ifunc_p) + *is_gnu_ifunc_p = cache_pc_function_is_gnu_ifunc; + return 1; } -/* Return the innermost stack frame executing inside of BLOCK, - or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */ +/* See find_pc_partial_function_gnu_ifunc, only the IS_GNU_IFUNC_P parameter + is omitted here for backward API compatibility. */ + +int +find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, + CORE_ADDR *endaddr) +{ + return find_pc_partial_function_gnu_ifunc (pc, name, address, endaddr, NULL); +} + +/* Return the innermost stack frame executing inside of BLOCK, or NULL + if there is no such frame. If BLOCK is NULL, just return NULL. */ struct frame_info * block_innermost_frame (struct block *block) diff --git a/contrib/gdb-7/gdb/breakpoint.c b/contrib/gdb-7/gdb/breakpoint.c index 6a6864cf33..3ec99416d4 100644 --- a/contrib/gdb-7/gdb/breakpoint.c +++ b/contrib/gdb-7/gdb/breakpoint.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -39,6 +39,7 @@ #include "language.h" #include "gdb_string.h" #include "demangle.h" +#include "filenames.h" #include "annotate.h" #include "symfile.h" #include "objfiles.h" @@ -62,6 +63,7 @@ #include "jit.h" #include "xml-syscall.h" #include "parser-defs.h" +#include "cli/cli-utils.h" /* readline include files */ #include "readline/readline.h" @@ -71,12 +73,13 @@ #undef savestring #include "mi/mi-common.h" +#include "python/python.h" /* Arguments to pass as context to some catch command handlers. */ #define CATCH_PERMANENT ((void *) (uintptr_t) 0) #define CATCH_TEMPORARY ((void *) (uintptr_t) 1) -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static void enable_delete_command (char *, int); @@ -98,15 +101,14 @@ static void clear_command (char *, int); static void catch_command (char *, int); -static void watch_command (char *, int); - -static int can_use_hardware_watchpoint (struct value *); +static int can_use_hardware_watchpoint (struct value *, int); static void break_command_1 (char *, int, int); static void mention (struct breakpoint *); -/* This function is used in gdbtk sources and thus can not be made static. */ +/* This function is used in gdbtk sources and thus can not be made + static. */ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line, enum bptype); @@ -129,13 +131,16 @@ static int breakpoint_address_match (struct address_space *aspace1, static int watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2); +static int breakpoint_location_address_match (struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR addr); + static void breakpoints_info (char *, int); static void watchpoints_info (char *, int); -static int breakpoint_1 (int, int, int (*) (const struct breakpoint *)); - -static bpstat bpstat_alloc (const struct bp_location *, bpstat); +static int breakpoint_1 (char *, int, + int (*) (const struct breakpoint *)); static int breakpoint_cond_eval (void *); @@ -145,8 +150,6 @@ static void commands_command (char *, int); static void condition_command (char *, int); -static int get_number_trailer (char **, int); - typedef enum { mark_inserted, @@ -173,12 +176,6 @@ static void hbreak_command (char *, int); static void thbreak_command (char *, int); -static void watch_command_1 (char *, int, int); - -static void rwatch_command (char *, int); - -static void awatch_command (char *, int); - static void do_enable_breakpoint (struct breakpoint *, enum bpdisp); static void stop_command (char *arg, int from_tty); @@ -194,14 +191,14 @@ static void catch_exception_command_1 (enum exception_event_kind ex_event, static void tcatch_command (char *arg, int from_tty); -static void ep_skip_leading_whitespace (char **s); - static void detach_single_step_breakpoints (void); static int single_step_breakpoint_inserted_here_p (struct address_space *, CORE_ADDR pc); static void free_bp_location (struct bp_location *loc); +static void incref_bp_location (struct bp_location *loc); +static void decref_bp_location (struct bp_location **loc); static struct bp_location *allocate_bp_location (struct breakpoint *bpt); @@ -209,9 +206,6 @@ static void update_global_location_list (int); static void update_global_location_list_nothrow (int); -static int bpstat_remove_bp_location_callback (struct thread_info *th, - void *data); - static int is_hardware_watchpoint (const struct breakpoint *bpt); static int is_watchpoint (const struct breakpoint *bpt); @@ -233,7 +227,7 @@ static void trace_pass_command (char *, int); /* Assuming we're creating a static tracepoint, does S look like a static tracepoint marker spec ("-m MARKER_ID")? */ #define is_marker_spec(s) \ - (strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t')) + (s != NULL && strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t')) /* A reference-counted struct command_line. This lets multiple breakpoints share a single command list. */ @@ -257,19 +251,20 @@ breakpoint_commands (struct breakpoint *b) static int breakpoint_proceeded; -static const char * +const char * bpdisp_text (enum bpdisp disp) { - /* NOTE: the following values are a part of MI protocol and represent - values of 'disp' field returned when inferior stops at a breakpoint. */ - static char *bpdisps[] = {"del", "dstp", "dis", "keep"}; + /* NOTE: the following values are a part of MI protocol and + represent values of 'disp' field returned when inferior stops at + a breakpoint. */ + static const char * const bpdisps[] = {"del", "dstp", "dis", "keep"}; return bpdisps[(int) disp]; } -/* Prototypes for exported functions. */ +/* Prototypes for exported functions. */ /* If FALSE, gdb will not use hardware support for watchpoints, even - if such is available. */ + if such is available. */ static int can_use_hw_watchpoints; static void @@ -277,14 +272,15 @@ show_can_use_hw_watchpoints (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Debugger's willingness to use watchpoint hardware is %s.\n"), + fprintf_filtered (file, + _("Debugger's willingness to use " + "watchpoint hardware is %s.\n"), value); } /* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints. If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints - for unrecognized breakpoint locations. + for unrecognized breakpoint locations. If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */ static enum auto_boolean pending_break_support; static void @@ -292,13 +288,14 @@ show_pending_break_support (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Debugger's behavior regarding pending breakpoints is %s.\n"), + fprintf_filtered (file, + _("Debugger's behavior regarding " + "pending breakpoints is %s.\n"), value); } /* If 1, gdb will automatically use hardware breakpoints for breakpoints - set with "break" but falling in read-only memory. + set with "break" but falling in read-only memory. If 0, gdb will warn about such breakpoints, but won't automatically use hardware breakpoints. */ static int automatic_hardware_breakpoints; @@ -307,8 +304,8 @@ show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Automatic usage of hardware breakpoints is %s.\n"), + fprintf_filtered (file, + _("Automatic usage of hardware breakpoints is %s.\n"), value); } @@ -333,12 +330,14 @@ show_always_inserted_mode (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { if (always_inserted_mode == always_inserted_auto) - fprintf_filtered (file, _("\ -Always inserted breakpoint mode is %s (currently %s).\n"), + fprintf_filtered (file, + _("Always inserted breakpoint " + "mode is %s (currently %s).\n"), value, breakpoints_always_inserted_mode () ? "on" : "off"); else - fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), value); + fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), + value); } int @@ -356,9 +355,12 @@ static int executing_breakpoint_commands; /* Are overlay event breakpoints enabled? */ static int overlay_events_enabled; +/* See description in breakpoint.h. */ +int target_exact_watchpoints = 0; + /* Walk the following statement or block through all breakpoints. - ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current - breakpoint. */ + ALL_BREAKPOINTS_SAFE does so even if the statment deletes the + current breakpoint. */ #define ALL_BREAKPOINTS(B) for (B = breakpoint_chain; B; B = B->next) @@ -367,9 +369,9 @@ static int overlay_events_enabled; B ? (TMP=B->next, 1): 0; \ B = TMP) -/* Similar iterator for the low-level breakpoints. SAFE variant is not - provided so update_global_location_list must not be called while executing - the block of ALL_BP_LOCATIONS. */ +/* Similar iterator for the low-level breakpoints. SAFE variant is + not provided so update_global_location_list must not be called + while executing the block of ALL_BP_LOCATIONS. */ #define ALL_BP_LOCATIONS(B,BP_TMP) \ for (BP_TMP = bp_location; \ @@ -394,24 +396,25 @@ static struct bp_location **bp_location; static unsigned bp_location_count; -/* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and ADDRESS - for the current elements of BP_LOCATION which get a valid result from - bp_location_has_shadow. You can use it for roughly limiting the subrange of - BP_LOCATION to scan for shadow bytes for an address you need to read. */ +/* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and + ADDRESS for the current elements of BP_LOCATION which get a valid + result from bp_location_has_shadow. You can use it for roughly + limiting the subrange of BP_LOCATION to scan for shadow bytes for + an address you need to read. */ static CORE_ADDR bp_location_placed_address_before_address_max; -/* Maximum offset plus alignment between - bp_target_info.PLACED_ADDRESS + bp_target_info.SHADOW_LEN and ADDRESS for - the current elements of BP_LOCATION which get a valid result from - bp_location_has_shadow. You can use it for roughly limiting the subrange of - BP_LOCATION to scan for shadow bytes for an address you need to read. */ +/* Maximum offset plus alignment between bp_target_info.PLACED_ADDRESS + + bp_target_info.SHADOW_LEN and ADDRESS for the current elements of + BP_LOCATION which get a valid result from bp_location_has_shadow. + You can use it for roughly limiting the subrange of BP_LOCATION to + scan for shadow bytes for an address you need to read. */ static CORE_ADDR bp_location_shadow_len_after_address_max; -/* The locations that no longer correspond to any breakpoint, - unlinked from bp_location array, but for which a hit - may still be reported by a target. */ +/* The locations that no longer correspond to any breakpoint, unlinked + from bp_location array, but for which a hit may still be reported + by a target. */ VEC(bp_location_p) *moribund_locations = NULL; /* Number of last breakpoint made. */ @@ -430,7 +433,7 @@ static int tracepoint_count; static struct cmd_list_element *breakpoint_set_cmdlist; static struct cmd_list_element *breakpoint_show_cmdlist; -static struct cmd_list_element *save_cmdlist; +struct cmd_list_element *save_cmdlist; /* Return whether a breakpoint is an active enabled breakpoint. */ static int @@ -471,7 +474,7 @@ end_rbreak_breakpoints (void) prev_breakpoint_count = rbreak_start_breakpoint_count; } -/* Used in run_command to zero the hit count when a new run starts. */ +/* Used in run_command to zero the hit count when a new run starts. */ void clear_breakpoint_hit_counts (void) @@ -542,7 +545,7 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) /* Default address, symtab and line to put a breakpoint at for "break" command with no arg. - if default_breakpoint_valid is zero, the other three are + If default_breakpoint_valid is zero, the other three are not valid, and "break" with no arg is an error. This set by print_stack_frame, which calls set_default_breakpoint. */ @@ -554,162 +557,6 @@ int default_breakpoint_line; struct program_space *default_breakpoint_pspace; -/* *PP is a string denoting a breakpoint. Get the number of the breakpoint. - Advance *PP after the string and any trailing whitespace. - - Currently the string can either be a number or "$" followed by the name - of a convenience variable. Making it an expression wouldn't work well - for map_breakpoint_numbers (e.g. "4 + 5 + 6"). - - If the string is a NULL pointer, that denotes the last breakpoint. - - TRAILER is a character which can be found after the number; most - commonly this is `-'. If you don't want a trailer, use \0. */ -static int -get_number_trailer (char **pp, int trailer) -{ - int retval = 0; /* default */ - char *p = *pp; - - if (p == NULL) - /* Empty line means refer to the last breakpoint. */ - return breakpoint_count; - else if (*p == '$') - { - /* Make a copy of the name, so we can null-terminate it - to pass to lookup_internalvar(). */ - char *varname; - char *start = ++p; - LONGEST val; - - while (isalnum (*p) || *p == '_') - p++; - varname = (char *) alloca (p - start + 1); - strncpy (varname, start, p - start); - varname[p - start] = '\0'; - if (get_internalvar_integer (lookup_internalvar (varname), &val)) - retval = (int) val; - else - { - printf_filtered (_("Convenience variable must have integer value.\n")); - retval = 0; - } - } - else - { - if (*p == '-') - ++p; - while (*p >= '0' && *p <= '9') - ++p; - if (p == *pp) - /* There is no number here. (e.g. "cond a == b"). */ - { - /* Skip non-numeric token */ - while (*p && !isspace((int) *p)) - ++p; - /* Return zero, which caller must interpret as error. */ - retval = 0; - } - else - retval = atoi (*pp); - } - if (!(isspace (*p) || *p == '\0' || *p == trailer)) - { - /* Trailing junk: return 0 and let caller print error msg. */ - while (!(isspace (*p) || *p == '\0' || *p == trailer)) - ++p; - retval = 0; - } - while (isspace (*p)) - p++; - *pp = p; - return retval; -} - - -/* Like get_number_trailer, but don't allow a trailer. */ -int -get_number (char **pp) -{ - return get_number_trailer (pp, '\0'); -} - -/* Parse a number or a range. - * A number will be of the form handled by get_number. - * A range will be of the form - , and - * will represent all the integers between number1 and number2, - * inclusive. - * - * While processing a range, this fuction is called iteratively; - * At each call it will return the next value in the range. - * - * At the beginning of parsing a range, the char pointer PP will - * be advanced past and left pointing at the '-' token. - * Subsequent calls will not advance the pointer until the range - * is completed. The call that completes the range will advance - * pointer PP past . - */ - -int -get_number_or_range (char **pp) -{ - static int last_retval, end_value; - static char *end_ptr; - static int in_range = 0; - - if (**pp != '-') - { - /* Default case: pp is pointing either to a solo number, - or to the first number of a range. */ - last_retval = get_number_trailer (pp, '-'); - if (**pp == '-') - { - char **temp; - - /* This is the start of a range ( - ). - Skip the '-', parse and remember the second number, - and also remember the end of the final token. */ - - temp = &end_ptr; - end_ptr = *pp + 1; - while (isspace ((int) *end_ptr)) - end_ptr++; /* skip white space */ - end_value = get_number (temp); - if (end_value < last_retval) - { - error (_("inverted range")); - } - else if (end_value == last_retval) - { - /* degenerate range (number1 == number2). Advance the - token pointer so that the range will be treated as a - single number. */ - *pp = end_ptr; - } - else - in_range = 1; - } - } - else if (! in_range) - error (_("negative value")); - else - { - /* pp points to the '-' that betokens a range. All - number-parsing has already been done. Return the next - integer value (one greater than the saved previous value). - Do not advance the token pointer 'pp' until the end of range - is reached. */ - - if (++last_retval == end_value) - { - /* End of range reached; advance token pointer. */ - *pp = end_ptr; - in_range = 0; - } - } - return last_retval; -} - /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -802,6 +649,14 @@ condition_command (char *arg, int from_tty) ALL_BREAKPOINTS (b) if (b->number == bnum) { + /* Check if this breakpoint has a Python object assigned to + it, and if it has a definition of the "stop" + method. This method and conditions entered into GDB from + the CLI are mutually exclusive. */ + if (b->py_bp_object + && gdbpy_breakpoint_has_py_cond (b->py_bp_object)) + error (_("Cannot set a condition where a Python 'stop' " + "method has been defined in the breakpoint.")); set_breakpoint_condition (b, p, from_tty); return; } @@ -811,8 +666,8 @@ condition_command (char *arg, int from_tty) /* Check that COMMAND do not contain commands that are suitable only for tracepoints and not suitable for ordinary breakpoints. - Throw if any such commands is found. -*/ + Throw if any such commands is found. */ + static void check_no_tracepoint_commands (struct command_line *commands) { @@ -823,13 +678,14 @@ check_no_tracepoint_commands (struct command_line *commands) int i; if (c->control_type == while_stepping_control) - error (_("The 'while-stepping' command can only be used for tracepoints")); + error (_("The 'while-stepping' command can " + "only be used for tracepoints")); for (i = 0; i < c->body_count; ++i) check_no_tracepoint_commands ((c->body_list)[i]); /* Not that command parsing removes leading whitespace and comment - lines and also empty lines. So, we only need to check for + lines and also empty lines. So, we only need to check for command directly. */ if (strstr (c->line, "collect ") == c->line) error (_("The 'collect' command can only be used for tracepoints")); @@ -859,10 +715,10 @@ validate_commands_for_breakpoint (struct breakpoint *b, { if (is_tracepoint (b)) { - /* We need to verify that each top-level element of commands - is valid for tracepoints, that there's at most one while-stepping - element, and that while-stepping's body has valid tracing commands - excluding nested while-stepping. */ + /* We need to verify that each top-level element of commands is + valid for tracepoints, that there's at most one + while-stepping element, and that while-stepping's body has + valid tracing commands excluding nested while-stepping. */ struct command_line *c; struct command_line *while_stepping = 0; for (c = commands; c; c = c->next) @@ -870,14 +726,15 @@ validate_commands_for_breakpoint (struct breakpoint *b, if (c->control_type == while_stepping_control) { if (b->type == bp_fast_tracepoint) - error (_("\ -The 'while-stepping' command cannot be used for fast tracepoint")); + error (_("The 'while-stepping' command " + "cannot be used for fast tracepoint")); else if (b->type == bp_static_tracepoint) - error (_("\ -The 'while-stepping' command cannot be used for static tracepoint")); + error (_("The 'while-stepping' command " + "cannot be used for static tracepoint")); if (while_stepping) - error (_("The 'while-stepping' command can be used only once")); + error (_("The 'while-stepping' command " + "can be used only once")); else while_stepping = c; } @@ -923,11 +780,11 @@ static_tracepoints_here (CORE_ADDR addr) } /* Set the command list of B to COMMANDS. If breakpoint is tracepoint, - validate that only allowed commands are included. -*/ + validate that only allowed commands are included. */ void -breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) +breakpoint_set_commands (struct breakpoint *b, + struct command_line *commands) { validate_commands_for_breakpoint (b, commands); @@ -937,6 +794,46 @@ breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) observer_notify_breakpoint_modified (b->number); } +/* Set the internal `silent' flag on the breakpoint. Note that this + is not the same as the "silent" that may appear in the breakpoint's + commands. */ + +void +breakpoint_set_silent (struct breakpoint *b, int silent) +{ + int old_silent = b->silent; + + b->silent = silent; + if (old_silent != silent) + observer_notify_breakpoint_modified (b->number); +} + +/* Set the thread for this breakpoint. If THREAD is -1, make the + breakpoint work for any thread. */ + +void +breakpoint_set_thread (struct breakpoint *b, int thread) +{ + int old_thread = b->thread; + + b->thread = thread; + if (old_thread != thread) + observer_notify_breakpoint_modified (b->number); +} + +/* Set the task for this breakpoint. If TASK is 0, make the + breakpoint work for any task. */ + +void +breakpoint_set_task (struct breakpoint *b, int task) +{ + int old_task = b->task; + + b->task = task; + if (old_task != task) + observer_notify_breakpoint_modified (b->number); +} + void check_tracepoint_command (char *line, void *closure) { @@ -984,7 +881,8 @@ do_map_commands_command (struct breakpoint *b, void *data) struct cleanup *old_chain; char *str; - str = xstrprintf (_("Type commands for breakpoint(s) %s, one per line."), + str = xstrprintf (_("Type commands for breakpoint(s) " + "%s, one per line."), info->arg); old_chain = make_cleanup (xfree, str); @@ -1015,7 +913,8 @@ do_map_commands_command (struct breakpoint *b, void *data) } static void -commands_command_1 (char *arg, int from_tty, struct command_line *control) +commands_command_1 (char *arg, int from_tty, + struct command_line *control) { struct cleanup *cleanups; struct commands_info info; @@ -1030,7 +929,8 @@ commands_command_1 (char *arg, int from_tty, struct command_line *control) if (arg == NULL || !*arg) { if (breakpoint_count - prev_breakpoint_count > 1) - arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, breakpoint_count); + arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, + breakpoint_count); else if (breakpoint_count > 0) arg = xstrprintf ("%d", breakpoint_count); else @@ -1096,80 +996,103 @@ bp_location_has_shadow (struct bp_location *bl) by replacing any memory breakpoints with their shadowed contents. The range of shadowed area by each bp_location is: - b->address - bp_location_placed_address_before_address_max - up to b->address + bp_location_shadow_len_after_address_max + bl->address - bp_location_placed_address_before_address_max + up to bl->address + bp_location_shadow_len_after_address_max The range we were requested to resolve shadows for is: memaddr ... memaddr + len Thus the safe cutoff boundaries for performance optimization are - memaddr + len <= b->address - bp_location_placed_address_before_address_max + memaddr + len <= (bl->address + - bp_location_placed_address_before_address_max) and: - b->address + bp_location_shadow_len_after_address_max <= memaddr */ + bl->address + bp_location_shadow_len_after_address_max <= memaddr */ void breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) { - /* Left boundary, right boundary and median element of our binary search. */ + /* Left boundary, right boundary and median element of our binary + search. */ unsigned bc_l, bc_r, bc; - /* Find BC_L which is a leftmost element which may affect BUF content. It is - safe to report lower value but a failure to report higher one. */ + /* Find BC_L which is a leftmost element which may affect BUF + content. It is safe to report lower value but a failure to + report higher one. */ bc_l = 0; bc_r = bp_location_count; while (bc_l + 1 < bc_r) { - struct bp_location *b; + struct bp_location *bl; bc = (bc_l + bc_r) / 2; - b = bp_location[bc]; + bl = bp_location[bc]; - /* Check first B->ADDRESS will not overflow due to the added constant. - Then advance the left boundary only if we are sure the BC element can - in no way affect the BUF content (MEMADDR to MEMADDR + LEN range). + /* Check first BL->ADDRESS will not overflow due to the added + constant. Then advance the left boundary only if we are sure + the BC element can in no way affect the BUF content (MEMADDR + to MEMADDR + LEN range). - Use the BP_LOCATION_SHADOW_LEN_AFTER_ADDRESS_MAX safety offset so that - we cannot miss a breakpoint with its shadow range tail still reaching - MEMADDR. */ + Use the BP_LOCATION_SHADOW_LEN_AFTER_ADDRESS_MAX safety + offset so that we cannot miss a breakpoint with its shadow + range tail still reaching MEMADDR. */ - if (b->address + bp_location_shadow_len_after_address_max >= b->address - && b->address + bp_location_shadow_len_after_address_max <= memaddr) + if ((bl->address + bp_location_shadow_len_after_address_max + >= bl->address) + && (bl->address + bp_location_shadow_len_after_address_max + <= memaddr)) bc_l = bc; else bc_r = bc; } + /* Due to the binary search above, we need to make sure we pick the + first location that's at BC_L's address. E.g., if there are + multiple locations at the same address, BC_L may end up pointing + at a duplicate location, and miss the "master"/"inserted" + location. Say, given locations L1, L2 and L3 at addresses A and + B: + + L1@A, L2@A, L3@B, ... + + BC_L could end up pointing at location L2, while the "master" + location could be L1. Since the `loc->inserted' flag is only set + on "master" locations, we'd forget to restore the shadow of L1 + and L2. */ + while (bc_l > 0 + && bp_location[bc_l]->address == bp_location[bc_l - 1]->address) + bc_l--; + /* Now do full processing of the found relevant range of elements. */ for (bc = bc_l; bc < bp_location_count; bc++) { - struct bp_location *b = bp_location[bc]; + struct bp_location *bl = bp_location[bc]; CORE_ADDR bp_addr = 0; int bp_size = 0; int bptoffset = 0; - /* bp_location array has B->OWNER always non-NULL. */ - if (b->owner->type == bp_none) + /* bp_location array has BL->OWNER always non-NULL. */ + if (bl->owner->type == bp_none) warning (_("reading through apparently deleted breakpoint #%d?"), - b->owner->number); + bl->owner->number); /* Performance optimization: any futher element can no longer affect BUF content. */ - if (b->address >= bp_location_placed_address_before_address_max - && memaddr + len <= b->address - - bp_location_placed_address_before_address_max) + if (bl->address >= bp_location_placed_address_before_address_max + && memaddr + len <= (bl->address + - bp_location_placed_address_before_address_max)) break; - if (!bp_location_has_shadow (b)) + if (!bp_location_has_shadow (bl)) continue; - if (!breakpoint_address_match (b->target_info.placed_address_space, 0, + if (!breakpoint_address_match (bl->target_info.placed_address_space, 0, current_program_space->aspace, 0)) continue; /* Addresses and length of the part of the breakpoint that we need to copy. */ - bp_addr = b->target_info.placed_address; - bp_size = b->target_info.shadow_len; + bp_addr = bl->target_info.placed_address; + bp_size = bl->target_info.shadow_len; if (bp_addr + bp_size <= memaddr) /* The breakpoint is entirely before the chunk of memory we @@ -1178,7 +1101,7 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) if (bp_addr >= memaddr + len) /* The breakpoint is entirely after the chunk of memory we are - reading. */ + reading. */ continue; /* Offset within shadow_contents. */ @@ -1197,23 +1120,11 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) } memcpy (buf + bp_addr - memaddr, - b->target_info.shadow_contents + bptoffset, bp_size); + bl->target_info.shadow_contents + bptoffset, bp_size); } } -/* A wrapper function for inserting catchpoints. */ -static void -insert_catchpoint (struct ui_out *uo, void *args) -{ - struct breakpoint *b = (struct breakpoint *) args; - - gdb_assert (b->type == bp_catchpoint); - gdb_assert (b->ops != NULL && b->ops->insert != NULL); - - b->ops->insert (b); -} - /* Return true if BPT is of any hardware watchpoint kind. */ static int @@ -1252,6 +1163,25 @@ watchpoint_in_thread_scope (struct breakpoint *b) && !is_executing (inferior_ptid))); } +/* Set watchpoint B to disp_del_at_next_stop, even including its possible + associated bp_watchpoint_scope breakpoint. */ + +static void +watchpoint_del_at_next_stop (struct breakpoint *b) +{ + gdb_assert (is_watchpoint (b)); + + if (b->related_breakpoint != b) + { + gdb_assert (b->related_breakpoint->type == bp_watchpoint_scope); + gdb_assert (b->related_breakpoint->related_breakpoint == b); + b->related_breakpoint->disposition = disp_del_at_next_stop; + b->related_breakpoint->related_breakpoint = b->related_breakpoint; + b->related_breakpoint = b; + } + b->disposition = disp_del_at_next_stop; +} + /* Assuming that B is a watchpoint: - Reparse watchpoint expression, if REPARSE is non-zero - Evaluate expression and store the result in B->val @@ -1259,46 +1189,50 @@ watchpoint_in_thread_scope (struct breakpoint *b) in b->loc->cond. - Update the list of values that must be watched in B->loc. - If the watchpoint disposition is disp_del_at_next_stop, then do nothing. - If this is local watchpoint that is out of scope, delete it. - - Even with `set breakpoint always-inserted on' the watchpoints are removed - + inserted on each stop here. Normal breakpoints must never be removed - because they might be missed by a running thread when debugging in non-stop - mode. On the other hand, hardware watchpoints (is_hardware_watchpoint; - processed here) are specific to each LWP since they are stored in each LWP's - hardware debug registers. Therefore, such LWP must be stopped first in - order to be able to modify its hardware watchpoints. - - Hardware watchpoints must be reset exactly once after being presented to the - user. It cannot be done sooner, because it would reset the data used to - present the watchpoint hit to the user. And it must not be done later - because it could display the same single watchpoint hit during multiple GDB - stops. Note that the latter is relevant only to the hardware watchpoint - types bp_read_watchpoint and bp_access_watchpoint. False hit by - bp_hardware_watchpoint is not user-visible - its hit is suppressed if the - memory content has not changed. - - The following constraints influence the location where we can reset hardware - watchpoints: - - * target_stopped_by_watchpoint and target_stopped_data_address are called - several times when GDB stops. - - [linux] - * Multiple hardware watchpoints can be hit at the same time, causing GDB to - stop. GDB only presents one hardware watchpoint hit at a time as the - reason for stopping, and all the other hits are presented later, one after - the other, each time the user requests the execution to be resumed. - Execution is not resumed for the threads still having pending hit event - stored in LWP_INFO->STATUS. While the watchpoint is already removed from - the inferior on the first stop the thread hit event is kept being reported - from its cached value by linux_nat_stopped_data_address until the real - thread resume happens after the watchpoint gets presented and thus its - LWP_INFO->STATUS gets reset. - - Therefore the hardware watchpoint hit can get safely reset on the watchpoint - removal from inferior. */ + If the watchpoint disposition is disp_del_at_next_stop, then do + nothing. If this is local watchpoint that is out of scope, delete + it. + + Even with `set breakpoint always-inserted on' the watchpoints are + removed + inserted on each stop here. Normal breakpoints must + never be removed because they might be missed by a running thread + when debugging in non-stop mode. On the other hand, hardware + watchpoints (is_hardware_watchpoint; processed here) are specific + to each LWP since they are stored in each LWP's hardware debug + registers. Therefore, such LWP must be stopped first in order to + be able to modify its hardware watchpoints. + + Hardware watchpoints must be reset exactly once after being + presented to the user. It cannot be done sooner, because it would + reset the data used to present the watchpoint hit to the user. And + it must not be done later because it could display the same single + watchpoint hit during multiple GDB stops. Note that the latter is + relevant only to the hardware watchpoint types bp_read_watchpoint + and bp_access_watchpoint. False hit by bp_hardware_watchpoint is + not user-visible - its hit is suppressed if the memory content has + not changed. + + The following constraints influence the location where we can reset + hardware watchpoints: + + * target_stopped_by_watchpoint and target_stopped_data_address are + called several times when GDB stops. + + [linux] + * Multiple hardware watchpoints can be hit at the same time, + causing GDB to stop. GDB only presents one hardware watchpoint + hit at a time as the reason for stopping, and all the other hits + are presented later, one after the other, each time the user + requests the execution to be resumed. Execution is not resumed + for the threads still having pending hit event stored in + LWP_INFO->STATUS. While the watchpoint is already removed from + the inferior on the first stop the thread hit event is kept being + reported from its cached value by linux_nat_stopped_data_address + until the real thread resume happens after the watchpoint gets + presented and thus its LWP_INFO->STATUS gets reset. + + Therefore the hardware watchpoint hit can get safely reset on the + watchpoint removal from inferior. */ static void update_watchpoint (struct breakpoint *b, int reparse) @@ -1307,17 +1241,14 @@ update_watchpoint (struct breakpoint *b, int reparse) struct frame_id saved_frame_id; int frame_saved; + gdb_assert (is_watchpoint (b)); + /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread that was used to create the watchpoint. */ if (!watchpoint_in_thread_scope (b)) return; - /* We don't free locations. They are stored in bp_location array and - update_global_locations will eventually delete them and remove - breakpoints if needed. */ - b->loc = NULL; - if (b->disposition == disp_del_at_next_stop) return; @@ -1328,7 +1259,15 @@ update_watchpoint (struct breakpoint *b, int reparse) within_current_scope = 1; else { - struct frame_info *fi; + struct frame_info *fi = get_current_frame (); + struct gdbarch *frame_arch = get_frame_arch (fi); + CORE_ADDR frame_pc = get_frame_pc (fi); + + /* If we're in a function epilogue, unwinding may not work + properly, so do not attempt to recreate locations at this + point. See similar comments in watchpoint_check. */ + if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc)) + return; /* Save the current frame's ID so we can restore it after evaluating the watchpoint expression on its own frame. */ @@ -1344,15 +1283,21 @@ update_watchpoint (struct breakpoint *b, int reparse) select_frame (fi); } + /* We don't free locations. They are stored in the bp_location array + and update_global_location_list will eventually delete them and + remove breakpoints if needed. */ + b->loc = NULL; + if (within_current_scope && reparse) { char *s; + if (b->exp) { xfree (b->exp); b->exp = NULL; } - s = b->exp_string; + s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string; b->exp = parse_exp_1 (&s, b->exp_valid_block, 0); /* If the meaning of expression itself changed, the old value is no longer relevant. We don't want to report a watchpoint hit @@ -1407,42 +1352,10 @@ update_watchpoint (struct breakpoint *b, int reparse) b->val_valid = 1; } - /* Change the type of breakpoint between hardware assisted or an - ordinary watchpoint depending on the hardware support and free - hardware slots. REPARSE is set when the inferior is started. */ - if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint) - && reparse) - { - int i, mem_cnt, other_type_used; - - /* We need to determine how many resources are already used - for all other hardware watchpoints to see if we still have - enough resources to also fit this watchpoint in as well. - To avoid the hw_watchpoint_used_count call below from counting - this watchpoint, make sure that it is marked as a software - watchpoint. */ - b->type = bp_watchpoint; - i = hw_watchpoint_used_count (bp_hardware_watchpoint, - &other_type_used); - mem_cnt = can_use_hardware_watchpoint (val_chain); - - if (!mem_cnt) - b->type = bp_watchpoint; - else - { - int target_resources_ok = target_can_use_hardware_watchpoint - (bp_hardware_watchpoint, i + mem_cnt, other_type_used); - if (target_resources_ok <= 0) - b->type = bp_watchpoint; - else - b->type = bp_hardware_watchpoint; - } - } - frame_pspace = get_frame_program_space (get_selected_frame (NULL)); /* Look at each value on the value chain. */ - for (v = val_chain; v; v = next) + for (v = val_chain; v; v = value_next (v)) { /* If it's a memory location, and GDB actually needed its contents to evaluate the expression, then we @@ -1485,7 +1398,62 @@ update_watchpoint (struct breakpoint *b, int reparse) loc->watchpoint_type = type; } } + } + + /* Change the type of breakpoint between hardware assisted or + an ordinary watchpoint depending on the hardware support + and free hardware slots. REPARSE is set when the inferior + is started. */ + if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint) + && reparse) + { + int reg_cnt; + enum bp_loc_type loc_type; + struct bp_location *bl; + + reg_cnt = can_use_hardware_watchpoint (val_chain, b->exact); + + if (reg_cnt) + { + int i, target_resources_ok, other_type_used; + enum enable_state orig_enable_state; + + /* We need to determine how many resources are already + used for all other hardware watchpoints plus this one + to see if we still have enough resources to also fit + this watchpoint in as well. To guarantee the + hw_watchpoint_used_count call below counts this + watchpoint, make sure that it is marked as a hardware + watchpoint. */ + b->type = bp_hardware_watchpoint; + + /* hw_watchpoint_used_count ignores disabled watchpoints, + and b might be disabled if we're being called from + do_enable_breakpoint. */ + orig_enable_state = b->enable_state; + b->enable_state = bp_enabled; + + i = hw_watchpoint_used_count (bp_hardware_watchpoint, + &other_type_used); + + b->enable_state = orig_enable_state; + + target_resources_ok = target_can_use_hardware_watchpoint + (bp_hardware_watchpoint, i, other_type_used); + if (target_resources_ok <= 0) + b->type = bp_watchpoint; + } + else + b->type = bp_watchpoint; + + loc_type = (b->type == bp_watchpoint? bp_loc_other + : bp_loc_hardware_watchpoint); + for (bl = b->loc; bl; bl = bl->next) + bl->loc_type = loc_type; + } + for (v = val_chain; v; v = next) + { next = value_next (v); if (v != b->val) value_free (v); @@ -1510,13 +1478,7 @@ update_watchpoint (struct breakpoint *b, int reparse) Watchpoint %d deleted because the program has left the block\n\ in which its expression is valid.\n"), b->number); - if (b->related_breakpoint) - { - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->related_breakpoint->related_breakpoint = NULL; - b->related_breakpoint= NULL; - } - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); } /* Restore the selected frame. */ @@ -1528,15 +1490,15 @@ in which its expression is valid.\n"), /* Returns 1 iff breakpoint location should be inserted in the inferior. */ static int -should_be_inserted (struct bp_location *bpt) +should_be_inserted (struct bp_location *bl) { - if (bpt->owner == NULL || !breakpoint_enabled (bpt->owner)) + if (bl->owner == NULL || !breakpoint_enabled (bl->owner)) return 0; - if (bpt->owner->disposition == disp_del_at_next_stop) + if (bl->owner->disposition == disp_del_at_next_stop) return 0; - if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate) + if (!bl->enabled || bl->shlib_disabled || bl->duplicate) return 0; /* This is set for example, when we're attached to the parent of a @@ -1547,61 +1509,65 @@ should_be_inserted (struct bp_location *bpt) memory region, do not insert breakpoints in the parent, otherwise the child could still trip on the parent's breakpoints. Since the parent is blocked anyway, it won't miss any breakpoint. */ - if (bpt->pspace->breakpoints_not_allowed) + if (bl->pspace->breakpoints_not_allowed) return 0; /* Tracepoints are inserted by the target at a time of its choosing, not by us. */ - if (is_tracepoint (bpt->owner)) + if (is_tracepoint (bl->owner)) return 0; return 1; } -/* Insert a low-level "breakpoint" of some type. BPT is the breakpoint. - Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS, - and HW_BREAKPOINT_ERROR are used to report problems. +/* Insert a low-level "breakpoint" of some type. BL is the breakpoint + location. Any error messages are printed to TMP_ERROR_STREAM; and + DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems. - NOTE drow/2003-09-09: This routine could be broken down to an object-style - method for each breakpoint or catchpoint type. */ + NOTE drow/2003-09-09: This routine could be broken down to an + object-style method for each breakpoint or catchpoint type. */ static int -insert_bp_location (struct bp_location *bpt, +insert_bp_location (struct bp_location *bl, struct ui_file *tmp_error_stream, int *disabled_breaks, int *hw_breakpoint_error) { int val = 0; - if (!should_be_inserted (bpt) || bpt->inserted) + if (!should_be_inserted (bl) || bl->inserted) return 0; /* Initialize the target-specific information. */ - memset (&bpt->target_info, 0, sizeof (bpt->target_info)); - bpt->target_info.placed_address = bpt->address; - bpt->target_info.placed_address_space = bpt->pspace->aspace; + memset (&bl->target_info, 0, sizeof (bl->target_info)); + bl->target_info.placed_address = bl->address; + bl->target_info.placed_address_space = bl->pspace->aspace; + bl->target_info.length = bl->length; - if (bpt->loc_type == bp_loc_software_breakpoint - || bpt->loc_type == bp_loc_hardware_breakpoint) + if (bl->loc_type == bp_loc_software_breakpoint + || bl->loc_type == bp_loc_hardware_breakpoint) { - if (bpt->owner->type != bp_hardware_breakpoint) + if (bl->owner->type != bp_hardware_breakpoint) { /* If the explicitly specified breakpoint type is not hardware breakpoint, check the memory map to see if the breakpoint address is in read only memory or not. + Two important cases are: - location type is not hardware breakpoint, memory is readonly. We change the type of the location to hardware breakpoint. - - location type is hardware breakpoint, memory is read-write. - This means we've previously made the location hardware one, but - then the memory map changed, so we undo. + - location type is hardware breakpoint, memory is + read-write. This means we've previously made the + location hardware one, but then the memory map changed, + so we undo. - When breakpoints are removed, remove_breakpoints will - use location types we've just set here, the only possible - problem is that memory map has changed during running program, - but it's not going to work anyway with current gdb. */ + When breakpoints are removed, remove_breakpoints will use + location types we've just set here, the only possible + problem is that memory map has changed during running + program, but it's not going to work anyway with current + gdb. */ struct mem_region *mr - = lookup_mem_region (bpt->target_info.placed_address); + = lookup_mem_region (bl->target_info.placed_address); if (mr) { @@ -1614,77 +1580,81 @@ insert_bp_location (struct bp_location *bpt, else new_type = bp_loc_software_breakpoint; - if (new_type != bpt->loc_type) + if (new_type != bl->loc_type) { static int said = 0; - bpt->loc_type = new_type; + bl->loc_type = new_type; if (!said) { - fprintf_filtered (gdb_stdout, _("\ -Note: automatically using hardware breakpoints for read-only addresses.\n")); + fprintf_filtered (gdb_stdout, + _("Note: automatically using " + "hardware breakpoints for " + "read-only addresses.\n")); said = 1; } } } - else if (bpt->loc_type == bp_loc_software_breakpoint + else if (bl->loc_type == bp_loc_software_breakpoint && mr->attrib.mode != MEM_RW) - warning (_("cannot set software breakpoint at readonly address %s"), - paddress (bpt->gdbarch, bpt->address)); + warning (_("cannot set software breakpoint " + "at readonly address %s"), + paddress (bl->gdbarch, bl->address)); } } /* First check to see if we have to handle an overlay. */ if (overlay_debugging == ovly_off - || bpt->section == NULL - || !(section_is_overlay (bpt->section))) + || bl->section == NULL + || !(section_is_overlay (bl->section))) { /* No overlay handling: just set the breakpoint. */ - if (bpt->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bpt->gdbarch, - &bpt->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint) + val = target_insert_hw_breakpoint (bl->gdbarch, + &bl->target_info); else - val = target_insert_breakpoint (bpt->gdbarch, - &bpt->target_info); + val = target_insert_breakpoint (bl->gdbarch, + &bl->target_info); } else { - /* This breakpoint is in an overlay section. + /* This breakpoint is in an overlay section. Shall we set a breakpoint at the LMA? */ if (!overlay_events_enabled) { /* Yes -- overlay event support is not active, so we must try to set a breakpoint at the LMA. This will not work for a hardware breakpoint. */ - if (bpt->loc_type == bp_loc_hardware_breakpoint) + if (bl->loc_type == bp_loc_hardware_breakpoint) warning (_("hardware breakpoint %d not supported in overlay!"), - bpt->owner->number); + bl->owner->number); else { - CORE_ADDR addr = overlay_unmapped_address (bpt->address, - bpt->section); + CORE_ADDR addr = overlay_unmapped_address (bl->address, + bl->section); /* Set a software (trap) breakpoint at the LMA. */ - bpt->overlay_target_info = bpt->target_info; - bpt->overlay_target_info.placed_address = addr; - val = target_insert_breakpoint (bpt->gdbarch, - &bpt->overlay_target_info); + bl->overlay_target_info = bl->target_info; + bl->overlay_target_info.placed_address = addr; + val = target_insert_breakpoint (bl->gdbarch, + &bl->overlay_target_info); if (val != 0) fprintf_unfiltered (tmp_error_stream, - "Overlay breakpoint %d failed: in ROM?\n", - bpt->owner->number); + "Overlay breakpoint %d " + "failed: in ROM?\n", + bl->owner->number); } } /* Shall we set a breakpoint at the VMA? */ - if (section_is_mapped (bpt->section)) + if (section_is_mapped (bl->section)) { /* Yes. This overlay section is mapped into memory. */ - if (bpt->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bpt->gdbarch, - &bpt->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint) + val = target_insert_hw_breakpoint (bl->gdbarch, + &bl->target_info); else - val = target_insert_breakpoint (bpt->gdbarch, - &bpt->target_info); + val = target_insert_breakpoint (bl->gdbarch, + &bl->target_info); } else { @@ -1697,40 +1667,42 @@ Note: automatically using hardware breakpoints for read-only addresses.\n")); if (val) { /* Can't set the breakpoint. */ - if (solib_name_from_address (bpt->pspace, bpt->address)) + if (solib_name_from_address (bl->pspace, bl->address)) { - /* See also: disable_breakpoints_in_shlibs. */ + /* See also: disable_breakpoints_in_shlibs. */ val = 0; - bpt->shlib_disabled = 1; + bl->shlib_disabled = 1; if (!*disabled_breaks) { fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", - bpt->owner->number); + bl->owner->number); fprintf_unfiltered (tmp_error_stream, - "Temporarily disabling shared library breakpoints:\n"); + "Temporarily disabling shared " + "library breakpoints:\n"); } *disabled_breaks = 1; fprintf_unfiltered (tmp_error_stream, - "breakpoint #%d\n", bpt->owner->number); + "breakpoint #%d\n", bl->owner->number); } else { - if (bpt->loc_type == bp_loc_hardware_breakpoint) + if (bl->loc_type == bp_loc_hardware_breakpoint) { *hw_breakpoint_error = 1; - fprintf_unfiltered (tmp_error_stream, - "Cannot insert hardware breakpoint %d.\n", - bpt->owner->number); + fprintf_unfiltered (tmp_error_stream, + "Cannot insert hardware " + "breakpoint %d.\n", + bl->owner->number); } else { fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", - bpt->owner->number); + bl->owner->number); fprintf_filtered (tmp_error_stream, "Error accessing memory address "); - fputs_filtered (paddress (bpt->gdbarch, bpt->address), + fputs_filtered (paddress (bl->gdbarch, bl->address), tmp_error_stream); fprintf_filtered (tmp_error_stream, ": %s.\n", safe_strerror (val)); @@ -1739,24 +1711,24 @@ Note: automatically using hardware breakpoints for read-only addresses.\n")); } } else - bpt->inserted = 1; + bl->inserted = 1; return val; } - else if (bpt->loc_type == bp_loc_hardware_watchpoint + else if (bl->loc_type == bp_loc_hardware_watchpoint /* NOTE drow/2003-09-08: This state only exists for removing - watchpoints. It's not clear that it's necessary... */ - && bpt->owner->disposition != disp_del_at_next_stop) + watchpoints. It's not clear that it's necessary... */ + && bl->owner->disposition != disp_del_at_next_stop) { - val = target_insert_watchpoint (bpt->address, - bpt->length, - bpt->watchpoint_type, - bpt->owner->cond_exp); + gdb_assert (bl->owner->ops != NULL + && bl->owner->ops->insert_location != NULL); + + val = bl->owner->ops->insert_location (bl); /* If trying to set a read-watchpoint, and it turns out it's not supported, try emulating one with an access watchpoint. */ - if (val == 1 && bpt->watchpoint_type == hw_read) + if (val == 1 && bl->watchpoint_type == hw_read) { struct bp_location *loc, **loc_temp; @@ -1764,42 +1736,51 @@ Note: automatically using hardware breakpoints for read-only addresses.\n")); hw_access location that would be considered a duplicate of this one. */ ALL_BP_LOCATIONS (loc, loc_temp) - if (loc != bpt + if (loc != bl && loc->watchpoint_type == hw_access - && watchpoint_locations_match (bpt, loc)) + && watchpoint_locations_match (bl, loc)) { - bpt->duplicate = 1; - bpt->inserted = 1; - bpt->target_info = loc->target_info; - bpt->watchpoint_type = hw_access; + bl->duplicate = 1; + bl->inserted = 1; + bl->target_info = loc->target_info; + bl->watchpoint_type = hw_access; val = 0; break; } if (val == 1) { - val = target_insert_watchpoint (bpt->address, - bpt->length, - hw_access, - bpt->owner->cond_exp); - if (val == 0) - bpt->watchpoint_type = hw_access; + bl->watchpoint_type = hw_access; + val = bl->owner->ops->insert_location (bl); + + if (val) + /* Back to the original value. */ + bl->watchpoint_type = hw_read; } } - bpt->inserted = (val == 0); + bl->inserted = (val == 0); } - else if (bpt->owner->type == bp_catchpoint) + else if (bl->owner->type == bp_catchpoint) { - struct gdb_exception e = catch_exception (uiout, insert_catchpoint, - bpt->owner, RETURN_MASK_ERROR); - exception_fprintf (gdb_stderr, e, "warning: inserting catchpoint %d: ", - bpt->owner->number); - if (e.reason < 0) - bpt->owner->enable_state = bp_disabled; - else - bpt->inserted = 1; + gdb_assert (bl->owner->ops != NULL + && bl->owner->ops->insert_location != NULL); + + val = bl->owner->ops->insert_location (bl); + if (val) + { + bl->owner->enable_state = bp_disabled; + + if (val == 1) + warning (_("\ +Error inserting catchpoint %d: Your system does not support this type\n\ +of catchpoint."), bl->owner->number); + else + warning (_("Error inserting catchpoint %d."), bl->owner->number); + } + + bl->inserted = (val == 0); /* We've already printed an error message if there was a problem inserting this catchpoint, and we've disabled the catchpoint, @@ -1864,7 +1845,7 @@ insert_breakpoints (void) ALL_BREAKPOINTS (bpt) if (is_hardware_watchpoint (bpt)) - update_watchpoint (bpt, 0 /* don't reparse. */); + update_watchpoint (bpt, 0 /* don't reparse. */); update_global_location_list (1); @@ -1884,7 +1865,7 @@ static void insert_breakpoint_locations (void) { struct breakpoint *bpt; - struct bp_location *b, **bp_tmp; + struct bp_location *bl, **blp_tmp; int error = 0; int val = 0; int disabled_breaks = 0; @@ -1899,19 +1880,19 @@ insert_breakpoint_locations (void) save_current_space_and_thread (); - ALL_BP_LOCATIONS (b, bp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (!should_be_inserted (b) || b->inserted) + if (!should_be_inserted (bl) || bl->inserted) continue; - /* There is no point inserting thread-specific breakpoints if the - thread no longer exists. ALL_BP_LOCATIONS bp_location has B->OWNER - always non-NULL. */ - if (b->owner->thread != -1 - && !valid_thread_id (b->owner->thread)) + /* There is no point inserting thread-specific breakpoints if + the thread no longer exists. ALL_BP_LOCATIONS bp_location + has BL->OWNER always non-NULL. */ + if (bl->owner->thread != -1 + && !valid_thread_id (bl->owner->thread)) continue; - switch_to_program_space_and_thread (b->pspace); + switch_to_program_space_and_thread (bl->pspace); /* For targets that support global breakpoints, there's no need to select an inferior to insert breakpoint to. In fact, even @@ -1921,15 +1902,14 @@ insert_breakpoint_locations (void) && ptid_equal (inferior_ptid, null_ptid)) continue; - val = insert_bp_location (b, tmp_error_stream, - &disabled_breaks, + val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks, &hw_breakpoint_error); if (val) error = val; } - /* If we failed to insert all locations of a watchpoint, - remove them, as half-inserted watchpoint is of limited use. */ + /* If we failed to insert all locations of a watchpoint, remove + them, as half-inserted watchpoint is of limited use. */ ALL_BREAKPOINTS (bpt) { int some_failed = 0; @@ -1984,13 +1964,13 @@ You may have requested too many hardware breakpoints/watchpoints.\n"); int remove_breakpoints (void) { - struct bp_location *b, **bp_tmp; + struct bp_location *bl, **blp_tmp; int val = 0; - ALL_BP_LOCATIONS (b, bp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (b->inserted) - val |= remove_breakpoint (b, mark_uninserted); + if (bl->inserted) + val |= remove_breakpoint (bl, mark_uninserted); } return val; } @@ -2000,18 +1980,18 @@ remove_breakpoints (void) int remove_breakpoints_pid (int pid) { - struct bp_location *b, **b_tmp; + struct bp_location *bl, **blp_tmp; int val; struct inferior *inf = find_inferior_pid (pid); - ALL_BP_LOCATIONS (b, b_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (b->pspace != inf->pspace) + if (bl->pspace != inf->pspace) continue; - if (b->inserted) + if (bl->inserted) { - val = remove_breakpoint (b, mark_uninserted); + val = remove_breakpoint (bl, mark_uninserted); if (val != 0) return val; } @@ -2022,13 +2002,13 @@ remove_breakpoints_pid (int pid) int remove_hw_watchpoints (void) { - struct bp_location *b, **bp_tmp; + struct bp_location *bl, **blp_tmp; int val = 0; - ALL_BP_LOCATIONS (b, bp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (b->inserted && b->loc_type == bp_loc_hardware_watchpoint) - val |= remove_breakpoint (b, mark_uninserted); + if (bl->inserted && bl->loc_type == bp_loc_hardware_watchpoint) + val |= remove_breakpoint (bl, mark_uninserted); } return val; } @@ -2037,9 +2017,9 @@ int reattach_breakpoints (int pid) { struct cleanup *old_chain; - struct bp_location *b, **bp_tmp; + struct bp_location *bl, **blp_tmp; int val; - struct ui_file *tmp_error_stream = mem_fileopen (); + struct ui_file *tmp_error_stream; int dummy1 = 0, dummy2 = 0; struct inferior *inf; struct thread_info *tp; @@ -2053,18 +2033,18 @@ reattach_breakpoints (int pid) inferior_ptid = tp->ptid; + tmp_error_stream = mem_fileopen (); make_cleanup_ui_file_delete (tmp_error_stream); - ALL_BP_LOCATIONS (b, bp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (b->pspace != inf->pspace) + if (bl->pspace != inf->pspace) continue; - if (b->inserted) + if (bl->inserted) { - b->inserted = 0; - val = insert_bp_location (b, tmp_error_stream, - &dummy1, &dummy2); + bl->inserted = 0; + val = insert_bp_location (bl, tmp_error_stream, &dummy1, &dummy2); if (val != 0) { do_cleanups (old_chain); @@ -2078,6 +2058,24 @@ reattach_breakpoints (int pid) static int internal_breakpoint_number = -1; +/* Set the breakpoint number of B, depending on the value of INTERNAL. + If INTERNAL is non-zero, the breakpoint number will be populated + from internal_breakpoint_number and that variable decremented. + Otherwis the breakpoint number will be populated from + breakpoint_count and that value incremented. Internal breakpoints + do not set the internal var bpnum. */ +static void +set_breakpoint_number (int internal, struct breakpoint *b) +{ + if (internal) + b->number = internal_breakpoint_number--; + else + { + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + } +} + static struct breakpoint * create_internal_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address, enum bptype type) @@ -2085,7 +2083,7 @@ create_internal_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal; struct breakpoint *b; - init_sal (&sal); /* initialize to zeroes */ + init_sal (&sal); /* Initialize to zeroes. */ sal.pc = address; sal.section = find_pc_overlay (sal.pc); @@ -2098,22 +2096,94 @@ create_internal_breakpoint (struct gdbarch *gdbarch, return b; } +static const char *const longjmp_names[] = + { + "longjmp", "_longjmp", "siglongjmp", "_siglongjmp" + }; +#define NUM_LONGJMP_NAMES ARRAY_SIZE(longjmp_names) + +/* Per-objfile data private to breakpoint.c. */ +struct breakpoint_objfile_data +{ + /* Minimal symbol for "_ovly_debug_event" (if any). */ + struct minimal_symbol *overlay_msym; + + /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */ + struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES]; + + /* Minimal symbol for "std::terminate()" (if any). */ + struct minimal_symbol *terminate_msym; + + /* Minimal symbol for "_Unwind_DebugHook" (if any). */ + struct minimal_symbol *exception_msym; +}; + +static const struct objfile_data *breakpoint_objfile_key; + +/* Minimal symbol not found sentinel. */ +static struct minimal_symbol msym_not_found; + +/* Returns TRUE if MSYM point to the "not found" sentinel. */ + +static int +msym_not_found_p (const struct minimal_symbol *msym) +{ + return msym == &msym_not_found; +} + +/* Return per-objfile data needed by breakpoint.c. + Allocate the data if necessary. */ + +static struct breakpoint_objfile_data * +get_breakpoint_objfile_data (struct objfile *objfile) +{ + struct breakpoint_objfile_data *bp_objfile_data; + + bp_objfile_data = objfile_data (objfile, breakpoint_objfile_key); + if (bp_objfile_data == NULL) + { + bp_objfile_data = obstack_alloc (&objfile->objfile_obstack, + sizeof (*bp_objfile_data)); + + memset (bp_objfile_data, 0, sizeof (*bp_objfile_data)); + set_objfile_data (objfile, breakpoint_objfile_key, bp_objfile_data); + } + return bp_objfile_data; +} + static void -create_overlay_event_breakpoint (char *func_name) +create_overlay_event_breakpoint (void) { struct objfile *objfile; + const char *const func_name = "_ovly_debug_event"; ALL_OBJFILES (objfile) { struct breakpoint *b; - struct minimal_symbol *m; + struct breakpoint_objfile_data *bp_objfile_data; + CORE_ADDR addr; - m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) - continue; + bp_objfile_data = get_breakpoint_objfile_data (objfile); + + if (msym_not_found_p (bp_objfile_data->overlay_msym)) + continue; + + if (bp_objfile_data->overlay_msym == NULL) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol_text (func_name, objfile); + if (m == NULL) + { + /* Avoid future lookups in this objfile. */ + bp_objfile_data->overlay_msym = &msym_not_found; + continue; + } + bp_objfile_data->overlay_msym = m; + } - b = create_internal_breakpoint (get_objfile_arch (objfile), - SYMBOL_VALUE_ADDRESS (m), + addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym); + b = create_internal_breakpoint (get_objfile_arch (objfile), addr, bp_overlay_event); b->addr_string = xstrdup (func_name); @@ -2132,80 +2202,173 @@ create_overlay_event_breakpoint (char *func_name) } static void -create_longjmp_master_breakpoint (char *func_name) +create_longjmp_master_breakpoint (void) { struct program_space *pspace; - struct objfile *objfile; struct cleanup *old_chain; old_chain = save_current_program_space (); ALL_PSPACES (pspace) - ALL_OBJFILES (objfile) + { + struct objfile *objfile; + + set_current_program_space (pspace); + + ALL_OBJFILES (objfile) { - struct breakpoint *b; - struct minimal_symbol *m; + int i; + struct gdbarch *gdbarch; + struct breakpoint_objfile_data *bp_objfile_data; - if (!gdbarch_get_longjmp_target_p (get_objfile_arch (objfile))) + gdbarch = get_objfile_arch (objfile); + if (!gdbarch_get_longjmp_target_p (gdbarch)) continue; - set_current_program_space (pspace); + bp_objfile_data = get_breakpoint_objfile_data (objfile); - m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) - continue; + for (i = 0; i < NUM_LONGJMP_NAMES; i++) + { + struct breakpoint *b; + const char *func_name; + CORE_ADDR addr; - b = create_internal_breakpoint (get_objfile_arch (objfile), - SYMBOL_VALUE_ADDRESS (m), - bp_longjmp_master); - b->addr_string = xstrdup (func_name); - b->enable_state = bp_disabled; + if (msym_not_found_p (bp_objfile_data->longjmp_msym[i])) + continue; + + func_name = longjmp_names[i]; + if (bp_objfile_data->longjmp_msym[i] == NULL) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol_text (func_name, objfile); + if (m == NULL) + { + /* Prevent future lookups in this objfile. */ + bp_objfile_data->longjmp_msym[i] = &msym_not_found; + continue; + } + bp_objfile_data->longjmp_msym[i] = m; + } + + addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]); + b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master); + b->addr_string = xstrdup (func_name); + b->enable_state = bp_disabled; + } } + } update_global_location_list (1); do_cleanups (old_chain); } -/* Create a master std::terminate breakpoint. The actual function - looked for is named FUNC_NAME. */ +/* Create a master std::terminate breakpoint. */ static void -create_std_terminate_master_breakpoint (const char *func_name) +create_std_terminate_master_breakpoint (void) { struct program_space *pspace; - struct objfile *objfile; struct cleanup *old_chain; + const char *const func_name = "std::terminate()"; old_chain = save_current_program_space (); ALL_PSPACES (pspace) + { + struct objfile *objfile; + CORE_ADDR addr; + + set_current_program_space (pspace); + ALL_OBJFILES (objfile) { struct breakpoint *b; - struct minimal_symbol *m; + struct breakpoint_objfile_data *bp_objfile_data; - set_current_program_space (pspace); + bp_objfile_data = get_breakpoint_objfile_data (objfile); - m = lookup_minimal_symbol (func_name, NULL, objfile); - if (m == NULL || (MSYMBOL_TYPE (m) != mst_text - && MSYMBOL_TYPE (m) != mst_file_text)) - continue; + if (msym_not_found_p (bp_objfile_data->terminate_msym)) + continue; + + if (bp_objfile_data->terminate_msym == NULL) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol (func_name, NULL, objfile); + if (m == NULL || (MSYMBOL_TYPE (m) != mst_text + && MSYMBOL_TYPE (m) != mst_file_text)) + { + /* Prevent future lookups in this objfile. */ + bp_objfile_data->terminate_msym = &msym_not_found; + continue; + } + bp_objfile_data->terminate_msym = m; + } - b = create_internal_breakpoint (get_objfile_arch (objfile), - SYMBOL_VALUE_ADDRESS (m), + addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym); + b = create_internal_breakpoint (get_objfile_arch (objfile), addr, bp_std_terminate_master); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; } + } + update_global_location_list (1); do_cleanups (old_chain); } +/* Install a master breakpoint on the unwinder's debug hook. */ + +void +create_exception_master_breakpoint (void) +{ + struct objfile *objfile; + const char *const func_name = "_Unwind_DebugHook"; + + ALL_OBJFILES (objfile) + { + struct breakpoint *b; + struct gdbarch *gdbarch; + struct breakpoint_objfile_data *bp_objfile_data; + CORE_ADDR addr; + + bp_objfile_data = get_breakpoint_objfile_data (objfile); + + if (msym_not_found_p (bp_objfile_data->exception_msym)) + continue; + + gdbarch = get_objfile_arch (objfile); + + if (bp_objfile_data->exception_msym == NULL) + { + struct minimal_symbol *debug_hook; + + debug_hook = lookup_minimal_symbol (func_name, NULL, objfile); + if (debug_hook == NULL) + { + bp_objfile_data->exception_msym = &msym_not_found; + continue; + } + + bp_objfile_data->exception_msym = debug_hook; + } + + addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym); + addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, + ¤t_target); + b = create_internal_breakpoint (gdbarch, addr, bp_exception_master); + b->addr_string = xstrdup (func_name); + b->enable_state = bp_disabled; + } + + update_global_location_list (1); +} + void update_breakpoints_after_exec (void) { - struct breakpoint *b; - struct breakpoint *temp; + struct breakpoint *b, *b_tmp; struct bp_location *bploc, **bplocp_tmp; /* We're about to delete breakpoints from GDB's lists. If the @@ -2220,19 +2383,19 @@ update_breakpoints_after_exec (void) if (bploc->pspace == current_program_space) gdb_assert (!bploc->inserted); - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { if (b->pspace != current_program_space) continue; - /* Solib breakpoints must be explicitly reset after an exec(). */ + /* Solib breakpoints must be explicitly reset after an exec(). */ if (b->type == bp_shlib_event) { delete_breakpoint (b); continue; } - /* JIT breakpoints must be explicitly reset after an exec(). */ + /* JIT breakpoints must be explicitly reset after an exec(). */ if (b->type == bp_jit_event) { delete_breakpoint (b); @@ -2242,13 +2405,14 @@ update_breakpoints_after_exec (void) /* Thread event breakpoints must be set anew after an exec(), as must overlay event and longjmp master breakpoints. */ if (b->type == bp_thread_event || b->type == bp_overlay_event - || b->type == bp_longjmp_master || b->type == bp_std_terminate_master) + || b->type == bp_longjmp_master || b->type == bp_std_terminate_master + || b->type == bp_exception_master) { delete_breakpoint (b); continue; } - /* Step-resume breakpoints are meaningless after an exec(). */ + /* Step-resume breakpoints are meaningless after an exec(). */ if (b->type == bp_step_resume) { delete_breakpoint (b); @@ -2257,7 +2421,8 @@ update_breakpoints_after_exec (void) /* Longjmp and longjmp-resume breakpoints are also meaningless after an exec. */ - if (b->type == bp_longjmp || b->type == bp_longjmp_resume) + if (b->type == bp_longjmp || b->type == bp_longjmp_resume + || b->type == bp_exception || b->type == bp_exception_resume) { delete_breakpoint (b); continue; @@ -2305,7 +2470,7 @@ update_breakpoints_after_exec (void) /* Without a symbolic address, we have little hope of the pre-exec() address meaning the same thing in the post-exec() - a.out. */ + a.out. */ if (b->addr_string == NULL) { delete_breakpoint (b); @@ -2313,18 +2478,16 @@ update_breakpoints_after_exec (void) } } /* FIXME what about longjmp breakpoints? Re-create them here? */ - create_overlay_event_breakpoint ("_ovly_debug_event"); - create_longjmp_master_breakpoint ("longjmp"); - create_longjmp_master_breakpoint ("_longjmp"); - create_longjmp_master_breakpoint ("siglongjmp"); - create_longjmp_master_breakpoint ("_siglongjmp"); - create_std_terminate_master_breakpoint ("std::terminate()"); + create_overlay_event_breakpoint (); + create_longjmp_master_breakpoint (); + create_std_terminate_master_breakpoint (); + create_exception_master_breakpoint (); } int detach_breakpoints (int pid) { - struct bp_location *b, **bp_tmp; + struct bp_location *bl, **blp_tmp; int val = 0; struct cleanup *old_chain = save_inferior_ptid (); struct inferior *inf = current_inferior (); @@ -2334,13 +2497,13 @@ detach_breakpoints (int pid) /* Set inferior_ptid; remove_breakpoint_1 uses this global. */ inferior_ptid = pid_to_ptid (pid); - ALL_BP_LOCATIONS (b, bp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (b->pspace != inf->pspace) + if (bl->pspace != inf->pspace) continue; - if (b->inserted) - val |= remove_breakpoint_1 (b, mark_inserted); + if (bl->inserted) + val |= remove_breakpoint_1 (bl, mark_inserted); } /* Detach single-step breakpoints as well. */ @@ -2350,30 +2513,30 @@ detach_breakpoints (int pid) return val; } -/* Remove the breakpoint location B from the current address space. +/* Remove the breakpoint location BL from the current address space. Note that this is used to detach breakpoints from a child fork. When we get here, the child isn't in the inferior list, and neither do we have objects to represent its address space --- we should - *not* look at b->pspace->aspace here. */ + *not* look at bl->pspace->aspace here. */ static int -remove_breakpoint_1 (struct bp_location *b, insertion_state_t is) +remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) { int val; - /* B is never in moribund_locations by our callers. */ - gdb_assert (b->owner != NULL); + /* BL is never in moribund_locations by our callers. */ + gdb_assert (bl->owner != NULL); - if (b->owner->enable_state == bp_permanent) + if (bl->owner->enable_state == bp_permanent) /* Permanent breakpoints cannot be inserted or removed. */ return 0; /* The type of none suggests that owner is actually deleted. This should not ever happen. */ - gdb_assert (b->owner->type != bp_none); + gdb_assert (bl->owner->type != bp_none); - if (b->loc_type == bp_loc_software_breakpoint - || b->loc_type == bp_loc_hardware_breakpoint) + if (bl->loc_type == bp_loc_software_breakpoint + || bl->loc_type == bp_loc_hardware_breakpoint) { /* "Normal" instruction breakpoint: either the standard trap-instruction bp (bp_breakpoint), or a @@ -2381,19 +2544,19 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is) /* First check to see if we have to handle an overlay. */ if (overlay_debugging == ovly_off - || b->section == NULL - || !(section_is_overlay (b->section))) + || bl->section == NULL + || !(section_is_overlay (bl->section))) { /* No overlay handling: just remove the breakpoint. */ - if (b->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (b->gdbarch, &b->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint) + val = target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); else - val = target_remove_breakpoint (b->gdbarch, &b->target_info); + val = target_remove_breakpoint (bl->gdbarch, &bl->target_info); } else { - /* This breakpoint is in an overlay section. + /* This breakpoint is in an overlay section. Did we set a breakpoint at the LMA? */ if (!overlay_events_enabled) { @@ -2402,31 +2565,31 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is) */ /* Ignore any failures: if the LMA is in ROM, we will have already warned when we failed to insert it. */ - if (b->loc_type == bp_loc_hardware_breakpoint) - target_remove_hw_breakpoint (b->gdbarch, - &b->overlay_target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint) + target_remove_hw_breakpoint (bl->gdbarch, + &bl->overlay_target_info); else - target_remove_breakpoint (b->gdbarch, - &b->overlay_target_info); + target_remove_breakpoint (bl->gdbarch, + &bl->overlay_target_info); } /* Did we set a breakpoint at the VMA? If so, we will have marked the breakpoint 'inserted'. */ - if (b->inserted) + if (bl->inserted) { /* Yes -- remove it. Previously we did not bother to remove the breakpoint if the section had been unmapped, but let's not rely on that being safe. We don't know what the overlay manager might do. */ - if (b->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (b->gdbarch, - &b->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint) + val = target_remove_hw_breakpoint (bl->gdbarch, + &bl->target_info); /* However, we should remove *software* breakpoints only if the section is still mapped, or else we overwrite wrong code with the saved shadow contents. */ - else if (section_is_mapped (b->section)) - val = target_remove_breakpoint (b->gdbarch, - &b->target_info); + else if (section_is_mapped (bl->section)) + val = target_remove_breakpoint (bl->gdbarch, + &bl->target_info); else val = 0; } @@ -2440,61 +2603,65 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is) /* In some cases, we might not be able to remove a breakpoint in a shared library that has already been removed, but we have not yet processed the shlib unload event. */ - if (val && solib_name_from_address (b->pspace, b->address)) + if (val && solib_name_from_address (bl->pspace, bl->address)) val = 0; if (val) return val; - b->inserted = (is == mark_inserted); + bl->inserted = (is == mark_inserted); } - else if (b->loc_type == bp_loc_hardware_watchpoint) + else if (bl->loc_type == bp_loc_hardware_watchpoint) { - b->inserted = (is == mark_inserted); - val = target_remove_watchpoint (b->address, b->length, - b->watchpoint_type, b->owner->cond_exp); + gdb_assert (bl->owner->ops != NULL + && bl->owner->ops->remove_location != NULL); + + bl->inserted = (is == mark_inserted); + bl->owner->ops->remove_location (bl); /* Failure to remove any of the hardware watchpoints comes here. */ - if ((is == mark_uninserted) && (b->inserted)) + if ((is == mark_uninserted) && (bl->inserted)) warning (_("Could not remove hardware watchpoint %d."), - b->owner->number); + bl->owner->number); } - else if (b->owner->type == bp_catchpoint - && breakpoint_enabled (b->owner) - && !b->duplicate) + else if (bl->owner->type == bp_catchpoint + && breakpoint_enabled (bl->owner) + && !bl->duplicate) { - gdb_assert (b->owner->ops != NULL && b->owner->ops->remove != NULL); + gdb_assert (bl->owner->ops != NULL + && bl->owner->ops->remove_location != NULL); - val = b->owner->ops->remove (b->owner); + val = bl->owner->ops->remove_location (bl); if (val) return val; - b->inserted = (is == mark_inserted); + + bl->inserted = (is == mark_inserted); } return 0; } static int -remove_breakpoint (struct bp_location *b, insertion_state_t is) +remove_breakpoint (struct bp_location *bl, insertion_state_t is) { int ret; struct cleanup *old_chain; - /* B is never in moribund_locations by our callers. */ - gdb_assert (b->owner != NULL); + /* BL is never in moribund_locations by our callers. */ + gdb_assert (bl->owner != NULL); - if (b->owner->enable_state == bp_permanent) + if (bl->owner->enable_state == bp_permanent) /* Permanent breakpoints cannot be inserted or removed. */ return 0; /* The type of none suggests that owner is actually deleted. This should not ever happen. */ - gdb_assert (b->owner->type != bp_none); + gdb_assert (bl->owner->type != bp_none); old_chain = save_current_space_and_thread (); - switch_to_program_space_and_thread (b->pspace); + switch_to_program_space_and_thread (bl->pspace); - ret = remove_breakpoint_1 (b, is); + ret = remove_breakpoint_1 (bl, is); do_cleanups (old_chain); return ret; @@ -2505,11 +2672,11 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is) void mark_breakpoints_out (void) { - struct bp_location *bpt, **bptp_tmp; + struct bp_location *bl, **blp_tmp; - ALL_BP_LOCATIONS (bpt, bptp_tmp) - if (bpt->pspace == current_program_space) - bpt->inserted = 0; + ALL_BP_LOCATIONS (bl, blp_tmp) + if (bl->pspace == current_program_space) + bl->inserted = 0; } /* Clear the "inserted" flag in all breakpoints and delete any @@ -2520,15 +2687,15 @@ mark_breakpoints_out (void) Note: this function gets called at the end of a run (by generic_mourn_inferior) and when a run begins (by - init_wait_for_inferior). */ + init_wait_for_inferior). */ void breakpoint_init_inferior (enum inf_context context) { - struct breakpoint *b, *temp; - struct bp_location *bpt, **bptp_tmp; + struct breakpoint *b, *b_tmp; + struct bp_location *bl, **blp_tmp; int ix; struct program_space *pspace = current_program_space; @@ -2537,15 +2704,15 @@ breakpoint_init_inferior (enum inf_context context) if (gdbarch_has_global_breakpoints (target_gdbarch)) return; - ALL_BP_LOCATIONS (bpt, bptp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL. */ - if (bpt->pspace == pspace - && bpt->owner->enable_state != bp_permanent) - bpt->inserted = 0; + /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */ + if (bl->pspace == pspace + && bl->owner->enable_state != bp_permanent) + bl->inserted = 0; } - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { if (b->loc && b->loc->pspace != pspace) continue; @@ -2591,8 +2758,8 @@ breakpoint_init_inferior (enum inf_context context) delete_breakpoint (b); else if (context == inf_starting) { - /* Reset val field to force reread of starting value - in insert_breakpoints. */ + /* Reset val field to force reread of starting value in + insert_breakpoints. */ if (b->val) value_free (b->val); b->val = NULL; @@ -2605,8 +2772,8 @@ breakpoint_init_inferior (enum inf_context context) } /* Get rid of the moribund locations. */ - for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, bpt); ++ix) - free_bp_location (bpt); + for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, bl); ++ix) + decref_bp_location (&bl); VEC_free (bp_location_p, moribund_locations); } @@ -2628,26 +2795,25 @@ breakpoint_init_inferior (enum inf_context context) enum breakpoint_here breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) { - struct bp_location *bpt, **bptp_tmp; + struct bp_location *bl, **blp_tmp; int any_breakpoint_here = 0; - ALL_BP_LOCATIONS (bpt, bptp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (bpt->loc_type != bp_loc_software_breakpoint - && bpt->loc_type != bp_loc_hardware_breakpoint) + if (bl->loc_type != bp_loc_software_breakpoint + && bl->loc_type != bp_loc_hardware_breakpoint) continue; - /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL. */ - if ((breakpoint_enabled (bpt->owner) - || bpt->owner->enable_state == bp_permanent) - && breakpoint_address_match (bpt->pspace->aspace, bpt->address, - aspace, pc)) + /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */ + if ((breakpoint_enabled (bl->owner) + || bl->owner->enable_state == bp_permanent) + && breakpoint_location_address_match (bl, aspace, pc)) { if (overlay_debugging - && section_is_overlay (bpt->section) - && !section_is_mapped (bpt->section)) + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ - else if (bpt->owner->enable_state == bp_permanent) + else if (bl->owner->enable_state == bp_permanent) return permanent_breakpoint_here; else any_breakpoint_here = 1; @@ -2666,36 +2832,35 @@ moribund_breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) int ix; for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) - if (breakpoint_address_match (loc->pspace->aspace, loc->address, - aspace, pc)) + if (breakpoint_location_address_match (loc, aspace, pc)) return 1; return 0; } /* Returns non-zero if there's a breakpoint inserted at PC, which is - inserted using regular breakpoint_chain / bp_location array mechanism. - This does not check for single-step breakpoints, which are - inserted and removed using direct target manipulation. */ + inserted using regular breakpoint_chain / bp_location array + mechanism. This does not check for single-step breakpoints, which + are inserted and removed using direct target manipulation. */ int -regular_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) +regular_breakpoint_inserted_here_p (struct address_space *aspace, + CORE_ADDR pc) { - struct bp_location *bpt, **bptp_tmp; + struct bp_location *bl, **blp_tmp; - ALL_BP_LOCATIONS (bpt, bptp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (bpt->loc_type != bp_loc_software_breakpoint - && bpt->loc_type != bp_loc_hardware_breakpoint) + if (bl->loc_type != bp_loc_software_breakpoint + && bl->loc_type != bp_loc_hardware_breakpoint) continue; - if (bpt->inserted - && breakpoint_address_match (bpt->pspace->aspace, bpt->address, - aspace, pc)) + if (bl->inserted + && breakpoint_location_address_match (bl, aspace, pc)) { if (overlay_debugging - && section_is_overlay (bpt->section) - && !section_is_mapped (bpt->section)) + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ else return 1; @@ -2723,22 +2888,23 @@ breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) inserted at PC. */ int -software_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) +software_breakpoint_inserted_here_p (struct address_space *aspace, + CORE_ADDR pc) { - struct bp_location *bpt, **bptp_tmp; + struct bp_location *bl, **blp_tmp; - ALL_BP_LOCATIONS (bpt, bptp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (bpt->loc_type != bp_loc_software_breakpoint) + if (bl->loc_type != bp_loc_software_breakpoint) continue; - if (bpt->inserted - && breakpoint_address_match (bpt->pspace->aspace, bpt->address, + if (bl->inserted + && breakpoint_address_match (bl->pspace->aspace, bl->address, aspace, pc)) { if (overlay_debugging - && section_is_overlay (bpt->section) - && !section_is_mapped (bpt->section)) + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ else return 1; @@ -2791,51 +2957,50 @@ int breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc, ptid_t ptid) { - struct bp_location *bpt, **bptp_tmp; + struct bp_location *bl, **blp_tmp; /* The thread and task IDs associated to PTID, computed lazily. */ int thread = -1; int task = 0; - ALL_BP_LOCATIONS (bpt, bptp_tmp) + ALL_BP_LOCATIONS (bl, blp_tmp) { - if (bpt->loc_type != bp_loc_software_breakpoint - && bpt->loc_type != bp_loc_hardware_breakpoint) + if (bl->loc_type != bp_loc_software_breakpoint + && bl->loc_type != bp_loc_hardware_breakpoint) continue; - /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL. */ - if (!breakpoint_enabled (bpt->owner) - && bpt->owner->enable_state != bp_permanent) + /* ALL_BP_LOCATIONS bp_location has bl->OWNER always non-NULL. */ + if (!breakpoint_enabled (bl->owner) + && bl->owner->enable_state != bp_permanent) continue; - if (!breakpoint_address_match (bpt->pspace->aspace, bpt->address, - aspace, pc)) + if (!breakpoint_location_address_match (bl, aspace, pc)) continue; - if (bpt->owner->thread != -1) + if (bl->owner->thread != -1) { /* This is a thread-specific breakpoint. Check that ptid matches that thread. If thread hasn't been computed yet, it is now time to do so. */ if (thread == -1) thread = pid_to_thread_id (ptid); - if (bpt->owner->thread != thread) + if (bl->owner->thread != thread) continue; } - if (bpt->owner->task != 0) + if (bl->owner->task != 0) { /* This is a task-specific breakpoint. Check that ptid matches that task. If task hasn't been computed yet, it is now time to do so. */ if (task == 0) task = ada_get_task_number (ptid); - if (bpt->owner->task != task) + if (bl->owner->task != task) continue; } if (overlay_debugging - && section_is_overlay (bpt->section) - && !section_is_mapped (bpt->section)) + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ return 1; @@ -2854,12 +3019,16 @@ ep_is_catchpoint (struct breakpoint *ep) return (ep->type == bp_catchpoint); } -void +/* Frees any storage that is part of a bpstat. Does not walk the + 'next' chain. */ + +static void bpstat_free (bpstat bs) { if (bs->old_val != NULL) value_free (bs->old_val); decref_counted_command_line (&bs->commands); + decref_bp_location (&bs->bp_location_at); xfree (bs); } @@ -2902,6 +3071,7 @@ bpstat_copy (bpstat bs) tmp = (bpstat) xmalloc (sizeof (*tmp)); memcpy (tmp, bs, sizeof (*tmp)); incref_counted_command_line (tmp->commands); + incref_bp_location (tmp->bp_location_at); if (bs->old_val != NULL) { tmp->old_val = value_copy (bs->old_val); @@ -2919,7 +3089,7 @@ bpstat_copy (bpstat bs) return retval; } -/* Find the bpstat associated with this breakpoint */ +/* Find the bpstat associated with this breakpoint. */ bpstat bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint) @@ -2929,16 +3099,17 @@ bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint) for (; bsp != NULL; bsp = bsp->next) { - if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint) + if (bsp->breakpoint_at == breakpoint) return bsp; } return NULL; } -/* Put in *NUM the breakpoint number of the first breakpoint we are stopped - at. *BSP upon return is a bpstat which points to the remaining - breakpoints stopped at (but which is not guaranteed to be good for - anything but further calls to bpstat_num). +/* Put in *NUM the breakpoint number of the first breakpoint we are + stopped at. *BSP upon return is a bpstat which points to the + remaining breakpoints stopped at (but which is not guaranteed to be + good for anything but further calls to bpstat_num). + Return 0 if passed a bpstat which does not indicate any breakpoints. Return -1 if stopped at a breakpoint that has been deleted since we set it. @@ -2952,11 +3123,10 @@ bpstat_num (bpstat *bsp, int *num) if ((*bsp) == NULL) return 0; /* No more breakpoint values */ - /* We assume we'll never have several bpstats that - correspond to a single breakpoint -- otherwise, - this function might return the same number more - than once and this will look ugly. */ - b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL; + /* We assume we'll never have several bpstats that correspond to a + single breakpoint -- otherwise, this function might return the + same number more than once and this will look ugly. */ + b = (*bsp)->breakpoint_at; *bsp = (*bsp)->next; if (b == NULL) return -1; /* breakpoint that's been deleted since */ @@ -2995,24 +3165,25 @@ breakpoint_about_to_proceed (void) interrupt the command list. When the call finishes successfully, the inferior will be standing at the same breakpoint as if nothing happened. */ - if (tp->in_infcall) + if (tp->control.in_infcall) return; } breakpoint_proceeded = 1; } -/* Stub for cleaning up our state if we error-out of a breakpoint command */ +/* Stub for cleaning up our state if we error-out of a breakpoint + command. */ static void cleanup_executing_breakpoints (void *ignore) { executing_breakpoint_commands = 0; } -/* Execute all the commands associated with all the breakpoints at this - location. Any of these commands could cause the process to proceed - beyond this point, etc. We look out for such changes by checking - the global "breakpoint_proceeded" after each command. +/* Execute all the commands associated with all the breakpoints at + this location. Any of these commands could cause the process to + proceed beyond this point, etc. We look out for such changes by + checking the global "breakpoint_proceeded" after each command. Returns true if a breakpoint command resumed the inferior. In that case, it is the caller's responsibility to recall it again with the @@ -3033,7 +3204,7 @@ bpstat_do_actions_1 (bpstat *bsp) executing_breakpoint_commands = 1; old_chain = make_cleanup (cleanup_executing_breakpoints, 0); - /* This pointer will iterate over the list of bpstat's. */ + /* This pointer will iterate over the list of bpstat's. */ bs = *bsp; breakpoint_proceeded = 0; @@ -3114,7 +3285,7 @@ bpstat_do_actions (void) and only return when it is stopped at the next breakpoint, we keep doing breakpoint actions until it returns false to indicate the inferior was not resumed. */ - if (!bpstat_do_actions_1 (&inferior_thread ()->stop_bpstat)) + if (!bpstat_do_actions_1 (&inferior_thread ()->control.stop_bpstat)) break; } @@ -3139,9 +3310,9 @@ watchpoint_value_print (struct value *val, struct ui_file *stream) Current scheme: When we stop, bpstat_print() is called. It loops through the bpstat list of things causing this stop, calling the - print_bp_stop_message function on each one. The behavior of the + print_bp_stop_message function on each one. The behavior of the print_bp_stop_message function depends on the print_it field of - bpstat. If such field so indicates, call this function here. + bpstat. If such field so indicates, call this function here. Return values from this routine (ultimately used by bpstat_print() and normal_stop() to decide what to do): @@ -3164,17 +3335,10 @@ print_it_typical (bpstat bs) int bp_temp = 0; enum print_stop_action result; - /* bs->breakpoint_at can be NULL if it was a momentary breakpoint - which has since been deleted. */ - if (bs->breakpoint_at == NULL) - return PRINT_UNKNOWN; - bl = bs->breakpoint_at; + gdb_assert (bs->bp_location_at != NULL); - /* bl->owner can be NULL if it was a momentary breakpoint - which has since been placed into moribund_locations. */ - if (bl->owner == NULL) - return PRINT_UNKNOWN; - b = bl->owner; + bl = bs->bp_location_at; + b = bs->breakpoint_at; stb = ui_out_stream_new (uiout); old_chain = make_cleanup_ui_out_stream_delete (stb); @@ -3183,7 +3347,7 @@ print_it_typical (bpstat bs) { case bp_breakpoint: case bp_hardware_breakpoint: - bp_temp = bs->breakpoint_at->owner->disposition == disp_del; + bp_temp = b->disposition == disp_del; if (bl->address != bl->requested_address) breakpoint_adjustment_warning (bl->requested_address, bl->address, @@ -3213,14 +3377,14 @@ print_it_typical (bpstat bs) break; case bp_thread_event: - /* Not sure how we will get here. + /* Not sure how we will get here. GDB should not stop for these breakpoints. */ printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); result = PRINT_NOTHING; break; case bp_overlay_event: - /* By analogy with the thread event, GDB should not stop for these. */ + /* By analogy with the thread event, GDB should not stop for these. */ printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); result = PRINT_NOTHING; break; @@ -3233,7 +3397,15 @@ print_it_typical (bpstat bs) case bp_std_terminate_master: /* These should never be enabled. */ - printf_filtered (_("std::terminate Master Breakpoint: gdb should not stop!\n")); + printf_filtered (_("std::terminate Master Breakpoint: " + "gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + case bp_exception_master: + /* These should never be enabled. */ + printf_filtered (_("Exception Master Breakpoint: " + "gdb should not stop!\n")); result = PRINT_NOTHING; break; @@ -3303,7 +3475,7 @@ print_it_typical (bpstat bs) break; /* Fall through, we don't deal with these types of breakpoints - here. */ + here. */ case bp_finish: if (ui_out_is_mi_like_p (uiout)) @@ -3324,6 +3496,8 @@ print_it_typical (bpstat bs) case bp_none: case bp_longjmp: case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: case bp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: @@ -3331,6 +3505,8 @@ print_it_typical (bpstat bs) case bp_tracepoint: case bp_fast_tracepoint: case bp_jit_event: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: default: result = PRINT_UNKNOWN; break; @@ -3341,10 +3517,10 @@ print_it_typical (bpstat bs) } /* Generic routine for printing messages indicating why we - stopped. The behavior of this function depends on the value + stopped. The behavior of this function depends on the value 'print_it' in the bpstat structure. Under some circumstances we may decide not to print anything here and delegate the task to - normal_stop(). */ + normal_stop(). */ static enum print_stop_action print_bp_stop_message (bpstat bs) @@ -3352,25 +3528,28 @@ print_bp_stop_message (bpstat bs) switch (bs->print_it) { case print_it_noop: - /* Nothing should be printed for this bpstat entry. */ + /* Nothing should be printed for this bpstat entry. */ return PRINT_UNKNOWN; break; case print_it_done: /* We still want to print the frame, but we already printed the - relevant messages. */ + relevant messages. */ return PRINT_SRC_AND_LOC; break; case print_it_normal: { - const struct bp_location *bl = bs->breakpoint_at; - struct breakpoint *b = bl ? bl->owner : NULL; - + struct breakpoint *b = bs->breakpoint_at; + + /* bs->breakpoint_at can be NULL if it was a momentary breakpoint + which has since been deleted. */ + if (b == NULL) + return PRINT_UNKNOWN; + /* Normal case. Call the breakpoint's print_it method, or print_it_typical. */ - /* FIXME: how breakpoint can ever be NULL here? */ - if (b != NULL && b->ops != NULL && b->ops->print_it != NULL) + if (b->ops != NULL && b->ops->print_it != NULL) return b->ops->print_it (b); else return print_it_typical (bs); @@ -3392,17 +3571,17 @@ print_bp_stop_message (bpstat bs) "Breakpoint n," part of the output. The return value of this routine is one of: - PRINT_UNKNOWN: Means we printed nothing + PRINT_UNKNOWN: Means we printed nothing. PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent - code to print the location. An example is + code to print the location. An example is "Breakpoint 1, " which should be followed by the location. PRINT_SRC_ONLY: Means we printed something, but there is no need to also print the location part of the message. An example is the catch/throw messages, which - don't require a location appended to the end. + don't require a location appended to the end. PRINT_NOTHING: We have done some printing and we don't need any - further info to be printed.*/ + further info to be printed. */ enum print_stop_action bpstat_print (bpstat bs) @@ -3423,14 +3602,14 @@ bpstat_print (bpstat bs) } /* We reached the end of the chain, or we got a null BS to start - with and nothing was printed. */ + with and nothing was printed. */ return PRINT_UNKNOWN; } -/* Evaluate the expression EXP and return 1 if value is zero. - This is used inside a catch_errors to evaluate the breakpoint condition. - The argument is a "struct expression *" that has been cast to char * to - make it pass through catch_errors. */ +/* Evaluate the expression EXP and return 1 if value is zero. This is + used inside a catch_errors to evaluate the breakpoint condition. + The argument is a "struct expression *" that has been cast to a + "char *" to make it pass through catch_errors. */ static int breakpoint_cond_eval (void *exp) @@ -3442,16 +3621,20 @@ breakpoint_cond_eval (void *exp) return i; } -/* Allocate a new bpstat and chain it to the current one. */ +/* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */ static bpstat -bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */ ) +bpstat_alloc (struct bp_location *bl, bpstat **bs_link_pointer) { bpstat bs; bs = (bpstat) xmalloc (sizeof (*bs)); - cbs->next = bs; - bs->breakpoint_at = bl; + bs->next = NULL; + **bs_link_pointer = bs; + *bs_link_pointer = &bs->next; + bs->breakpoint_at = bl->owner; + bs->bp_location_at = bl; + incref_bp_location (bl); /* If the condition is false, etc., don't do the commands. */ bs->commands = NULL; bs->commands_left = NULL; @@ -3531,7 +3714,8 @@ watchpoints_triggered (struct target_waitstatus *ws) #define BP_TEMPFLAG 1 #define BP_HARDWAREFLAG 2 -/* Evaluate watchpoint condition expression and check if its value changed. +/* Evaluate watchpoint condition expression and check if its value + changed. P should be a pointer to struct bpstat, but is defined as a void * in order for this function to be usable with catch_errors. */ @@ -3544,10 +3728,11 @@ watchpoint_check (void *p) struct frame_info *fr; int within_current_scope; - /* BS is built for existing struct breakpoint. */ + /* BS is built from an existing struct breakpoint. */ gdb_assert (bs->breakpoint_at != NULL); - gdb_assert (bs->breakpoint_at->owner != NULL); - b = bs->breakpoint_at->owner; + b = bs->breakpoint_at; + + gdb_assert (is_watchpoint (b)); /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread @@ -3563,14 +3748,15 @@ watchpoint_check (void *p) struct gdbarch *frame_arch = get_frame_arch (frame); CORE_ADDR frame_pc = get_frame_pc (frame); - /* in_function_epilogue_p() returns a non-zero value if we're still - in the function but the stack frame has already been invalidated. - Since we can't rely on the values of local variables after the - stack has been destroyed, we are treating the watchpoint in that - state as `not changed' without further checking. Don't mark - watchpoints as changed if the current frame is in an epilogue - - even if they are in some other frame, our view of the stack - is likely to be wrong and frame_find_by_id could error out. */ + /* in_function_epilogue_p() returns a non-zero value if we're + still in the function but the stack frame has already been + invalidated. Since we can't rely on the values of local + variables after the stack has been destroyed, we are treating + the watchpoint in that state as `not changed' without further + checking. Don't mark watchpoints as changed if the current + frame is in an epilogue - even if they are in some other + frame, our view of the stack is likely to be wrong and + frame_find_by_id could error out. */ if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc)) return WP_IGNORE; @@ -3599,10 +3785,10 @@ watchpoint_check (void *p) if (within_current_scope) { - /* We use value_{,free_to_}mark because it could be a - *long* time before we return to the command level and - call free_all_values. We can't call free_all_values because - we might be in the middle of evaluating a function call. */ + /* We use value_{,free_to_}mark because it could be a *long* + time before we return to the command level and call + free_all_values. We can't call free_all_values because we + might be in the middle of evaluating a function call. */ int pc = 0; struct value *mark = value_mark (); @@ -3610,9 +3796,10 @@ watchpoint_check (void *p) fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL); - /* We use value_equal_contents instead of value_equal because the latter - coerces an array to a pointer, thus comparing just the address of the - array instead of its contents. This is not what we want. */ + /* We use value_equal_contents instead of value_equal because + the latter coerces an array to a pointer, thus comparing just + the address of the array instead of its contents. This is + not what we want. */ if ((b->val != NULL) != (new_val != NULL) || (b->val != NULL && !value_equal_contents (b->val, new_val))) { @@ -3645,23 +3832,18 @@ watchpoint_check (void *p) the first value assigned). */ /* We print all the stop information in print_it_typical(), but in this case, by the time we call print_it_typical() this bp - will be deleted already. So we have no choice but print the - information here. */ + will be deleted already. So we have no choice but print the + information here. */ if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE)); ui_out_text (uiout, "\nWatchpoint "); ui_out_field_int (uiout, "wpnum", b->number); - ui_out_text (uiout, " deleted because the program has left the block in\n\ + ui_out_text (uiout, + " deleted because the program has left the block in\n\ which its expression is valid.\n"); - if (b->related_breakpoint) - { - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->related_breakpoint->related_breakpoint = NULL; - b->related_breakpoint = NULL; - } - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); return WP_DELETED; } @@ -3679,6 +3861,9 @@ bpstat_check_location (const struct bp_location *bl, /* BL is from existing struct breakpoint. */ gdb_assert (b != NULL); + if (b->ops && b->ops->breakpoint_hit) + return b->ops->breakpoint_hit (bl, aspace, bp_addr); + /* By definition, the inferior does not report stops at tracepoints. */ if (is_tracepoint (b)) @@ -3692,7 +3877,7 @@ bpstat_check_location (const struct bp_location *bl, aspace, bp_addr)) return 0; if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) + && section_is_overlay (bl->section) && !section_is_mapped (bl->section)) return 0; } @@ -3707,24 +3892,17 @@ bpstat_check_location (const struct bp_location *bl, if (is_hardware_watchpoint (b) && b->watchpoint_triggered == watch_triggered_no) return 0; - + if (b->type == bp_hardware_breakpoint) { if (bl->address != bp_addr) return 0; if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) + && section_is_overlay (bl->section) && !section_is_mapped (bl->section)) return 0; } - if (b->type == bp_catchpoint) - { - gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL); - if (!b->ops->breakpoint_hit (b)) - return 0; - } - return 1; } @@ -3738,9 +3916,9 @@ bpstat_check_watchpoint (bpstat bs) struct breakpoint *b; /* BS is built for existing struct breakpoint. */ - bl = bs->breakpoint_at; + bl = bs->bp_location_at; gdb_assert (bl != NULL); - b = bl->owner; + b = bs->breakpoint_at; gdb_assert (b != NULL); if (is_watchpoint (b)) @@ -3766,8 +3944,9 @@ bpstat_check_watchpoint (bpstat bs) if (must_check_value) { - char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", - b->number); + char *message + = xstrprintf ("Error evaluating expression for watchpoint %d\n", + b->number); struct cleanup *cleanups = make_cleanup (xfree, message); int e = catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL); @@ -3788,7 +3967,7 @@ bpstat_check_watchpoint (bpstat bs) { /* There are two cases to consider here: - 1. we're watching the triggered memory for reads. + 1. We're watching the triggered memory for reads. In that case, trust the target, and always report the watchpoint hit to the user. Even though reads don't cause value changes, the value may @@ -3797,16 +3976,16 @@ bpstat_check_watchpoint (bpstat bs) those, and as such we should ignore our notion of old value. - 2. we're watching the triggered memory for both + 2. We're watching the triggered memory for both reads and writes. There are two ways this may happen: - 2.1. this is a target that can't break on data + 2.1. This is a target that can't break on data reads only, but can break on accesses (reads or writes), such as e.g., x86. We detect this case at the time we try to insert read watchpoints. - 2.2. otherwise, the target supports read + 2.2. Otherwise, the target supports read watchpoints, but, the user set an access or write watchpoint watching the same memory as this read watchpoint. @@ -3865,9 +4044,7 @@ bpstat_check_watchpoint (bpstat bs) case 0: /* Error from catch_errors. */ printf_filtered (_("Watchpoint %d deleted.\n"), b->number); - if (b->related_breakpoint) - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; break; @@ -3889,6 +4066,7 @@ bpstat_check_watchpoint (bpstat bs) /* Check conditions (condition proper, frame, thread and ignore count) of breakpoint referred to by BS. If we should not stop for this breakpoint, set BS->stop to 0. */ + static void bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) { @@ -3897,9 +4075,9 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) struct breakpoint *b; /* BS is built for existing struct breakpoint. */ - bl = bs->breakpoint_at; + bl = bs->bp_location_at; gdb_assert (bl != NULL); - b = bl->owner; + b = bs->breakpoint_at; gdb_assert (b != NULL); if (frame_id_p (b->frame_id) @@ -3910,19 +4088,17 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) int value_is_zero = 0; struct expression *cond; - /* If this is a scope breakpoint, mark the associated - watchpoint as triggered so that we will handle the - out-of-scope event. We'll get to the watchpoint next - iteration. */ - if (b->type == bp_watchpoint_scope) - b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; + /* Evaluate Python breakpoints that have a "stop" + method implemented. */ + if (b->py_bp_object) + bs->stop = gdbpy_should_stop (b->py_bp_object); if (is_watchpoint (b)) cond = b->cond_exp; else cond = bl->cond; - if (cond && bl->owner->disposition != disp_del_at_next_stop) + if (cond && b->disposition != disp_del_at_next_stop) { int within_current_scope = 1; @@ -3978,7 +4154,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) watchpoint, unconditionally report it. */ value_is_zero = 0; } - /* FIXME-someday, should give breakpoint # */ + /* FIXME-someday, should give breakpoint #. */ value_free_to_mark (mark); } @@ -3995,8 +4171,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) b->ignore_count--; annotate_ignore_count_change (); bs->stop = 0; - /* Increase the hit count even though we don't - stop. */ + /* Increase the hit count even though we don't stop. */ ++(b->hit_count); } } @@ -4007,7 +4182,8 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) BP_ADDR in thread PTID. Determine whether we stopped at a breakpoint, etc, or whether we - don't understand this stop. Result is a chain of bpstat's such that: + don't understand this stop. Result is a chain of bpstat's such + that: if we don't understand the stop, the result is a null pointer. @@ -4027,16 +4203,20 @@ bpstat_stop_status (struct address_space *aspace, struct breakpoint *b = NULL; struct bp_location *bl; struct bp_location *loc; - /* Root of the chain of bpstat's */ - struct bpstats root_bs[1]; + /* First item of allocated bpstat's. */ + bpstat bs_head = NULL, *bs_link = &bs_head; /* Pointer to the last thing in the chain currently. */ - bpstat bs = root_bs; + bpstat bs; int ix; int need_remove_insert; + int removed_any; - /* ALL_BP_LOCATIONS iteration would break across - update_global_location_list possibly executed by - bpstat_check_breakpoint_conditions's inferior call. */ + /* First, build the bpstat chain with locations that explain a + target stop, while being careful to not set the target running, + as that may invalidate locations (in particular watchpoint + locations are recreated). Resuming will happen here with + breakpoint conditions or watchpoint expressions that include + inferior function calls. */ ALL_BREAKPOINTS (b) { @@ -4045,11 +4225,11 @@ bpstat_stop_status (struct address_space *aspace, for (bl = b->loc; bl != NULL; bl = bl->next) { - /* For hardware watchpoints, we look only at the first location. - The watchpoint_check function will work on the entire expression, - not the individual locations. For read watchpoints, the - watchpoints_triggered function has checked all locations - already. */ + /* For hardware watchpoints, we look only at the first + location. The watchpoint_check function will work on the + entire expression, not the individual locations. For + read watchpoints, the watchpoints_triggered function has + checked all locations already. */ if (b->type == bp_hardware_watchpoint && bl != b->loc) break; @@ -4059,38 +4239,75 @@ bpstat_stop_status (struct address_space *aspace, if (!bpstat_check_location (bl, aspace, bp_addr)) continue; - /* Come here if it's a watchpoint, or if the break address matches */ + /* Come here if it's a watchpoint, or if the break address + matches. */ - bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */ + bs = bpstat_alloc (bl, &bs_link); /* Alloc a bpstat to + explain stop. */ - /* Assume we stop. Should we find watchpoint that is not actually - triggered, or if condition of breakpoint is false, we'll reset - 'stop' to 0. */ + /* Assume we stop. Should we find a watchpoint that is not + actually triggered, or if the condition of the breakpoint + evaluates as false, we'll reset 'stop' to 0. */ bs->stop = 1; bs->print = 1; - bpstat_check_watchpoint (bs); - if (!bs->stop) - continue; + /* If this is a scope breakpoint, mark the associated + watchpoint as triggered so that we will handle the + out-of-scope event. We'll get to the watchpoint next + iteration. */ + if (b->type == bp_watchpoint_scope && b->related_breakpoint != b) + b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; + } + } + + for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) + { + if (breakpoint_location_address_match (loc, aspace, bp_addr)) + { + bs = bpstat_alloc (loc, &bs_link); + /* For hits of moribund locations, we should just proceed. */ + bs->stop = 0; + bs->print = 0; + bs->print_it = print_it_noop; + } + } + + /* Now go through the locations that caused the target to stop, and + check whether we're interested in reporting this stop to higher + layers, or whether we should resume the target transparently. */ + + removed_any = 0; + + for (bs = bs_head; bs != NULL; bs = bs->next) + { + if (!bs->stop) + continue; + + bpstat_check_watchpoint (bs); + if (!bs->stop) + continue; + + b = bs->breakpoint_at; if (b->type == bp_thread_event || b->type == bp_overlay_event || b->type == bp_longjmp_master - || b->type == bp_std_terminate_master) + || b->type == bp_std_terminate_master + || b->type == bp_exception_master) /* We do not stop for these. */ bs->stop = 0; else bpstat_check_breakpoint_conditions (bs, ptid); - + if (bs->stop) { ++(b->hit_count); - /* We will stop here */ + /* We will stop here. */ if (b->disposition == disp_disable) { if (b->enable_state != bp_permanent) b->enable_state = bp_disabled; - update_global_location_list (0); + removed_any = 1; } if (b->silent) bs->print = 0; @@ -4111,46 +4328,29 @@ bpstat_stop_status (struct address_space *aspace, /* Print nothing for this entry if we dont stop or dont print. */ if (bs->stop == 0 || bs->print == 0) bs->print_it = print_it_noop; - } } - for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) - { - if (breakpoint_address_match (loc->pspace->aspace, loc->address, - aspace, bp_addr)) - { - bs = bpstat_alloc (loc, bs); - /* For hits of moribund locations, we should just proceed. */ - bs->stop = 0; - bs->print = 0; - bs->print_it = print_it_noop; - } - } - - bs->next = NULL; /* Terminate the chain */ - /* If we aren't stopping, the value of some hardware watchpoint may not have changed, but the intermediate memory locations we are watching may have. Don't bother if we're stopping; this will get done later. */ need_remove_insert = 0; - if (! bpstat_causes_stop (root_bs->next)) - for (bs = root_bs->next; bs != NULL; bs = bs->next) + if (! bpstat_causes_stop (bs_head)) + for (bs = bs_head; bs != NULL; bs = bs->next) if (!bs->stop - && bs->breakpoint_at->owner - && is_hardware_watchpoint (bs->breakpoint_at->owner)) + && bs->breakpoint_at + && is_hardware_watchpoint (bs->breakpoint_at)) { - update_watchpoint (bs->breakpoint_at->owner, 0 /* don't reparse. */); - /* Updating watchpoints invalidates bs->breakpoint_at. - Prevent further code from trying to use it. */ - bs->breakpoint_at = NULL; + update_watchpoint (bs->breakpoint_at, 0 /* don't reparse. */); need_remove_insert = 1; } if (need_remove_insert) update_global_location_list (1); + else if (removed_any) + update_global_location_list (0); - return root_bs->next; + return bs_head; } static void @@ -4176,7 +4376,7 @@ handle_jit_event (void) /* Decide what infrun needs to do with this bpstat. */ struct bpstat_what -bpstat_what (bpstat bs) +bpstat_what (bpstat bs_head) { struct bpstat_what retval; /* We need to defer calling `solib_add', as adding new symbols @@ -4184,11 +4384,13 @@ bpstat_what (bpstat bs) and hence may clear unprocessed entries in the BS chain. */ int shlib_event = 0; int jit_event = 0; + bpstat bs; retval.main_action = BPSTAT_WHAT_KEEP_CHECKING; retval.call_dummy = STOP_NONE; + retval.is_longjmp = 0; - for (; bs != NULL; bs = bs->next) + for (bs = bs_head; bs != NULL; bs = bs->next) { /* Extract this BS's action. After processing each BS, we check if its action overrides all we've seem so far. */ @@ -4201,10 +4403,10 @@ bpstat_what (bpstat bs) breakpoint which has since been deleted. */ bptype = bp_none; } - else if (bs->breakpoint_at->owner == NULL) + else if (bs->breakpoint_at == NULL) bptype = bp_none; else - bptype = bs->breakpoint_at->owner->type; + bptype = bs->breakpoint_at->type; switch (bptype) { @@ -4242,10 +4444,14 @@ bpstat_what (bpstat bs) } break; case bp_longjmp: + case bp_exception: this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME; + retval.is_longjmp = bptype == bp_longjmp; break; case bp_longjmp_resume: + case bp_exception_resume: this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME; + retval.is_longjmp = bptype == bp_longjmp_resume; break; case bp_step_resume: if (bs->stop) @@ -4261,6 +4467,7 @@ bpstat_what (bpstat bs) case bp_overlay_event: case bp_longjmp_master: case bp_std_terminate_master: + case bp_exception_master: this_action = BPSTAT_WHAT_SINGLE; break; case bp_catchpoint: @@ -4313,6 +4520,16 @@ bpstat_what (bpstat bs) out already. */ internal_error (__FILE__, __LINE__, _("bpstat_what: tracepoint encountered")); + break; + case bp_gnu_ifunc_resolver: + /* Step over it (and insert bp_gnu_ifunc_resolver_return). */ + this_action = BPSTAT_WHAT_SINGLE; + break; + case bp_gnu_ifunc_resolver_return: + /* The breakpoint will be removed, execution will restart from the + PC of the former breakpoint. */ + this_action = BPSTAT_WHAT_KEEP_CHECKING; + break; default: internal_error (__FILE__, __LINE__, _("bpstat_what: unhandled bptype %d"), (int) bptype); @@ -4321,6 +4538,9 @@ bpstat_what (bpstat bs) retval.main_action = max (retval.main_action, this_action); } + /* These operations may affect the bs->breakpoint_at state so they are + delayed after MAIN_ACTION is decided above. */ + if (shlib_event) { if (debug_infrun) @@ -4350,6 +4570,23 @@ bpstat_what (bpstat bs) handle_jit_event (); } + for (bs = bs_head; bs != NULL; bs = bs->next) + { + struct breakpoint *b = bs->breakpoint_at; + + if (b == NULL) + continue; + switch (b->type) + { + case bp_gnu_ifunc_resolver: + gnu_ifunc_resolver_stop (b); + break; + case bp_gnu_ifunc_resolver_return: + gnu_ifunc_resolver_return_stop (b); + break; + } + } + return retval; } @@ -4380,12 +4617,40 @@ bpstat_causes_stop (bpstat bs) +/* Compute a string of spaces suitable to indent the next line + so it starts at the position corresponding to the table column + named COL_NAME in the currently active table of UIOUT. */ + +static char * +wrap_indent_at_field (struct ui_out *uiout, const char *col_name) +{ + static char wrap_indent[80]; + int i, total_width, width, align; + char *text; + + total_width = 0; + for (i = 1; ui_out_query_field (uiout, i, &width, &align, &text); i++) + { + if (strcmp (text, col_name) == 0) + { + gdb_assert (total_width < sizeof wrap_indent); + memset (wrap_indent, ' ', total_width); + wrap_indent[total_width] = 0; + + return wrap_indent; + } + + total_width += width + 1; + } + + return NULL; +} + /* Print the LOC location out of the list of B->LOC locations. */ -static void print_breakpoint_location (struct breakpoint *b, - struct bp_location *loc, - char *wrap_indent, - struct ui_stream *stb) +static void +print_breakpoint_location (struct breakpoint *b, + struct bp_location *loc) { struct cleanup *old_chain = save_current_program_space (); @@ -4395,7 +4660,9 @@ static void print_breakpoint_location (struct breakpoint *b, if (loc != NULL) set_current_program_space (loc->pspace); - if (b->source_file && loc) + if (b->display_canonical) + ui_out_field_string (uiout, "what", b->addr_string); + else if (b->source_file && loc) { struct symbol *sym = find_pc_sect_function (loc->address, loc->section); @@ -4404,8 +4671,9 @@ static void print_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, "in "); ui_out_field_string (uiout, "func", SYMBOL_PRINT_NAME (sym)); - ui_out_wrap_hint (uiout, wrap_indent); - ui_out_text (uiout, " at "); + ui_out_text (uiout, " "); + ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what")); + ui_out_text (uiout, "at "); } ui_out_field_string (uiout, "file", b->source_file); ui_out_text (uiout, ":"); @@ -4423,9 +4691,14 @@ static void print_breakpoint_location (struct breakpoint *b, } else if (loc) { + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *stb_chain = make_cleanup_ui_out_stream_delete (stb); + print_address_symbolic (loc->gdbarch, loc->address, stb->stream, demangle, ""); ui_out_field_stream (uiout, "at", stb); + + do_cleanups (stb_chain); } else ui_out_field_string (uiout, "pending", b->addr_string); @@ -4433,16 +4706,9 @@ static void print_breakpoint_location (struct breakpoint *b, do_cleanups (old_chain); } -/* Print B to gdb_stdout. */ -static void -print_one_breakpoint_location (struct breakpoint *b, - struct bp_location *loc, - int loc_number, - struct bp_location **last_loc, - int print_address_bits, - int allflag) +static const char * +bptype_string (enum bptype type) { - struct command_line *l; struct ep_type_description { enum bptype type; @@ -4461,6 +4727,8 @@ print_one_breakpoint_location (struct breakpoint *b, {bp_access_watchpoint, "acc watchpoint"}, {bp_longjmp, "longjmp"}, {bp_longjmp_resume, "longjmp resume"}, + {bp_exception, "exception"}, + {bp_exception_resume, "exception resume"}, {bp_step_resume, "step resume"}, {bp_watchpoint_scope, "watchpoint scope"}, {bp_call_dummy, "call dummy"}, @@ -4470,17 +4738,36 @@ print_one_breakpoint_location (struct breakpoint *b, {bp_overlay_event, "overlay events"}, {bp_longjmp_master, "longjmp master"}, {bp_std_terminate_master, "std::terminate master"}, + {bp_exception_master, "exception master"}, {bp_catchpoint, "catchpoint"}, {bp_tracepoint, "tracepoint"}, {bp_fast_tracepoint, "fast tracepoint"}, {bp_static_tracepoint, "static tracepoint"}, {bp_jit_event, "jit events"}, + {bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"}, + {bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"}, }; - + + if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0]))) + || ((int) type != bptypes[(int) type].type)) + internal_error (__FILE__, __LINE__, + _("bptypes table does not describe type #%d."), + (int) type); + + return bptypes[(int) type].description; +} + +/* Print B to gdb_stdout. */ + +static void +print_one_breakpoint_location (struct breakpoint *b, + struct bp_location *loc, + int loc_number, + struct bp_location **last_loc, + int allflag) +{ + struct command_line *l; static char bpenables[] = "nynny"; - char wrap_indent[80]; - struct ui_stream *stb = ui_out_stream_new (uiout); - struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); struct cleanup *bkpt_chain; int header_of_multiple = 0; @@ -4490,9 +4777,8 @@ print_one_breakpoint_location (struct breakpoint *b, get_user_print_options (&opts); gdb_assert (!loc || loc_number != 0); - /* See comment in print_one_breakpoint concerning - treatment of breakpoints with single disabled - location. */ + /* See comment in print_one_breakpoint concerning treatment of + breakpoints with single disabled location. */ if (loc == NULL && (b->loc != NULL && (b->loc->next != NULL || !b->loc->enabled))) @@ -4521,15 +4807,8 @@ print_one_breakpoint_location (struct breakpoint *b, annotate_field (1); if (part_of_multiple) ui_out_field_skip (uiout, "type"); - else - { - if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0]))) - || ((int) b->type != bptypes[(int) b->type].type)) - internal_error (__FILE__, __LINE__, - _("bptypes table does not describe type #%d."), - (int) b->type); - ui_out_field_string (uiout, "type", bptypes[(int) b->type].description); - } + else + ui_out_field_string (uiout, "type", bptype_string (b->type)); /* 3 */ annotate_field (2); @@ -4544,27 +4823,17 @@ print_one_breakpoint_location (struct breakpoint *b, if (part_of_multiple) ui_out_field_string (uiout, "enabled", loc->enabled ? "y" : "n"); else - ui_out_field_fmt (uiout, "enabled", "%c", - bpenables[(int) b->enable_state]); + ui_out_field_fmt (uiout, "enabled", "%c", + bpenables[(int) b->enable_state]); ui_out_spaces (uiout, 2); /* 5 and 6 */ - strcpy (wrap_indent, " "); - if (opts.addressprint) - { - if (print_address_bits <= 32) - strcat (wrap_indent, " "); - else - strcat (wrap_indent, " "); - } - if (b->ops != NULL && b->ops->print_one != NULL) { - /* Although the print_one can possibly print - all locations, calling it here is not likely - to get any nice result. So, make sure there's - just one location. */ + /* Although the print_one can possibly print all locations, + calling it here is not likely to get any nice result. So, + make sure there's just one location. */ gdb_assert (b->loc == NULL || b->loc->next == NULL); b->ops->print_one (b, last_loc); } @@ -4595,6 +4864,8 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: case bp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: @@ -4604,10 +4875,13 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_overlay_event: case bp_longjmp_master: case bp_std_terminate_master: + case bp_exception_master: case bp_tracepoint: case bp_fast_tracepoint: case bp_static_tracepoint: case bp_jit_event: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: if (opts.addressprint) { annotate_field (4); @@ -4621,7 +4895,7 @@ print_one_breakpoint_location (struct breakpoint *b, } annotate_field (5); if (!header_of_multiple) - print_breakpoint_location (b, loc, wrap_indent, stb); + print_breakpoint_location (b, loc); if (b->loc) *last_loc = b->loc; break; @@ -4636,8 +4910,8 @@ print_one_breakpoint_location (struct breakpoint *b, || (!gdbarch_has_global_breakpoints (target_gdbarch) && (number_of_program_spaces () > 1 || number_of_inferiors () > 1) - /* LOC is for existing B, it cannot be in moribund_locations and - thus having NULL OWNER. */ + /* LOC is for existing B, it cannot be in + moribund_locations and thus having NULL OWNER. */ && loc->owner->type != bp_catchpoint))) { struct inferior *inf; @@ -4664,7 +4938,7 @@ print_one_breakpoint_location (struct breakpoint *b, if (b->thread != -1) { /* FIXME: This seems to be redundant and lost here; see the - "stop only in" line a little further down. */ + "stop only in" line a little further down. */ ui_out_text (uiout, " thread "); ui_out_field_int (uiout, "thread", b->thread); } @@ -4674,9 +4948,12 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_field_int (uiout, "task", b->task); } } - + ui_out_text (uiout, "\n"); - + + if (!part_of_multiple && b->ops && b->ops->print_one_detail) + b->ops->print_one_detail (b, uiout); + if (!part_of_multiple && b->static_trace_marker_id) { gdb_assert (b->type == bp_static_tracepoint); @@ -4714,7 +4991,7 @@ print_one_breakpoint_location (struct breakpoint *b, if (!part_of_multiple && b->thread != -1) { - /* FIXME should make an annotation for this */ + /* FIXME should make an annotation for this. */ ui_out_text (uiout, "\tstop only in thread "); ui_out_field_int (uiout, "thread", b->thread); ui_out_text (uiout, "\n"); @@ -4722,7 +4999,7 @@ print_one_breakpoint_location (struct breakpoint *b, if (!part_of_multiple && b->hit_count) { - /* FIXME should make an annotation for this */ + /* FIXME should make an annotation for this. */ if (ep_is_catchpoint (b)) ui_out_text (uiout, "\tcatchpoint"); else @@ -4735,8 +5012,8 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, " times\n"); } - /* Output the count also if it is zero, but only if this is - mi. FIXME: Should have a better test for this. */ + /* Output the count also if it is zero, but only if this is mi. + FIXME: Should have a better test for this. */ if (ui_out_is_mi_like_p (uiout)) if (!part_of_multiple && b->hit_count == 0) ui_out_field_int (uiout, "times", b->hit_count); @@ -4777,30 +5054,27 @@ print_one_breakpoint_location (struct breakpoint *b, } do_cleanups (bkpt_chain); - do_cleanups (old_chain); } static void print_one_breakpoint (struct breakpoint *b, - struct bp_location **last_loc, int print_address_bits, + struct bp_location **last_loc, int allflag) { - print_one_breakpoint_location (b, NULL, 0, last_loc, - print_address_bits, allflag); + print_one_breakpoint_location (b, NULL, 0, last_loc, allflag); /* If this breakpoint has custom print function, it's already printed. Otherwise, print individual locations, if any. */ if (b->ops == NULL || b->ops->print_one == NULL) { - /* If breakpoint has a single location that is - disabled, we print it as if it had - several locations, since otherwise it's hard to - represent "breakpoint enabled, location disabled" - situation. - Note that while hardware watchpoints have - several locations internally, that's no a property - exposed to user. */ + /* If breakpoint has a single location that is disabled, we + print it as if it had several locations, since otherwise it's + hard to represent "breakpoint enabled, location disabled" + situation. + + Note that while hardware watchpoints have several locations + internally, that's not a property exposed to user. */ if (b->loc && !is_hardware_watchpoint (b) && (b->loc->next || !b->loc->enabled) @@ -4809,8 +5083,7 @@ print_one_breakpoint (struct breakpoint *b, struct bp_location *loc; int n = 1; for (loc = b->loc; loc; loc = loc->next, ++n) - print_one_breakpoint_location (b, loc, n, last_loc, - print_address_bits, allflag); + print_one_breakpoint_location (b, loc, n, last_loc, allflag); } } } @@ -4854,9 +5127,7 @@ do_captured_breakpoint_query (struct ui_out *uiout, void *data) { if (args->bnum == b->number) { - int print_address_bits = breakpoint_address_bits (b); - - print_one_breakpoint (b, &dummy_loc, print_address_bits, 0); + print_one_breakpoint (b, &dummy_loc, 0); return GDB_RC_OK; } } @@ -4864,13 +5135,14 @@ do_captured_breakpoint_query (struct ui_out *uiout, void *data) } enum gdb_rc -gdb_breakpoint_query (struct ui_out *uiout, int bnum, char **error_message) +gdb_breakpoint_query (struct ui_out *uiout, int bnum, + char **error_message) { struct captured_breakpoint_query_args args; args.bnum = bnum; /* For the moment we don't trust print_one_breakpoint() to not throw - an error. */ + an error. */ if (catch_exceptions_with_msg (uiout, do_captured_breakpoint_query, &args, error_message, RETURN_MASK_ALL) < 0) return GDB_RC_FAIL; @@ -4879,7 +5151,7 @@ gdb_breakpoint_query (struct ui_out *uiout, int bnum, char **error_message) } /* Return non-zero if B is user settable (breakpoints, watchpoints, - catchpoints, et.al.). */ + catchpoints, et.al.). */ static int user_settable_breakpoint (const struct breakpoint *b) @@ -4888,9 +5160,19 @@ user_settable_breakpoint (const struct breakpoint *b) || b->type == bp_catchpoint || b->type == bp_hardware_breakpoint || is_tracepoint (b) - || is_watchpoint (b)); + || is_watchpoint (b) + || b->type == bp_gnu_ifunc_resolver); } - + +/* Return true if this breakpoint was set by the user, false if it is + internal or momentary. */ + +int +user_breakpoint_p (struct breakpoint *b) +{ + return user_settable_breakpoint (b) && b->number > 0; +} + /* Print information on user settable breakpoint (watchpoint, etc) number BNUM. If BNUM is -1 print all user-settable breakpoints. If ALLFLAG is non-zero, include non-user-settable breakpoints. If @@ -4899,7 +5181,8 @@ user_settable_breakpoint (const struct breakpoint *b) breakpoints listed. */ static int -breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *)) +breakpoint_1 (char *args, int allflag, + int (*filter) (const struct breakpoint *)) { struct breakpoint *b; struct bp_location *last_loc = NULL; @@ -4907,62 +5190,82 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *)) struct cleanup *bkpttbl_chain; struct value_print_options opts; int print_address_bits = 0; - + int print_type_col_width = 14; + get_user_print_options (&opts); - /* Compute the number of rows in the table, as well as the - size required for address fields. */ + /* Compute the number of rows in the table, as well as the size + required for address fields. */ nr_printable_breakpoints = 0; ALL_BREAKPOINTS (b) - if (bnum == -1 - || bnum == b->number) - { - /* If we have a filter, only list the breakpoints it accepts. */ - if (filter && !filter (b)) - continue; - - if (allflag || user_settable_breakpoint (b)) - { - int addr_bit = breakpoint_address_bits (b); - if (addr_bit > print_address_bits) - print_address_bits = addr_bit; + { + /* If we have a filter, only list the breakpoints it accepts. */ + if (filter && !filter (b)) + continue; - nr_printable_breakpoints++; - } - } + /* If we have an "args" string, it is a list of breakpoints to + accept. Skip the others. */ + if (args != NULL && *args != '\0') + { + if (allflag && parse_and_eval_long (args) != b->number) + continue; + if (!allflag && !number_is_in_list (args, b->number)) + continue; + } + + if (allflag || user_breakpoint_p (b)) + { + int addr_bit, type_len; + + addr_bit = breakpoint_address_bits (b); + if (addr_bit > print_address_bits) + print_address_bits = addr_bit; + + type_len = strlen (bptype_string (b->type)); + if (type_len > print_type_col_width) + print_type_col_width = type_len; + + nr_printable_breakpoints++; + } + } if (opts.addressprint) bkpttbl_chain - = make_cleanup_ui_out_table_begin_end (uiout, 6, nr_printable_breakpoints, + = make_cleanup_ui_out_table_begin_end (uiout, 6, + nr_printable_breakpoints, "BreakpointTable"); else bkpttbl_chain - = make_cleanup_ui_out_table_begin_end (uiout, 5, nr_printable_breakpoints, + = make_cleanup_ui_out_table_begin_end (uiout, 5, + nr_printable_breakpoints, "BreakpointTable"); if (nr_printable_breakpoints > 0) annotate_breakpoints_headers (); if (nr_printable_breakpoints > 0) annotate_field (0); - ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */ if (nr_printable_breakpoints > 0) annotate_field (1); - ui_out_table_header (uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (uiout, print_type_col_width, ui_left, + "type", "Type"); /* 2 */ if (nr_printable_breakpoints > 0) annotate_field (2); - ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */ + ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */ if (nr_printable_breakpoints > 0) annotate_field (3); ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */ if (opts.addressprint) - { - if (nr_printable_breakpoints > 0) - annotate_field (4); - if (print_address_bits <= 32) - ui_out_table_header (uiout, 10, ui_left, "addr", "Address");/* 5 */ - else - ui_out_table_header (uiout, 18, ui_left, "addr", "Address");/* 5 */ - } + { + if (nr_printable_breakpoints > 0) + annotate_field (4); + if (print_address_bits <= 32) + ui_out_table_header (uiout, 10, ui_left, + "addr", "Address"); /* 5 */ + else + ui_out_table_header (uiout, 18, ui_left, + "addr", "Address"); /* 5 */ + } if (nr_printable_breakpoints > 0) annotate_field (5); ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); /* 6 */ @@ -4971,34 +5274,48 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *)) annotate_breakpoints_table (); ALL_BREAKPOINTS (b) - { - QUIT; - if (bnum == -1 - || bnum == b->number) - { - /* If we have a filter, only list the breakpoints it accepts. */ - if (filter && !filter (b)) - continue; - - /* We only print out user settable breakpoints unless the - allflag is set. */ - if (allflag || user_settable_breakpoint (b)) - print_one_breakpoint (b, &last_loc, print_address_bits, allflag); - } - } - + { + QUIT; + /* If we have a filter, only list the breakpoints it accepts. */ + if (filter && !filter (b)) + continue; + + /* If we have an "args" string, it is a list of breakpoints to + accept. Skip the others. */ + + if (args != NULL && *args != '\0') + { + if (allflag) /* maintenance info breakpoint */ + { + if (parse_and_eval_long (args) != b->number) + continue; + } + else /* all others */ + { + if (!number_is_in_list (args, b->number)) + continue; + } + } + /* We only print out user settable breakpoints unless the + allflag is set. */ + if (allflag || user_breakpoint_p (b)) + print_one_breakpoint (b, &last_loc, allflag); + } + do_cleanups (bkpttbl_chain); if (nr_printable_breakpoints == 0) { - /* If there's a filter, let the caller decide how to report empty list. */ + /* If there's a filter, let the caller decide how to report + empty list. */ if (!filter) { - if (bnum == -1) + if (args == NULL || *args == '\0') ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n"); else - ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n", - bnum); + ui_out_message (uiout, 0, + "No breakpoint or watchpoint matching '%s'.\n", + args); } } else @@ -5007,7 +5324,7 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *)) set_next_address (last_loc->gdbarch, last_loc->address); } - /* FIXME? Should this be moved up so that it is only called when + /* FIXME? Should this be moved up so that it is only called when there have been breakpoints? */ annotate_breakpoints_table_end (); @@ -5034,46 +5351,31 @@ default_collect_info (void) } static void -breakpoints_info (char *bnum_exp, int from_tty) +breakpoints_info (char *args, int from_tty) { - int bnum = -1; - - if (bnum_exp) - bnum = parse_and_eval_long (bnum_exp); - - breakpoint_1 (bnum, 0, NULL); + breakpoint_1 (args, 0, NULL); default_collect_info (); } static void -watchpoints_info (char *wpnum_exp, int from_tty) +watchpoints_info (char *args, int from_tty) { - int wpnum = -1, num_printed; - - if (wpnum_exp) - wpnum = parse_and_eval_long (wpnum_exp); - - num_printed = breakpoint_1 (wpnum, 0, is_watchpoint); + int num_printed = breakpoint_1 (args, 0, is_watchpoint); if (num_printed == 0) { - if (wpnum == -1) + if (args == NULL || *args == '\0') ui_out_message (uiout, 0, "No watchpoints.\n"); else - ui_out_message (uiout, 0, "No watchpoint number %d.\n", wpnum); + ui_out_message (uiout, 0, "No watchpoint matching '%s'.\n", args); } } static void -maintenance_info_breakpoints (char *bnum_exp, int from_tty) +maintenance_info_breakpoints (char *args, int from_tty) { - int bnum = -1; - - if (bnum_exp) - bnum = parse_and_eval_long (bnum_exp); - - breakpoint_1 (bnum, 1, NULL); + breakpoint_1 (args, 1, NULL); default_collect_info (); } @@ -5161,9 +5463,10 @@ set_default_breakpoint (int valid, struct program_space *pspace, and it makes no sense to attempt to compare it to other addresses (or use it for any other purpose either). - More specifically, each of the following breakpoint types will always - have a zero valued address and we don't want to mark breakpoints of any of - these types to be a duplicate of an actual breakpoint at address zero: + More specifically, each of the following breakpoint types will + always have a zero valued address and we don't want to mark + breakpoints of any of these types to be a duplicate of an actual + breakpoint at address zero: bp_watchpoint bp_catchpoint @@ -5182,23 +5485,27 @@ breakpoint_address_is_meaningful (struct breakpoint *bpt) true if LOC1 and LOC2 represent the same watchpoint location. */ static int -watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2) +watchpoint_locations_match (struct bp_location *loc1, + struct bp_location *loc2) { /* Both of them must not be in moribund_locations. */ gdb_assert (loc1->owner != NULL); gdb_assert (loc2->owner != NULL); - /* If the target can evaluate the condition expression in hardware, then we - we need to insert both watchpoints even if they are at the same place. - Otherwise the watchpoint will only trigger when the condition of whichever - watchpoint was inserted evaluates to true, not giving a chance for GDB to - check the condition of the other watchpoint. */ + /* If the target can evaluate the condition expression in hardware, + then we we need to insert both watchpoints even if they are at + the same place. Otherwise the watchpoint will only trigger when + the condition of whichever watchpoint was inserted evaluates to + true, not giving a chance for GDB to check the condition of the + other watchpoint. */ if ((loc1->owner->cond_exp - && target_can_accel_watchpoint_condition (loc1->address, loc1->length, + && target_can_accel_watchpoint_condition (loc1->address, + loc1->length, loc1->watchpoint_type, loc1->owner->cond_exp)) || (loc2->owner->cond_exp - && target_can_accel_watchpoint_condition (loc2->address, loc2->length, + && target_can_accel_watchpoint_condition (loc2->address, + loc2->length, loc2->watchpoint_type, loc2->owner->cond_exp))) return 0; @@ -5229,12 +5536,46 @@ breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1, && addr1 == addr2); } +/* Returns true if {ASPACE2,ADDR2} falls within the range determined by + {ASPACE1,ADDR1,LEN1}. In most targets, this can only be true if ASPACE1 + matches ASPACE2. On targets that have global breakpoints, the address + space doesn't really matter. */ + +static int +breakpoint_address_match_range (struct address_space *aspace1, CORE_ADDR addr1, + int len1, struct address_space *aspace2, + CORE_ADDR addr2) +{ + return ((gdbarch_has_global_breakpoints (target_gdbarch) + || aspace1 == aspace2) + && addr2 >= addr1 && addr2 < addr1 + len1); +} + +/* Returns true if {ASPACE,ADDR} matches the breakpoint BL. BL may be + a ranged breakpoint. In most targets, a match happens only if ASPACE + matches the breakpoint's address space. On targets that have global + breakpoints, the address space doesn't really matter. */ + +static int +breakpoint_location_address_match (struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR addr) +{ + return (breakpoint_address_match (bl->pspace->aspace, bl->address, + aspace, addr) + || (bl->length + && breakpoint_address_match_range (bl->pspace->aspace, + bl->address, bl->length, + aspace, addr))); +} + /* Assuming LOC1 and LOC2's types' have meaningful target addresses (breakpoint_address_is_meaningful), returns true if LOC1 and LOC2 represent the same location. */ static int -breakpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2) +breakpoint_locations_match (struct bp_location *loc1, + struct bp_location *loc2) { int hw_point1, hw_point2; @@ -5250,16 +5591,20 @@ breakpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2) else if (hw_point1) return watchpoint_locations_match (loc1, loc2); else - return breakpoint_address_match (loc1->pspace->aspace, loc1->address, - loc2->pspace->aspace, loc2->address); + /* We compare bp_location.length in order to cover ranged breakpoints. */ + return (breakpoint_address_match (loc1->pspace->aspace, loc1->address, + loc2->pspace->aspace, loc2->address) + && loc1->length == loc2->length); } static void breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr, int bnum, int have_bnum) { - char astr1[40]; - char astr2[40]; + /* The longest string possibly returned by hex_string_custom + is 50 chars. These must be at least that big for safety. */ + char astr1[64]; + char astr2[64]; strcpy (astr1, hex_string_custom ((unsigned long) from_addr, 8)); strcpy (astr2, hex_string_custom ((unsigned long) to_addr, 8)); @@ -5270,10 +5615,10 @@ breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr, warning (_("Breakpoint address adjusted from %s to %s."), astr1, astr2); } -/* Adjust a breakpoint's address to account for architectural constraints - on breakpoint placement. Return the adjusted address. Note: Very - few targets require this kind of adjustment. For most targets, - this function is simply the identity function. */ +/* Adjust a breakpoint's address to account for architectural + constraints on breakpoint placement. Return the adjusted address. + Note: Very few targets require this kind of adjustment. For most + targets, this function is simply the identity function. */ static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch, @@ -5334,6 +5679,8 @@ allocate_bp_location (struct breakpoint *bpt) case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: case bp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: @@ -5344,6 +5691,9 @@ allocate_bp_location (struct breakpoint *bpt) case bp_jit_event: case bp_longjmp_master: case bp_std_terminate_master: + case bp_exception_master: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: loc->loc_type = bp_loc_software_breakpoint; break; case bp_hardware_breakpoint: @@ -5365,35 +5715,47 @@ allocate_bp_location (struct breakpoint *bpt) internal_error (__FILE__, __LINE__, _("unknown breakpoint type")); } + loc->refc = 1; return loc; } -static void free_bp_location (struct bp_location *loc) +static void +free_bp_location (struct bp_location *loc) { - /* Be sure no bpstat's are pointing at it after it's been freed. */ - /* FIXME, how can we find all bpstat's? - We just check stop_bpstat for now. Note that we cannot just - remove bpstats pointing at bpt from the stop_bpstat list - entirely, as breakpoint commands are associated with the bpstat; - if we remove it here, then the later call to - bpstat_do_actions (&stop_bpstat); - in event-top.c won't do anything, and temporary breakpoints - with commands won't work. */ - - iterate_over_threads (bpstat_remove_bp_location_callback, loc); - if (loc->cond) xfree (loc->cond); if (loc->function_name) xfree (loc->function_name); - + xfree (loc); } -/* Helper to set_raw_breakpoint below. Creates a breakpoint - that has type BPTYPE and has no locations as yet. */ -/* This function is used in gdbtk sources and thus can not be made static. */ +/* Increment reference count. */ + +static void +incref_bp_location (struct bp_location *bl) +{ + ++bl->refc; +} + +/* Decrement reference count. If the reference count reaches 0, + destroy the bp_location. Sets *BLP to NULL. */ + +static void +decref_bp_location (struct bp_location **blp) +{ + gdb_assert ((*blp)->refc > 0); + + if (--(*blp)->refc == 0) + free_bp_location (*blp); + *blp = NULL; +} + +/* Helper to set_raw_breakpoint below. Creates a breakpoint that has + type BPTYPE and has no locations as yet. */ +/* This function is used in gdbtk sources and thus can not be made + static. */ static struct breakpoint * set_raw_breakpoint_without_location (struct gdbarch *gdbarch, @@ -5420,10 +5782,11 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, b->syscalls_to_be_caught = NULL; b->ops = NULL; b->condition_not_parsed = 0; + b->py_bp_object = NULL; + b->related_breakpoint = b; - /* Add this breakpoint to the end of the chain - so that a list of breakpoints will come out in order - of increasing numbers. */ + /* Add this breakpoint to the end of the chain so that a list of + breakpoints will come out in order of increasing numbers. */ b1 = breakpoint_chain; if (b1 == 0) @@ -5437,9 +5800,12 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, return b; } -/* Initialize loc->function_name. */ +/* Initialize loc->function_name. EXPLICIT_LOC says no indirect function + resolutions should be made as the user specified the location explicitly + enough. */ + static void -set_breakpoint_location_function (struct bp_location *loc) +set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) { gdb_assert (loc->owner != NULL); @@ -5447,8 +5813,33 @@ set_breakpoint_location_function (struct bp_location *loc) || loc->owner->type == bp_hardware_breakpoint || is_tracepoint (loc->owner)) { - find_pc_partial_function (loc->address, &(loc->function_name), - NULL, NULL); + int is_gnu_ifunc; + + find_pc_partial_function_gnu_ifunc (loc->address, &loc->function_name, + NULL, NULL, &is_gnu_ifunc); + + if (is_gnu_ifunc && !explicit_loc) + { + struct breakpoint *b = loc->owner; + + gdb_assert (loc->pspace == current_program_space); + if (gnu_ifunc_resolve_name (loc->function_name, + &loc->requested_address)) + { + /* Recalculate ADDRESS based on new REQUESTED_ADDRESS. */ + loc->address = adjust_breakpoint_address (loc->gdbarch, + loc->requested_address, + b->type); + } + else if (b->type == bp_breakpoint && b->loc == loc + && loc->next == NULL && b->related_breakpoint == b) + { + /* Create only the whole new breakpoint of this type but do not + mess more complicated breakpoints with multiple locations. */ + b->type = bp_gnu_ifunc_resolver; + } + } + if (loc->function_name) loc->function_name = xstrdup (loc->function_name); } @@ -5485,7 +5876,8 @@ struct breakpoint * set_raw_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, enum bptype bptype) { - struct breakpoint *b = set_raw_breakpoint_without_location (gdbarch, bptype); + struct breakpoint *b = set_raw_breakpoint_without_location (gdbarch, + bptype); CORE_ADDR adjusted_address; struct gdbarch *loc_gdbarch; @@ -5502,7 +5894,8 @@ set_raw_breakpoint (struct gdbarch *gdbarch, breakpoint may cause target_read_memory() to be called and we do not want its scan of the location chain to find a breakpoint and location that's only been partially initialized. */ - adjusted_address = adjust_breakpoint_address (loc_gdbarch, sal.pc, b->type); + adjusted_address = adjust_breakpoint_address (loc_gdbarch, + sal.pc, b->type); b->loc = allocate_bp_location (b); b->loc->gdbarch = loc_gdbarch; @@ -5521,7 +5914,8 @@ set_raw_breakpoint (struct gdbarch *gdbarch, b->loc->section = sal.section; b->line_number = sal.line; - set_breakpoint_location_function (b->loc); + set_breakpoint_location_function (b->loc, + sal.explicit_pc || sal.explicit_line); breakpoints_changed (); @@ -5538,47 +5932,51 @@ make_breakpoint_permanent (struct breakpoint *b) b->enable_state = bp_permanent; - /* By definition, permanent breakpoints are already present in the code. - Mark all locations as inserted. For now, make_breakpoint_permanent - is called in just one place, so it's hard to say if it's reasonable - to have permanent breakpoint with multiple locations or not, - but it's easy to implmement. */ + /* By definition, permanent breakpoints are already present in the + code. Mark all locations as inserted. For now, + make_breakpoint_permanent is called in just one place, so it's + hard to say if it's reasonable to have permanent breakpoint with + multiple locations or not, but it's easy to implmement. */ for (bl = b->loc; bl; bl = bl->next) bl->inserted = 1; } /* Call this routine when stepping and nexting to enable a breakpoint - if we do a longjmp() in THREAD. When we hit that breakpoint, call - set_longjmp_resume_breakpoint() to figure out where we are going. */ + if we do a longjmp() or 'throw' in TP. FRAME is the frame which + initiated the operation. */ void -set_longjmp_breakpoint (int thread) +set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; + int thread = tp->num; /* To avoid having to rescan all objfile symbols at every step, we maintain a list of continually-inserted but always disabled longjmp "master" breakpoints. Here, we simply create momentary clones of those and enable them for the requested thread. */ - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) if (b->pspace == current_program_space - && b->type == bp_longjmp_master) + && (b->type == bp_longjmp_master + || b->type == bp_exception_master)) { struct breakpoint *clone = clone_momentary_breakpoint (b); - clone->type = bp_longjmp; + clone->type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception; clone->thread = thread; } + + tp->initiating_frame = frame; } /* Delete all longjmp breakpoints from THREAD. */ void delete_longjmp_breakpoint (int thread) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; - ALL_BREAKPOINTS_SAFE (b, temp) - if (b->type == bp_longjmp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) + if (b->type == bp_longjmp || b->type == bp_exception) { if (b->thread == thread) delete_breakpoint (b); @@ -5618,9 +6016,9 @@ disable_overlay_breakpoints (void) void set_std_terminate_breakpoint (void) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) if (b->pspace == current_program_space && b->type == bp_std_terminate_master) { @@ -5633,9 +6031,9 @@ set_std_terminate_breakpoint (void) void delete_std_terminate_breakpoint (void) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) if (b->type == bp_std_terminate) delete_breakpoint (b); } @@ -5660,9 +6058,9 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) void remove_thread_event_breakpoints (void) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) if (b->type == bp_thread_event && b->loc->pspace == current_program_space) delete_breakpoint (b); @@ -5672,8 +6070,7 @@ struct captured_parse_breakpoint_args { char **arg_p; struct symtabs_and_lines *sals_p; - char ***addr_string_p; - int *not_found_ptr; + struct linespec_result *canonical_p; }; struct lang_and_radix @@ -5694,12 +6091,25 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) return b; } +/* Remove JIT code registration and unregistration breakpoint(s). */ + +void +remove_jit_event_breakpoints (void) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + if (b->type == bp_jit_event + && b->loc->pspace == current_program_space) + delete_breakpoint (b); +} + void remove_solib_event_breakpoints (void) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) if (b->type == bp_shlib_event && b->loc->pspace == current_program_space) delete_breakpoint (b); @@ -5728,11 +6138,11 @@ disable_breakpoints_in_shlibs (void) /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */ struct breakpoint *b = loc->owner; - /* We apply the check to all breakpoints, including disabled - for those with loc->duplicate set. This is so that when breakpoint - becomes enabled, or the duplicate is removed, gdb will try to insert - all breakpoints. If we don't set shlib_disabled here, we'll try - to insert those breakpoints and fail. */ + /* We apply the check to all breakpoints, including disabled for + those with loc->duplicate set. This is so that when breakpoint + becomes enabled, or the duplicate is removed, gdb will try to + insert all breakpoints. If we don't set shlib_disabled here, + we'll try to insert those breakpoints and fail. */ if (((b->type == bp_breakpoint) || (b->type == bp_jit_event) || (b->type == bp_hardware_breakpoint) @@ -5751,8 +6161,9 @@ disable_breakpoints_in_shlibs (void) } } -/* Disable any breakpoints that are in in an unloaded shared library. Only - apply to enabled breakpoints, disabled ones can just stay disabled. */ +/* Disable any breakpoints that are in in an unloaded shared library. + Only apply to enabled breakpoints, disabled ones can just stay + disabled. */ static void disable_breakpoints_in_unloaded_shlib (struct so_list *solib) @@ -5790,7 +6201,8 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) if (!disabled_shlib_breaks) { target_terminal_ours_for_output (); - warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""), + warning (_("Temporarily disabling breakpoints " + "for unloaded shared library \"%s\""), solib->so_name); } disabled_shlib_breaks = 1; @@ -5800,18 +6212,20 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) /* FORK & VFORK catchpoints. */ -/* Implement the "insert" breakpoint_ops method for fork catchpoints. */ +/* Implement the "insert" breakpoint_ops method for fork + catchpoints. */ -static void -insert_catch_fork (struct breakpoint *b) +static int +insert_catch_fork (struct bp_location *bl) { - target_insert_fork_catchpoint (PIDGET (inferior_ptid)); + return target_insert_fork_catchpoint (PIDGET (inferior_ptid)); } -/* Implement the "remove" breakpoint_ops method for fork catchpoints. */ +/* Implement the "remove" breakpoint_ops method for fork + catchpoints. */ static int -remove_catch_fork (struct breakpoint *b) +remove_catch_fork (struct bp_location *bl) { return target_remove_fork_catchpoint (PIDGET (inferior_ptid)); } @@ -5820,12 +6234,14 @@ remove_catch_fork (struct breakpoint *b) catchpoints. */ static int -breakpoint_hit_catch_fork (struct breakpoint *b) +breakpoint_hit_catch_fork (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid); + return inferior_has_forked (inferior_ptid, &bl->owner->forked_inferior_pid); } -/* Implement the "print_it" breakpoint_ops method for fork catchpoints. */ +/* Implement the "print_it" breakpoint_ops method for fork + catchpoints. */ static enum print_stop_action print_it_catch_fork (struct breakpoint *b) @@ -5836,7 +6252,8 @@ print_it_catch_fork (struct breakpoint *b) return PRINT_SRC_AND_LOC; } -/* Implement the "print_one" breakpoint_ops method for fork catchpoints. */ +/* Implement the "print_one" breakpoint_ops method for fork + catchpoints. */ static void print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc) @@ -5845,9 +6262,9 @@ print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc) get_user_print_options (&opts); - /* Field 4, the address, is omitted (which makes the columns - not line up too nicely with the headers, but the effect - is relatively readable). */ + /* Field 4, the address, is omitted (which makes the columns not + line up too nicely with the headers, but the effect is relatively + readable). */ if (opts.addressprint) ui_out_field_skip (uiout, "addr"); annotate_field (5); @@ -5886,24 +6303,28 @@ static struct breakpoint_ops catch_fork_breakpoint_ops = insert_catch_fork, remove_catch_fork, breakpoint_hit_catch_fork, + NULL, /* resources_needed */ print_it_catch_fork, print_one_catch_fork, + NULL, /* print_one_detail */ print_mention_catch_fork, print_recreate_catch_fork }; -/* Implement the "insert" breakpoint_ops method for vfork catchpoints. */ +/* Implement the "insert" breakpoint_ops method for vfork + catchpoints. */ -static void -insert_catch_vfork (struct breakpoint *b) +static int +insert_catch_vfork (struct bp_location *bl) { - target_insert_vfork_catchpoint (PIDGET (inferior_ptid)); + return target_insert_vfork_catchpoint (PIDGET (inferior_ptid)); } -/* Implement the "remove" breakpoint_ops method for vfork catchpoints. */ +/* Implement the "remove" breakpoint_ops method for vfork + catchpoints. */ static int -remove_catch_vfork (struct breakpoint *b) +remove_catch_vfork (struct bp_location *bl) { return target_remove_vfork_catchpoint (PIDGET (inferior_ptid)); } @@ -5912,12 +6333,14 @@ remove_catch_vfork (struct breakpoint *b) catchpoints. */ static int -breakpoint_hit_catch_vfork (struct breakpoint *b) +breakpoint_hit_catch_vfork (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid); + return inferior_has_vforked (inferior_ptid, &bl->owner->forked_inferior_pid); } -/* Implement the "print_it" breakpoint_ops method for vfork catchpoints. */ +/* Implement the "print_it" breakpoint_ops method for vfork + catchpoints. */ static enum print_stop_action print_it_catch_vfork (struct breakpoint *b) @@ -5928,7 +6351,8 @@ print_it_catch_vfork (struct breakpoint *b) return PRINT_SRC_AND_LOC; } -/* Implement the "print_one" breakpoint_ops method for vfork catchpoints. */ +/* Implement the "print_one" breakpoint_ops method for vfork + catchpoints. */ static void print_one_catch_vfork (struct breakpoint *b, struct bp_location **last_loc) @@ -5936,9 +6360,9 @@ print_one_catch_vfork (struct breakpoint *b, struct bp_location **last_loc) struct value_print_options opts; get_user_print_options (&opts); - /* Field 4, the address, is omitted (which makes the columns - not line up too nicely with the headers, but the effect - is relatively readable). */ + /* Field 4, the address, is omitted (which makes the columns not + line up too nicely with the headers, but the effect is relatively + readable). */ if (opts.addressprint) ui_out_field_skip (uiout, "addr"); annotate_field (5); @@ -5977,8 +6401,10 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops = insert_catch_vfork, remove_catch_vfork, breakpoint_hit_catch_vfork, + NULL, /* resources_needed */ print_it_catch_vfork, print_one_catch_vfork, + NULL, /* print_one_detail */ print_mention_catch_vfork, print_recreate_catch_vfork }; @@ -5986,20 +6412,20 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops = /* Implement the "insert" breakpoint_ops method for syscall catchpoints. */ -static void -insert_catch_syscall (struct breakpoint *b) +static int +insert_catch_syscall (struct bp_location *bl) { struct inferior *inf = current_inferior (); ++inf->total_syscalls_count; - if (!b->syscalls_to_be_caught) + if (!bl->owner->syscalls_to_be_caught) ++inf->any_syscall_count; else { int i, iter; for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, bl->owner->syscalls_to_be_caught, i, iter); i++) { int elem; @@ -6007,7 +6433,8 @@ insert_catch_syscall (struct breakpoint *b) if (iter >= VEC_length (int, inf->syscalls_counts)) { int old_size = VEC_length (int, inf->syscalls_counts); - uintptr_t vec_addr_offset = old_size * ((uintptr_t) sizeof (int)); + uintptr_t vec_addr_offset + = old_size * ((uintptr_t) sizeof (int)); uintptr_t vec_addr; VEC_safe_grow (int, inf->syscalls_counts, iter + 1); vec_addr = (uintptr_t) VEC_address (int, inf->syscalls_counts) + @@ -6020,30 +6447,30 @@ insert_catch_syscall (struct breakpoint *b) } } - target_set_syscall_catchpoint (PIDGET (inferior_ptid), - inf->total_syscalls_count != 0, - inf->any_syscall_count, - VEC_length (int, inf->syscalls_counts), - VEC_address (int, inf->syscalls_counts)); + return target_set_syscall_catchpoint (PIDGET (inferior_ptid), + inf->total_syscalls_count != 0, + inf->any_syscall_count, + VEC_length (int, inf->syscalls_counts), + VEC_address (int, inf->syscalls_counts)); } /* Implement the "remove" breakpoint_ops method for syscall catchpoints. */ static int -remove_catch_syscall (struct breakpoint *b) +remove_catch_syscall (struct bp_location *bl) { struct inferior *inf = current_inferior (); --inf->total_syscalls_count; - if (!b->syscalls_to_be_caught) + if (!bl->owner->syscalls_to_be_caught) --inf->any_syscall_count; else { int i, iter; for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, bl->owner->syscalls_to_be_caught, i, iter); i++) { int elem; @@ -6059,19 +6486,22 @@ remove_catch_syscall (struct breakpoint *b) inf->total_syscalls_count != 0, inf->any_syscall_count, VEC_length (int, inf->syscalls_counts), - VEC_address (int, inf->syscalls_counts)); + VEC_address (int, + inf->syscalls_counts)); } /* Implement the "breakpoint_hit" breakpoint_ops method for syscall catchpoints. */ static int -breakpoint_hit_catch_syscall (struct breakpoint *b) +breakpoint_hit_catch_syscall (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - /* We must check if we are catching specific syscalls in this breakpoint. - If we are, then we must guarantee that the called syscall is the same - syscall we are catching. */ + /* We must check if we are catching specific syscalls in this + breakpoint. If we are, then we must guarantee that the called + syscall is the same syscall we are catching. */ int syscall_number = 0; + const struct breakpoint *b = bl->owner; if (!inferior_has_called_syscall (inferior_ptid, &syscall_number)) return 0; @@ -6140,14 +6570,14 @@ print_it_catch_syscall (struct breakpoint *b) static void print_one_catch_syscall (struct breakpoint *b, - struct bp_location **last_loc) + struct bp_location **last_loc) { struct value_print_options opts; get_user_print_options (&opts); - /* Field 4, the address, is omitted (which makes the columns - not line up too nicely with the headers, but the effect - is relatively readable). */ + /* Field 4, the address, is omitted (which makes the columns not + line up too nicely with the headers, but the effect is relatively + readable). */ if (opts.addressprint) ui_out_field_skip (uiout, "addr"); annotate_field (5); @@ -6258,8 +6688,10 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops = insert_catch_syscall, remove_catch_syscall, breakpoint_hit_catch_syscall, + NULL, /* resources_needed */ print_it_catch_syscall, print_one_catch_syscall, + NULL, /* print_one_detail */ print_mention_catch_syscall, print_recreate_catch_syscall }; @@ -6342,22 +6774,23 @@ create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch, /* Exec catchpoints. */ -static void -insert_catch_exec (struct breakpoint *b) +static int +insert_catch_exec (struct bp_location *bl) { - target_insert_exec_catchpoint (PIDGET (inferior_ptid)); + return target_insert_exec_catchpoint (PIDGET (inferior_ptid)); } static int -remove_catch_exec (struct breakpoint *b) +remove_catch_exec (struct bp_location *bl) { return target_remove_exec_catchpoint (PIDGET (inferior_ptid)); } static int -breakpoint_hit_catch_exec (struct breakpoint *b) +breakpoint_hit_catch_exec (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_execd (inferior_ptid, &b->exec_pathname); + return inferior_has_execd (inferior_ptid, &bl->owner->exec_pathname); } static enum print_stop_action @@ -6411,8 +6844,10 @@ static struct breakpoint_ops catch_exec_breakpoint_ops = insert_catch_exec, remove_catch_exec, breakpoint_hit_catch_exec, + NULL, /* resources_needed */ print_it_catch_exec, print_one_catch_exec, + NULL, /* print_one_detail */ print_mention_catch_exec, print_recreate_catch_exec }; @@ -6436,13 +6871,22 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, static int hw_breakpoint_used_count (void) { - struct breakpoint *b; int i = 0; + struct breakpoint *b; + struct bp_location *bl; ALL_BREAKPOINTS (b) { if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b)) - i++; + for (bl = b->loc; bl; bl = bl->next) + { + /* Special types of hardware breakpoints may use more than + one register. */ + if (b->ops && b->ops->resources_needed) + i += b->ops->resources_needed (bl); + else + i++; + } } return i; @@ -6451,20 +6895,30 @@ hw_breakpoint_used_count (void) static int hw_watchpoint_used_count (enum bptype type, int *other_type_used) { - struct breakpoint *b; int i = 0; + struct breakpoint *b; + struct bp_location *bl; *other_type_used = 0; ALL_BREAKPOINTS (b) - { - if (breakpoint_enabled (b)) - { + { + if (!breakpoint_enabled (b)) + continue; + if (b->type == type) - i++; + for (bl = b->loc; bl; bl = bl->next) + { + /* Special types of hardware watchpoints may use more than + one register. */ + if (b->ops && b->ops->resources_needed) + i += b->ops->resources_needed (bl); + else + i++; + } else if (is_hardware_watchpoint (b)) *other_type_used = 1; - } - } + } + return i; } @@ -6570,9 +7024,9 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, b->disposition = disp_donttouch; b->frame_id = frame_id; - /* If we're debugging a multi-threaded program, then we - want momentary breakpoints to be active in only a - single thread of control. */ + /* If we're debugging a multi-threaded program, then we want + momentary breakpoints to be active in only a single thread of + control. */ if (in_thread_list (inferior_ptid)) b->thread = pid_to_thread_id (inferior_ptid); @@ -6595,7 +7049,7 @@ clone_momentary_breakpoint (struct breakpoint *orig) copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type); copy->loc = allocate_bp_location (copy); - set_breakpoint_location_function (copy->loc); + set_breakpoint_location_function (copy->loc, 1); copy->loc->gdbarch = orig->loc->gdbarch; copy->loc->requested_address = orig->loc->requested_address; @@ -6659,7 +7113,8 @@ mention (struct breakpoint *b) switch (b->type) { case bp_none: - printf_filtered (_("(apparently deleted?) Eventpoint %d: "), b->number); + printf_filtered (_("(apparently deleted?) Eventpoint %d: "), + b->number); break; case bp_watchpoint: ui_out_text (uiout, "Watchpoint "); @@ -6694,6 +7149,7 @@ mention (struct breakpoint *b) do_cleanups (ui_out_chain); break; case bp_breakpoint: + case bp_gnu_ifunc_resolver: if (ui_out_is_mi_like_p (uiout)) { say_where = 0; @@ -6704,6 +7160,8 @@ mention (struct breakpoint *b) else printf_filtered (_("Breakpoint")); printf_filtered (_(" %d"), b->number); + if (b->type == bp_gnu_ifunc_resolver) + printf_filtered (_(" at gnu-indirect-function resolver")); say_where = 1; break; case bp_hardware_breakpoint: @@ -6750,6 +7208,8 @@ mention (struct breakpoint *b) case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: case bp_step_resume: case bp_call_dummy: case bp_std_terminate: @@ -6760,6 +7220,8 @@ mention (struct breakpoint *b) case bp_jit_event: case bp_longjmp_master: case bp_std_terminate_master: + case bp_exception_master: + case bp_gnu_ifunc_resolver_return: break; } @@ -6820,7 +7282,8 @@ add_location_to_breakpoint (struct breakpoint *b, gdb_assert (loc->pspace != NULL); loc->section = sal->section; - set_breakpoint_location_function (loc); + set_breakpoint_location_function (loc, + sal->explicit_pc || sal->explicit_line); return loc; } @@ -6878,7 +7341,8 @@ create_breakpoint_sal (struct gdbarch *gdbarch, char *cond_string, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, - struct breakpoint_ops *ops, int from_tty, int enabled) + struct breakpoint_ops *ops, int from_tty, + int enabled, int internal, int display_canonical) { struct breakpoint *b = NULL; int i; @@ -6915,8 +7379,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch, if (i == 0) { b = set_raw_breakpoint (gdbarch, sal, type); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; + set_breakpoint_number (internal, b); b->thread = thread; b->task = task; @@ -6939,17 +7402,15 @@ create_breakpoint_sal (struct gdbarch *gdbarch, char *marker_str; int i; - while (*p == ' ' || *p == '\t') - p++; + p = skip_spaces (p); - endp = p; - while (*endp != ' ' && *endp != '\t' && *endp != '\0') - endp++; + endp = skip_to_space (p); marker_str = savestring (p, endp - p); b->static_trace_marker_id = marker_str; - printf_filtered (_("Probed static tracepoint marker \"%s\"\n"), + printf_filtered (_("Probed static tracepoint " + "marker \"%s\"\n"), b->static_trace_marker_id); } else if (target_static_tracepoint_marker_at (sal.pc, &marker)) @@ -6957,12 +7418,13 @@ create_breakpoint_sal (struct gdbarch *gdbarch, b->static_trace_marker_id = xstrdup (marker.str_id); release_static_tracepoint_marker (&marker); - printf_filtered (_("Probed static tracepoint marker \"%s\"\n"), + printf_filtered (_("Probed static tracepoint " + "marker \"%s\"\n"), b->static_trace_marker_id); } else - warning (_("\ -Couldn't determine the static tracepoint marker to probe")); + warning (_("Couldn't determine the static " + "tracepoint marker to probe")); } if (enabled && b->pspace->executing_startup @@ -6989,6 +7451,7 @@ Couldn't determine the static tracepoint marker to probe")); } } + b->display_canonical = display_canonical; if (addr_string) b->addr_string = addr_string; else @@ -6998,7 +7461,12 @@ Couldn't determine the static tracepoint marker to probe")); = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); b->ops = ops; - mention (b); + if (internal) + /* Do not mention breakpoints with a negative number, but do + notify observers. */ + observer_notify_breakpoint_created (b->number); + else + mention (b); } /* Remove element at INDEX_TO_REMOVE from SAL, shifting other @@ -7106,9 +7574,10 @@ expand_line_sal_maybe (struct symtab_and_line sal) if (expanded.nelts <= 1) { - /* This is un ugly workaround. If we get zero - expanded sals then something is really wrong. - Fix that by returnign the original sal. */ + /* This is un ugly workaround. If we get zero expanded sals + then something is really wrong. Fix that by returning the + original sal. */ + xfree (expanded.sals); expanded.nelts = 1; expanded.sals = xmalloc (sizeof (struct symtab_and_line)); @@ -7145,16 +7614,17 @@ expand_line_sal_maybe (struct symtab_and_line sal) the arrays ADDR_STRING, COND_STRING, and SALS (but not the array contents). If the function fails (error() is called), the caller is expected to cleanups both the ADDR_STRING, COND_STRING, - COND and SALS arrays and each of those arrays contents. */ + COND and SALS arrays and each of those arrays contents. */ static void create_breakpoints_sal (struct gdbarch *gdbarch, - struct symtabs_and_lines sals, char **addr_string, + struct symtabs_and_lines sals, + struct linespec_result *canonical, char *cond_string, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, struct breakpoint_ops *ops, int from_tty, - int enabled) + int enabled, int internal) { int i; @@ -7163,28 +7633,31 @@ create_breakpoints_sal (struct gdbarch *gdbarch, struct symtabs_and_lines expanded = expand_line_sal_maybe (sals.sals[i]); - create_breakpoint_sal (gdbarch, expanded, addr_string[i], + create_breakpoint_sal (gdbarch, expanded, canonical->canonical[i], cond_string, type, disposition, - thread, task, ignore_count, ops, from_tty, enabled); + thread, task, ignore_count, ops, + from_tty, enabled, internal, + canonical->special_display); } } -/* Parse ARG which is assumed to be a SAL specification possibly +/* Parse ADDRESS which is assumed to be a SAL specification possibly followed by conditionals. On return, SALS contains an array of SAL - addresses found. ADDR_STRING contains a vector of (canonical) - address strings. ARG points to the end of the SAL. */ + addresses found. ADDR_STRING contains a vector of (canonical) + address strings. ADDRESS points to the end of the SAL. + + The array and the line spec strings are allocated on the heap, it is + the caller's responsibility to free them. */ static void parse_breakpoint_sals (char **address, struct symtabs_and_lines *sals, - char ***addr_string, - int *not_found_ptr) + struct linespec_result *canonical) { char *addr_start = *address; - *addr_string = NULL; /* If no arg given, or if first arg is 'if ', use the default - breakpoint. */ + breakpoint. */ if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { @@ -7192,7 +7665,7 @@ parse_breakpoint_sals (char **address, { struct symtab_and_line sal; - init_sal (&sal); /* initialize to zeroes */ + init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); sal.pc = default_breakpoint_address; @@ -7201,11 +7674,11 @@ parse_breakpoint_sals (char **address, sal.pspace = default_breakpoint_pspace; sal.section = find_pc_overlay (sal.pc); - /* "break" without arguments is equivalent to "break *PC" where PC is - the default_breakpoint_address. So make sure to set - sal.explicit_pc to prevent GDB from trying to expand the list of - sals to include all other instances with the same symtab and line. - */ + /* "break" without arguments is equivalent to "break *PC" + where PC is the default_breakpoint_address. So make sure + to set sal.explicit_pc to prevent GDB from trying to + expand the list of sals to include all other instances + with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7217,9 +7690,10 @@ parse_breakpoint_sals (char **address, else { /* Force almost all breakpoints to be in terms of the - current_source_symtab (which is decode_line_1's default). This - should produce the results we want almost all of the time while - leaving default_breakpoint_* alone. + current_source_symtab (which is decode_line_1's default). + This should produce the results we want almost all of the + time while leaving default_breakpoint_* alone. + ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ @@ -7230,32 +7704,31 @@ parse_breakpoint_sals (char **address, || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, addr_string, - not_found_ptr); + default_breakpoint_line, canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, - addr_string, not_found_ptr); + canonical); } - /* For any SAL that didn't have a canonical string, fill one in. */ - if (sals->nelts > 0 && *addr_string == NULL) - *addr_string = xcalloc (sals->nelts, sizeof (char **)); + /* For any SAL that didn't have a canonical string, fill one in. */ + if (sals->nelts > 0 && canonical->canonical == NULL) + canonical->canonical = xcalloc (sals->nelts, sizeof (char **)); if (addr_start != (*address)) { int i; for (i = 0; i < sals->nelts; i++) { - /* Add the string if not present. */ - if ((*addr_string)[i] == NULL) - (*addr_string)[i] = savestring (addr_start, - (*address) - addr_start); + /* Add the string if not present. */ + if (canonical->canonical[i] == NULL) + canonical->canonical[i] = savestring (addr_start, + (*address) - addr_start); } } } /* Convert each SAL into a real PC. Verify that the PC can be - inserted as a breakpoint. If it can't throw an error. */ + inserted as a breakpoint. If it can't throw an error. */ static void breakpoint_sals_to_pc (struct symtabs_and_lines *sals) @@ -7303,14 +7776,13 @@ do_captured_parse_breakpoint (struct ui_out *ui, void *data) { struct captured_parse_breakpoint_args *args = data; - parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p, - args->not_found_ptr); + parse_breakpoint_sals (args->arg_p, args->sals_p, args->canonical_p); } /* Given TOK, a string specification of condition and thread, as accepted by the 'break' command, extract the condition string and thread number and set *COND_STRING and *THREAD. - PC identifies the context at which the condition should be parsed. + PC identifies the context at which the condition should be parsed. If no condition is found, *COND_STRING is set to NULL. If no thread is found, *THREAD is set to -1. */ static void @@ -7326,13 +7798,9 @@ find_condition_and_thread (char *tok, CORE_ADDR pc, char *cond_start = NULL; char *cond_end = NULL; - while (*tok == ' ' || *tok == '\t') - tok++; - - end_tok = tok; + tok = skip_spaces (tok); - while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') - end_tok++; + end_tok = skip_to_space (tok); toklen = end_tok - tok; @@ -7391,12 +7859,9 @@ decode_static_tracepoint_spec (char **arg_p) char *marker_str; int i; - while (*p == ' ' || *p == '\t') - p++; + p = skip_spaces (p); - endp = p; - while (*endp != ' ' && *endp != '\t' && *endp != '\0') - endp++; + endp = skip_to_space (p); marker_str = savestring (p, endp - p); old_chain = make_cleanup (xfree, marker_str); @@ -7432,10 +7897,12 @@ decode_static_tracepoint_spec (char **arg_p) functions for setting a breakpoint. This function has two major modes of operations, selected by the PARSE_CONDITION_AND_THREAD parameter. If non-zero, the function will parse arg, extracting - breakpoint location, address and thread. Otherwise, ARG is just the - location of breakpoint, with condition and thread specified by the - COND_STRING and THREAD parameters. Returns true if any breakpoint - was created; false otherwise. */ + breakpoint location, address and thread. Otherwise, ARG is just + the location of breakpoint, with condition and thread specified by + the COND_STRING and THREAD parameters. If INTERNAL is non-zero, + the breakpoint number will be allocated from the internal + breakpoint count. Returns true if any breakpoint was created; + false otherwise. */ int create_breakpoint (struct gdbarch *gdbarch, @@ -7445,32 +7912,29 @@ create_breakpoint (struct gdbarch *gdbarch, int ignore_count, enum auto_boolean pending_break_support, struct breakpoint_ops *ops, - int from_tty, - int enabled) + int from_tty, int enabled, int internal) { struct gdb_exception e; struct symtabs_and_lines sals; struct symtab_and_line pending_sal; char *copy_arg; char *addr_start = arg; - char **addr_string; + struct linespec_result canonical; struct cleanup *old_chain; struct cleanup *bkpt_chain = NULL; struct captured_parse_breakpoint_args parse_args; int i; int pending = 0; - int not_found = 0; int task = 0; int prev_bkpt_count = breakpoint_count; sals.sals = NULL; sals.nelts = 0; - addr_string = NULL; + init_linespec_result (&canonical); parse_args.arg_p = &arg; parse_args.sals_p = &sals; - parse_args.addr_string_p = &addr_string; - parse_args.not_found_ptr = ¬_found; + parse_args.canonical_p = &canonical; if (type_wanted == bp_static_tracepoint && is_marker_spec (arg)) { @@ -7479,9 +7943,9 @@ create_breakpoint (struct gdbarch *gdbarch, sals = decode_static_tracepoint_spec (&arg); copy_arg = savestring (addr_start, arg - addr_start); - addr_string = xcalloc (sals.nelts, sizeof (char **)); + canonical.canonical = xcalloc (sals.nelts, sizeof (char **)); for (i = 0; i < sals.nelts; i++) - addr_string[i] = xstrdup (copy_arg); + canonical.canonical[i] = xstrdup (copy_arg); goto done; } @@ -7509,7 +7973,8 @@ create_breakpoint (struct gdbarch *gdbarch, /* If pending breakpoint support is auto query and the user selects no, then simply return the error code. */ if (pending_break_support == AUTO_BOOLEAN_AUTO - && !nquery ("Make breakpoint pending on future shared library load? ")) + && !nquery (_("Make breakpoint pending on " + "future shared library load? "))) return 0; /* At this point, either the user was queried about setting @@ -7517,7 +7982,7 @@ create_breakpoint (struct gdbarch *gdbarch, breakpoint behavior is on and thus a pending breakpoint is defaulted on behalf of the user. */ copy_arg = xstrdup (addr_start); - addr_string = ©_arg; + canonical.canonical = ©_arg; sals.nelts = 1; sals.sals = &pending_sal; pending_sal.pc = 0; @@ -7526,6 +7991,7 @@ create_breakpoint (struct gdbarch *gdbarch, default: throw_exception (e); } + break; default: if (!sals.nelts) return 0; @@ -7533,7 +7999,7 @@ create_breakpoint (struct gdbarch *gdbarch, done: - /* Create a chain of things that always need to be cleaned up. */ + /* Create a chain of things that always need to be cleaned up. */ old_chain = make_cleanup (null_cleanup, 0); if (!pending) @@ -7541,8 +8007,8 @@ create_breakpoint (struct gdbarch *gdbarch, /* Make sure that all storage allocated to SALS gets freed. */ make_cleanup (xfree, sals.sals); - /* Cleanup the addr_string array but not its contents. */ - make_cleanup (xfree, addr_string); + /* Cleanup the canonical array but not its contents. */ + make_cleanup (xfree, canonical.canonical); } /* ----------------------------- SNIP ----------------------------- @@ -7551,12 +8017,12 @@ create_breakpoint (struct gdbarch *gdbarch, then the memory is not reclaimed. */ bkpt_chain = make_cleanup (null_cleanup, 0); - /* Mark the contents of the addr_string for cleanup. These go on + /* Mark the contents of the canonical for cleanup. These go on the bkpt_chain and only occur if the breakpoint create fails. */ for (i = 0; i < sals.nelts; i++) { - if (addr_string[i] != NULL) - make_cleanup (xfree, addr_string[i]); + if (canonical.canonical[i] != NULL) + make_cleanup (xfree, canonical.canonical[i]); } /* Resolve all line numbers to PC's and verify that the addresses @@ -7570,7 +8036,7 @@ create_breakpoint (struct gdbarch *gdbarch, /* Verify that condition can be parsed, before setting any breakpoints. Allocate a separate condition expression for each - breakpoint. */ + breakpoint. */ if (!pending) { if (parse_condition_and_thread) @@ -7603,7 +8069,7 @@ create_breakpoint (struct gdbarch *gdbarch, expand multiple locations for each sal, given than SALS already should contain all sals for MARKER_ID. */ if (type_wanted == bp_static_tracepoint - && is_marker_spec (addr_string[0])) + && is_marker_spec (canonical.canonical[0])) { int i; @@ -7618,16 +8084,20 @@ create_breakpoint (struct gdbarch *gdbarch, expanded.sals[0] = sals.sals[i]; old_chain = make_cleanup (xfree, expanded.sals); - create_breakpoint_sal (gdbarch, expanded, addr_string[i], + create_breakpoint_sal (gdbarch, expanded, canonical.canonical[i], cond_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, - from_tty, enabled); + from_tty, enabled, internal, + canonical.special_display); do_cleanups (old_chain); /* Get the tracepoint we just created. */ - tp = get_breakpoint (breakpoint_count); + if (internal) + tp = get_breakpoint (internal_breakpoint_number); + else + tp = get_breakpoint (breakpoint_count); gdb_assert (tp != NULL); /* Given that its possible to have multiple markers with @@ -7640,10 +8110,11 @@ create_breakpoint (struct gdbarch *gdbarch, } } else - create_breakpoints_sal (gdbarch, sals, addr_string, cond_string, - type_wanted, tempflag ? disp_del : disp_donttouch, + create_breakpoints_sal (gdbarch, sals, &canonical, cond_string, + type_wanted, + tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, from_tty, - enabled); + enabled, internal); } else { @@ -7652,10 +8123,9 @@ create_breakpoint (struct gdbarch *gdbarch, make_cleanup (xfree, copy_arg); b = set_raw_breakpoint_without_location (gdbarch, type_wanted); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; + set_breakpoint_number (internal, b); b->thread = -1; - b->addr_string = addr_string[0]; + b->addr_string = canonical.canonical[0]; b->cond_string = NULL; b->ignore_count = ignore_count; b->disposition = tempflag ? disp_del : disp_donttouch; @@ -7663,19 +8133,25 @@ create_breakpoint (struct gdbarch *gdbarch, b->ops = ops; b->enable_state = enabled ? bp_enabled : bp_disabled; b->pspace = current_program_space; + b->py_bp_object = NULL; if (enabled && b->pspace->executing_startup && (b->type == bp_breakpoint || b->type == bp_hardware_breakpoint)) b->enable_state = bp_startup_disabled; - mention (b); + if (internal) + /* Do not mention breakpoints with a negative number, + but do notify observers. */ + observer_notify_breakpoint_created (b->number); + else + mention (b); } if (sals.nelts > 1) { - warning (_("Multiple breakpoints were set.\n" - "Use the \"delete\" command to delete unwanted breakpoints.")); + warning (_("Multiple breakpoints were set.\nUse the " + "\"delete\" command to delete unwanted breakpoints.")); prev_breakpoint_count = prev_bkpt_count; } @@ -7714,7 +8190,8 @@ break_command_1 (char *arg, int flag, int from_tty) pending_break_support, NULL /* breakpoint_ops */, from_tty, - 1 /* enabled */); + 1 /* enabled */, + 0 /* internal */); } @@ -7732,8 +8209,8 @@ resolve_sal_pc (struct symtab_and_line *sal) sal->line, sal->symtab->filename); sal->pc = pc; - /* If this SAL corresponds to a breakpoint inserted using - a line number, then skip the function prologue if necessary. */ + /* If this SAL corresponds to a breakpoint inserted using a line + number, then skip the function prologue if necessary. */ if (sal->explicit_line) skip_prologue_sal (sal); } @@ -7755,10 +8232,10 @@ resolve_sal_pc (struct symtab_and_line *sal) } else { - /* It really is worthwhile to have the section, so we'll just - have to look harder. This case can be executed if we have - line numbers but no functions (as can happen in assembly - source). */ + /* It really is worthwhile to have the section, so we'll + just have to look harder. This case can be executed + if we have line numbers but no functions (as can + happen in assembly source). */ struct minimal_symbol *msym; struct cleanup *old_chain = save_current_space_and_thread (); @@ -7819,9 +8296,9 @@ stopin_command (char *arg, int from_tty) char *argptr = arg; int hasColon = 0; - /* look for a ':'. If this is a line number specification, then + /* Look for a ':'. If this is a line number specification, then say it is bad, otherwise, it should be an address or - function/method name */ + function/method name. */ while (*argptr && !hasColon) { hasColon = (*argptr == ':'); @@ -7852,8 +8329,8 @@ stopat_command (char *arg, int from_tty) char *argptr = arg; int hasColon = 0; - /* look for a ':'. If there is a '::' then get out, otherwise - it is probably a line number. */ + /* Look for a ':'. If there is a '::' then get out, otherwise + it is probably a line number. */ while (*argptr && !hasColon) { hasColon = (*argptr == ':'); @@ -7872,9 +8349,313 @@ stopat_command (char *arg, int from_tty) break_command_1 (arg, 0, from_tty); } -/* Return non-zero if EXP is verified as constant. Returned zero means EXP is - variable. Also the constant detection may fail for some constant - expressions and in such case still falsely return zero. */ +/* Implement the "breakpoint_hit" breakpoint_ops method for + ranged breakpoints. */ + +static int +breakpoint_hit_ranged_breakpoint (const struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR bp_addr) +{ + return breakpoint_address_match_range (bl->pspace->aspace, bl->address, + bl->length, aspace, bp_addr); +} + +/* Implement the "resources_needed" breakpoint_ops method for + ranged breakpoints. */ + +static int +resources_needed_ranged_breakpoint (const struct bp_location *bl) +{ + return target_ranged_break_num_registers (); +} + +/* Implement the "print_it" breakpoint_ops method for + ranged breakpoints. */ + +static enum print_stop_action +print_it_ranged_breakpoint (struct breakpoint *b) +{ + struct bp_location *bl = b->loc; + + gdb_assert (b->type == bp_hardware_breakpoint); + + /* Ranged breakpoints have only one location. */ + gdb_assert (bl && bl->next == NULL); + + annotate_breakpoint (b->number); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary ranged breakpoint "); + else + ui_out_text (uiout, "\nRanged breakpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); + + return PRINT_SRC_AND_LOC; +} + +/* Implement the "print_one" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_one_ranged_breakpoint (struct breakpoint *b, + struct bp_location **last_loc) +{ + struct bp_location *bl = b->loc; + struct value_print_options opts; + + /* Ranged breakpoints have only one location. */ + gdb_assert (bl && bl->next == NULL); + + get_user_print_options (&opts); + + if (opts.addressprint) + /* We don't print the address range here, it will be printed later + by print_one_detail_ranged_breakpoint. */ + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + print_breakpoint_location (b, bl); + *last_loc = bl; +} + +/* Implement the "print_one_detail" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_one_detail_ranged_breakpoint (const struct breakpoint *b, + struct ui_out *uiout) +{ + CORE_ADDR address_start, address_end; + struct bp_location *bl = b->loc; + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *cleanup = make_cleanup_ui_out_stream_delete (stb); + + gdb_assert (bl); + + address_start = bl->address; + address_end = address_start + bl->length - 1; + + ui_out_text (uiout, "\taddress range: "); + fprintf_unfiltered (stb->stream, "[%s, %s]", + print_core_address (bl->gdbarch, address_start), + print_core_address (bl->gdbarch, address_end)); + ui_out_field_stream (uiout, "addr", stb); + ui_out_text (uiout, "\n"); + + do_cleanups (cleanup); +} + +/* Implement the "print_mention" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_mention_ranged_breakpoint (struct breakpoint *b) +{ + struct bp_location *bl = b->loc; + + gdb_assert (bl); + gdb_assert (b->type == bp_hardware_breakpoint); + + if (ui_out_is_mi_like_p (uiout)) + return; + + printf_filtered (_("Hardware assisted ranged breakpoint %d from %s to %s."), + b->number, paddress (bl->gdbarch, bl->address), + paddress (bl->gdbarch, bl->address + bl->length - 1)); +} + +/* Implement the "print_recreate" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string, + b->addr_string_range_end); +} + +/* The breakpoint_ops structure to be used in ranged breakpoints. */ + +static struct breakpoint_ops ranged_breakpoint_ops = +{ + NULL, /* insert */ + NULL, /* remove */ + breakpoint_hit_ranged_breakpoint, + resources_needed_ranged_breakpoint, + print_it_ranged_breakpoint, + print_one_ranged_breakpoint, + print_one_detail_ranged_breakpoint, + print_mention_ranged_breakpoint, + print_recreate_ranged_breakpoint +}; + +/* Find the address where the end of the breakpoint range should be + placed, given the SAL of the end of the range. This is so that if + the user provides a line number, the end of the range is set to the + last instruction of the given line. */ + +static CORE_ADDR +find_breakpoint_range_end (struct symtab_and_line sal) +{ + CORE_ADDR end; + + /* If the user provided a PC value, use it. Otherwise, + find the address of the end of the given location. */ + if (sal.explicit_pc) + end = sal.pc; + else + { + int ret; + CORE_ADDR start; + + ret = find_line_pc_range (sal, &start, &end); + if (!ret) + error (_("Could not find location of the end of the range.")); + + /* find_line_pc_range returns the start of the next line. */ + end--; + } + + return end; +} + +/* Implement the "break-range" CLI command. */ + +static void +break_range_command (char *arg, int from_tty) +{ + char *arg_start, *addr_string_start, *addr_string_end; + struct linespec_result canonical_start, canonical_end; + int bp_count, can_use_bp, length; + CORE_ADDR end; + struct breakpoint *b; + struct symtab_and_line sal_start, sal_end; + struct symtabs_and_lines sals_start, sals_end; + struct cleanup *cleanup_bkpt; + + /* We don't support software ranged breakpoints. */ + if (target_ranged_break_num_registers () < 0) + error (_("This target does not support hardware ranged breakpoints.")); + + bp_count = hw_breakpoint_used_count (); + bp_count += target_ranged_break_num_registers (); + can_use_bp = target_can_use_hardware_watchpoint (bp_hardware_breakpoint, + bp_count, 0); + if (can_use_bp < 0) + error (_("Hardware breakpoints used exceeds limit.")); + + if (arg == NULL || arg[0] == '\0') + error(_("No address range specified.")); + + sals_start.sals = NULL; + sals_start.nelts = 0; + init_linespec_result (&canonical_start); + + while (*arg == ' ' || *arg == '\t') + arg++; + + parse_breakpoint_sals (&arg, &sals_start, &canonical_start); + + sal_start = sals_start.sals[0]; + addr_string_start = canonical_start.canonical[0]; + cleanup_bkpt = make_cleanup (xfree, addr_string_start); + xfree (sals_start.sals); + xfree (canonical_start.canonical); + + if (arg[0] != ',') + error (_("Too few arguments.")); + else if (sals_start.nelts == 0) + error (_("Could not find location of the beginning of the range.")); + else if (sals_start.nelts != 1) + error (_("Cannot create a ranged breakpoint with multiple locations.")); + + resolve_sal_pc (&sal_start); + + arg++; /* Skip the comma. */ + while (*arg == ' ' || *arg == '\t') + arg++; + + /* Parse the end location. */ + + sals_end.sals = NULL; + sals_end.nelts = 0; + init_linespec_result (&canonical_end); + arg_start = arg; + + /* We call decode_line_1 directly here instead of using + parse_breakpoint_sals because we need to specify the start location's + symtab and line as the default symtab and line for the end of the + range. This makes it possible to have ranges like "foo.c:27, +14", + where +14 means 14 lines from the start location. */ + sals_end = decode_line_1 (&arg, 1, sal_start.symtab, sal_start.line, + &canonical_end); + + /* canonical_end can be NULL if it was of the form "*0xdeadbeef". */ + if (canonical_end.canonical == NULL) + canonical_end.canonical = xcalloc (1, sizeof (char **)); + /* Add the string if not present. */ + if (arg_start != arg && canonical_end.canonical[0] == NULL) + canonical_end.canonical[0] = savestring (arg_start, arg - arg_start); + + sal_end = sals_end.sals[0]; + addr_string_end = canonical_end.canonical[0]; + make_cleanup (xfree, addr_string_end); + xfree (sals_end.sals); + xfree (canonical_end.canonical); + + if (sals_end.nelts == 0) + error (_("Could not find location of the end of the range.")); + else if (sals_end.nelts != 1) + error (_("Cannot create a ranged breakpoint with multiple locations.")); + + resolve_sal_pc (&sal_end); + + end = find_breakpoint_range_end (sal_end); + if (sal_start.pc > end) + error (_("Invalid address range, end preceeds start.")); + + length = end - sal_start.pc + 1; + if (length < 0) + /* Length overflowed. */ + error (_("Address range too large.")); + else if (length == 1) + { + /* This range is simple enough to be handled by + the `hbreak' command. */ + hbreak_command (addr_string_start, 1); + + do_cleanups (cleanup_bkpt); + + return; + } + + /* Now set up the breakpoint. */ + b = set_raw_breakpoint (get_current_arch (), sal_start, + bp_hardware_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->disposition = disp_donttouch; + b->addr_string = addr_string_start; + b->addr_string_range_end = addr_string_end; + b->ops = &ranged_breakpoint_ops; + b->loc->length = length; + + discard_cleanups (cleanup_bkpt); + + mention (b); + update_global_location_list (1); +} + +/* Return non-zero if EXP is verified as constant. Returned zero + means EXP is variable. Also the constant detection may fail for + some constant expressions and in such case still falsely return + zero. */ static int watchpoint_exp_is_const (const struct expression *exp) { @@ -7939,23 +8720,26 @@ watchpoint_exp_is_const (const struct expression *exp) case UNOP_COMPLEMENT: case UNOP_ADDR: case UNOP_HIGH: - /* Unary, binary and ternary operators: We have to check their - operands. If they are constant, then so is the result of - that operation. For instance, if A and B are determined to be - constants, then so is "A + B". - - UNOP_IND is one exception to the rule above, because the value - of *ADDR is not necessarily a constant, even when ADDR is. */ + /* Unary, binary and ternary operators: We have to check + their operands. If they are constant, then so is the + result of that operation. For instance, if A and B are + determined to be constants, then so is "A + B". + + UNOP_IND is one exception to the rule above, because the + value of *ADDR is not necessarily a constant, even when + ADDR is. */ break; case OP_VAR_VALUE: /* Check whether the associated symbol is a constant. + We use SYMBOL_CLASS rather than TYPE_CONST because it's - possible that a buggy compiler could mark a variable as constant - even when it is not, and TYPE_CONST would return true in this - case, while SYMBOL_CLASS wouldn't. - We also have to check for function symbols because they are - always constant. */ + possible that a buggy compiler could mark a variable as + constant even when it is not, and TYPE_CONST would return + true in this case, while SYMBOL_CLASS wouldn't. + + We also have to check for function symbols because they + are always constant. */ { struct symbol *s = exp->elts[i + 2].symbol; @@ -7977,16 +8761,65 @@ watchpoint_exp_is_const (const struct expression *exp) return 1; } +/* Implement the "insert" breakpoint_ops method for hardware watchpoints. */ + +static int +insert_watchpoint (struct bp_location *bl) +{ + int length = bl->owner->exact? 1 : bl->length; + + return target_insert_watchpoint (bl->address, length, bl->watchpoint_type, + bl->owner->cond_exp); +} + +/* Implement the "remove" breakpoint_ops method for hardware watchpoints. */ + +static int +remove_watchpoint (struct bp_location *bl) +{ + int length = bl->owner->exact? 1 : bl->length; + + return target_remove_watchpoint (bl->address, length, bl->watchpoint_type, + bl->owner->cond_exp); +} + +/* Implement the "resources_needed" breakpoint_ops method for + hardware watchpoints. */ + +static int +resources_needed_watchpoint (const struct bp_location *bl) +{ + int length = bl->owner->exact? 1 : bl->length; + + return target_region_ok_for_hw_watchpoint (bl->address, length); +} + +/* The breakpoint_ops structure to be used in hardware watchpoints. */ + +static struct breakpoint_ops watchpoint_breakpoint_ops = +{ + insert_watchpoint, + remove_watchpoint, + NULL, /* breakpoint_hit */ + resources_needed_watchpoint, + NULL, /* print_it */ + NULL, /* print_one */ + NULL, /* print_one_detail */ + NULL, /* print_mention */ + NULL /* print_recreate */ +}; + /* accessflag: hw_write: watch write, hw_read: watch read, hw_access: watch access (read or write) */ static void -watch_command_1 (char *arg, int accessflag, int from_tty) +watch_command_1 (char *arg, int accessflag, int from_tty, + int just_location, int internal) { struct breakpoint *b, *scope_breakpoint = NULL; struct expression *exp; struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; - struct value *val, *mark; + struct value *val, *mark, *result; struct frame_info *frame; char *exp_start = NULL; char *exp_end = NULL; @@ -7996,7 +8829,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty) char *cond_end = NULL; int i, other_type_used, target_resources_ok = 0; enum bptype bp_type; - int mem_cnt = 0; + int reg_cnt = 0; int thread = -1; int pc = 0; @@ -8008,9 +8841,9 @@ watch_command_1 (char *arg, int accessflag, int from_tty) /* Points tok to the end of the argument list. */ tok = arg + toklen - 1; - /* Go backwards in the parameters list. Skip the last parameter. - If we're expecting a 'thread ' parameter, this should - be the thread identifier. */ + /* Go backwards in the parameters list. Skip the last + parameter. If we're expecting a 'thread ' + parameter, this should be the thread identifier. */ while (tok > arg && (*tok == ' ' || *tok == '\t')) tok--; while (tok > arg && (*tok != ' ' && *tok != '\t')) @@ -8019,9 +8852,9 @@ watch_command_1 (char *arg, int accessflag, int from_tty) /* Points end_tok to the beginning of the last token. */ id_tok_start = tok + 1; - /* Go backwards in the parameters list. Skip one more parameter. - If we're expecting a 'thread ' parameter, we should - reach a "thread" token. */ + /* Go backwards in the parameters list. Skip one more + parameter. If we're expecting a 'thread ' + parameter, we should reach a "thread" token. */ while (tok > arg && (*tok == ' ' || *tok == '\t')) tok--; @@ -8085,17 +8918,20 @@ watch_command_1 (char *arg, int accessflag, int from_tty) exp_valid_block = innermost_block; mark = value_mark (); - fetch_subexp_value (exp, &pc, &val, NULL, NULL); - if (val != NULL) - release_value (val); + fetch_subexp_value (exp, &pc, &val, &result, NULL); - tok = arg; - while (*tok == ' ' || *tok == '\t') - tok++; - end_tok = tok; + if (just_location) + { + exp_valid_block = NULL; + val = value_addr (result); + release_value (val); + value_free_to_mark (mark); + } + else if (val != NULL) + release_value (val); - while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') - end_tok++; + tok = skip_spaces (arg); + end_tok = skip_to_space (tok); toklen = end_tok - tok; if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) @@ -8123,25 +8959,26 @@ watch_command_1 (char *arg, int accessflag, int from_tty) else bp_type = bp_hardware_watchpoint; - mem_cnt = can_use_hardware_watchpoint (val); - if (mem_cnt == 0 && bp_type != bp_hardware_watchpoint) + reg_cnt = can_use_hardware_watchpoint (val, target_exact_watchpoints); + if (reg_cnt == 0 && bp_type != bp_hardware_watchpoint) error (_("Expression cannot be implemented with read/access watchpoint.")); - if (mem_cnt != 0) + if (reg_cnt != 0) { i = hw_watchpoint_used_count (bp_type, &other_type_used); target_resources_ok = - target_can_use_hardware_watchpoint (bp_type, i + mem_cnt, + target_can_use_hardware_watchpoint (bp_type, i + reg_cnt, other_type_used); if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint) error (_("Target does not support this type of hardware watchpoint.")); if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint) - error (_("Target can only support one kind of HW watchpoint at a time.")); + error (_("Target can only support one kind " + "of HW watchpoint at a time.")); } - /* Change the type of breakpoint to an ordinary watchpoint if a hardware - watchpoint could not be set. */ - if (!mem_cnt || target_resources_ok <= 0) + /* Change the type of breakpoint to an ordinary watchpoint if a + hardware watchpoint could not be set. */ + if (!reg_cnt || target_resources_ok <= 0) bp_type = bp_watchpoint; frame = block_innermost_frame (exp_valid_block); @@ -8181,16 +9018,41 @@ watch_command_1 (char *arg, int accessflag, int from_tty) /* Now set up the breakpoint. */ b = set_raw_breakpoint_without_location (NULL, bp_type); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; + set_breakpoint_number (internal, b); b->thread = thread; b->disposition = disp_donttouch; b->exp = exp; b->exp_valid_block = exp_valid_block; b->cond_exp_valid_block = cond_exp_valid_block; - b->exp_string = savestring (exp_start, exp_end - exp_start); + if (just_location) + { + struct type *t = value_type (val); + CORE_ADDR addr = value_as_address (val); + char *name; + + t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t))); + name = type_to_string (t); + + b->exp_string_reparse = xstrprintf ("* (%s *) %s", name, + core_addr_to_string (addr)); + xfree (name); + + b->exp_string = xstrprintf ("-location %.*s", + (int) (exp_end - exp_start), exp_start); + + /* The above expression is in C. */ + b->language = language_c; + } + else + b->exp_string = savestring (exp_start, exp_end - exp_start); b->val = val; b->val_valid = 1; + b->ops = &watchpoint_breakpoint_ops; + + /* Use an exact watchpoint when there's only one memory region to be + watched, and only one debug register is needed to watch it. */ + b->exact = target_exact_watchpoints && reg_cnt == 1; + if (cond_start) b->cond_string = savestring (cond_start, cond_end - cond_start); else @@ -8215,22 +9077,30 @@ watch_command_1 (char *arg, int accessflag, int from_tty) scope_breakpoint->related_breakpoint = b; } - value_free_to_mark (mark); + if (!just_location) + value_free_to_mark (mark); /* Finally update the new watchpoint. This creates the locations that should be inserted. */ update_watchpoint (b, 1); - - mention (b); + if (internal) + /* Do not mention breakpoints with a negative number, but do + notify observers. */ + observer_notify_breakpoint_created (b->number); + else + mention (b); update_global_location_list (1); } -/* Return count of locations need to be watched and can be handled - in hardware. If the watchpoint can not be handled - in hardware return zero. */ +/* Return count of debug registers needed to watch the given expression. + If EXACT_WATCHPOINTS is 1, then consider that only the address of + the start of the watched region will be monitored (i.e., all accesses + will be aligned). This uses less debug registers on some targets. + + If the watchpoint cannot be handled in hardware return zero. */ static int -can_use_hardware_watchpoint (struct value *v) +can_use_hardware_watchpoint (struct value *v, int exact_watchpoints) { int found_memory_cnt = 0; struct value *head = v; @@ -8262,10 +9132,12 @@ can_use_hardware_watchpoint (struct value *v) { if (VALUE_LVAL (v) == lval_memory) { - if (value_lazy (v)) - /* A lazy memory lvalue is one that GDB never needed to fetch; - we either just used its address (e.g., `a' in `a.b') or - we never needed it at all (e.g., `a' in `a,b'). */ + if (v != head && value_lazy (v)) + /* A lazy memory lvalue in the chain is one that GDB never + needed to fetch; we either just used its address (e.g., + `a' in `a.b') or we never needed it at all (e.g., `a' + in `a,b'). This doesn't apply to HEAD; if that is + lazy then it was not readable, but watch it anyway. */ ; else { @@ -8281,12 +9153,18 @@ can_use_hardware_watchpoint (struct value *v) && TYPE_CODE (vtype) != TYPE_CODE_ARRAY)) { CORE_ADDR vaddr = value_address (v); - int len = TYPE_LENGTH (value_type (v)); + int len; + int num_regs; + + len = (exact_watchpoints + && is_scalar_type_recursive (vtype))? + 1 : TYPE_LENGTH (value_type (v)); - if (!target_region_ok_for_hw_watchpoint (vaddr, len)) + num_regs = target_region_ok_for_hw_watchpoint (vaddr, len); + if (!num_regs) return 0; else - found_memory_cnt++; + found_memory_cnt += num_regs; } } } @@ -8303,39 +9181,75 @@ can_use_hardware_watchpoint (struct value *v) } void -watch_command_wrapper (char *arg, int from_tty) +watch_command_wrapper (char *arg, int from_tty, int internal) +{ + watch_command_1 (arg, hw_write, from_tty, 0, internal); +} + +/* A helper function that looks for an argument at the start of a + string. The argument must also either be at the end of the string, + or be followed by whitespace. Returns 1 if it finds the argument, + 0 otherwise. If the argument is found, it updates *STR. */ + +static int +check_for_argument (char **str, char *arg, int arg_len) +{ + if (strncmp (*str, arg, arg_len) == 0 + && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len]))) + { + *str += arg_len; + return 1; + } + return 0; +} + +/* A helper function that looks for the "-location" argument and then + calls watch_command_1. */ + +static void +watch_maybe_just_location (char *arg, int accessflag, int from_tty) { - watch_command (arg, from_tty); + int just_location = 0; + + if (arg + && (check_for_argument (&arg, "-location", sizeof ("-location") - 1) + || check_for_argument (&arg, "-l", sizeof ("-l") - 1))) + { + arg = skip_spaces (arg); + just_location = 1; + } + + watch_command_1 (arg, accessflag, from_tty, just_location, 0); } static void watch_command (char *arg, int from_tty) { - watch_command_1 (arg, hw_write, from_tty); + watch_maybe_just_location (arg, hw_write, from_tty); } void -rwatch_command_wrapper (char *arg, int from_tty) +rwatch_command_wrapper (char *arg, int from_tty, int internal) { - rwatch_command (arg, from_tty); + watch_command_1 (arg, hw_read, from_tty, 0, internal); } static void rwatch_command (char *arg, int from_tty) { - watch_command_1 (arg, hw_read, from_tty); + watch_maybe_just_location (arg, hw_read, from_tty); } void -awatch_command_wrapper (char *arg, int from_tty) +awatch_command_wrapper (char *arg, int from_tty, int internal) { - awatch_command (arg, from_tty); + watch_command_1 (arg, hw_access, from_tty, 0, internal); } static void awatch_command (char *arg, int from_tty) { - watch_command_1 (arg, hw_access, from_tty); + watch_maybe_just_location (arg, hw_access, from_tty); } @@ -8346,12 +9260,13 @@ struct until_break_command_continuation_args { struct breakpoint *breakpoint; struct breakpoint *breakpoint2; + int thread_num; }; /* This function is called by fetch_inferior_event via the - cmd_continuation pointer, to complete the until command. It takes + cmd_continuation pointer, to complete the until command. It takes care of cleaning up the temporary breakpoints set up by the until - command. */ + command. */ static void until_break_command_continuation (void *arg) { @@ -8360,6 +9275,7 @@ until_break_command_continuation (void *arg) delete_breakpoint (a->breakpoint); if (a->breakpoint2) delete_breakpoint (a->breakpoint2); + delete_longjmp_breakpoint (a->thread_num); } void @@ -8371,24 +9287,25 @@ until_break_command (char *arg, int from_tty, int anywhere) struct breakpoint *breakpoint; struct breakpoint *breakpoint2 = NULL; struct cleanup *old_chain; + int thread; + struct thread_info *tp; clear_proceed_status (); /* Set a breakpoint where the user wants it and at return from - this function */ + this function. */ if (default_breakpoint_valid) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, (char ***) NULL, NULL); + default_breakpoint_line, NULL); else - sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, - 0, (char ***) NULL, NULL); + sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); if (sals.nelts != 1) error (_("Couldn't get information on specified line.")); sal = sals.sals[0]; - xfree (sals.sals); /* malloc'd, so freed */ + xfree (sals.sals); /* malloc'd, so freed. */ if (*arg) error (_("Junk at end of arguments.")); @@ -8401,14 +9318,17 @@ until_break_command (char *arg, int from_tty, int anywhere) breakpoint = set_momentary_breakpoint (get_frame_arch (frame), sal, null_frame_id, bp_until); else - /* Otherwise, specify the selected frame, because we want to stop only - at the very same frame. */ + /* Otherwise, specify the selected frame, because we want to stop + only at the very same frame. */ breakpoint = set_momentary_breakpoint (get_frame_arch (frame), sal, get_stack_frame_id (frame), bp_until); old_chain = make_cleanup_delete_breakpoint (breakpoint); + tp = inferior_thread (); + thread = tp->num; + /* Keep within the current frame, or in frames called by the current one. */ @@ -8421,14 +9341,17 @@ until_break_command (char *arg, int from_tty, int anywhere) frame_unwind_caller_id (frame), bp_until); make_cleanup_delete_breakpoint (breakpoint2); + + set_longjmp_breakpoint (tp, frame_unwind_caller_id (frame)); + make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); } proceed (-1, TARGET_SIGNAL_DEFAULT, 0); - /* If we are running asynchronously, and proceed call above has actually - managed to start the target, arrange for breakpoints to be - deleted when the target stops. Otherwise, we're already stopped and - delete breakpoints via cleanup chain. */ + /* If we are running asynchronously, and proceed call above has + actually managed to start the target, arrange for breakpoints to + be deleted when the target stops. Otherwise, we're already + stopped and delete breakpoints via cleanup chain. */ if (target_can_async_p () && is_running (inferior_ptid)) { @@ -8437,6 +9360,7 @@ until_break_command (char *arg, int from_tty, int anywhere) args->breakpoint = breakpoint; args->breakpoint2 = breakpoint2; + args->thread_num = thread; discard_cleanups (old_chain); add_continuation (inferior_thread (), @@ -8447,22 +9371,13 @@ until_break_command (char *arg, int from_tty, int anywhere) do_cleanups (old_chain); } -static void -ep_skip_leading_whitespace (char **s) -{ - if ((s == NULL) || (*s == NULL)) - return; - while (isspace (**s)) - *s += 1; -} - /* This function attempts to parse an optional "if " clause from the arg string. If one is not found, it returns NULL. Else, it returns a pointer to the condition string. (It does not attempt to evaluate the string against a particular block.) And, it updates arg to point to the first character following the parsed - if clause in the arg string. */ + if clause in the arg string. */ static char * ep_parse_optional_if_clause (char **arg) @@ -8472,15 +9387,16 @@ ep_parse_optional_if_clause (char **arg) if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2])) return NULL; - /* Skip the "if" keyword. */ + /* Skip the "if" keyword. */ (*arg) += 2; /* Skip any extra leading whitespace, and record the start of the - condition string. */ - ep_skip_leading_whitespace (arg); + condition string. */ + *arg = skip_spaces (*arg); cond_string = *arg; - /* Assume that the condition occupies the remainder of the arg string. */ + /* Assume that the condition occupies the remainder of the arg + string. */ (*arg) += strlen (cond_string); return cond_string; @@ -8511,20 +9427,20 @@ catch_fork_command_1 (char *arg, int from_tty, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); /* The allowed syntax is: catch [v]fork catch [v]fork if - First, check if there's an if clause. */ + First, check if there's an if clause. */ cond_string = ep_parse_optional_if_clause (&arg); if ((*arg != '\0') && !isspace (*arg)) error (_("Junk at end of arguments.")); /* If this target supports it, create a fork or vfork catchpoint - and enable reporting of such events. */ + and enable reporting of such events. */ switch (fork_kind) { case catch_fork_temporary: @@ -8555,20 +9471,20 @@ catch_exec_command_1 (char *arg, int from_tty, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); /* The allowed syntax is: catch exec catch exec if - First, check if there's an if clause. */ + First, check if there's an if clause. */ cond_string = ep_parse_optional_if_clause (&arg); if ((*arg != '\0') && !isspace (*arg)) error (_("Junk at end of arguments.")); /* If this target supports it, create an exec catchpoint - and enable reporting of such events. */ + and enable reporting of such events. */ create_catchpoint (gdbarch, tempflag, cond_string, &catch_exec_breakpoint_ops); } @@ -8648,7 +9564,8 @@ print_mention_exception_catchpoint (struct breakpoint *b) catch catchpoints. */ static void -print_recreate_exception_catchpoint (struct breakpoint *b, struct ui_file *fp) +print_recreate_exception_catchpoint (struct breakpoint *b, + struct ui_file *fp) { int bp_temp; int bp_throw; @@ -8663,8 +9580,10 @@ static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ + NULL, /* resources_needed */ print_exception_catchpoint, print_one_exception_catchpoint, + NULL, /* print_one_detail */ print_mention_exception_catchpoint, print_recreate_exception_catchpoint }; @@ -8687,12 +9606,13 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string, 0, AUTO_BOOLEAN_TRUE /* pending */, &gnu_v3_exception_catchpoint_ops, from_tty, - 1 /* enabled */); + 1 /* enabled */, + 0 /* internal */); return 1; } -/* Deal with "catch catch" and "catch throw" commands */ +/* Deal with "catch catch" and "catch throw" commands. */ static void catch_exception_command_1 (enum exception_event_kind ex_event, char *arg, @@ -8702,7 +9622,7 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); cond_string = ep_parse_optional_if_clause (&arg); @@ -8766,7 +9686,7 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch, version for exception catchpoints, because two catchpoints used for different exception names will use the same address. In this case, a "breakpoint ... also set at..." warning is - unproductive. Besides. the warning phrasing is also a bit + unproductive. Besides, the warning phrasing is also a bit inapropriate, we should use the word catchpoint, and tell the user what type of catchpoint it is. The above is good enough for now, though. */ @@ -8860,9 +9780,9 @@ catch_syscall_split_args (char *arg) get_syscall_by_name (cur_name, &s); if (s.number == UNKNOWN_SYSCALL) - /* Here we have to issue an error instead of a warning, because - GDB cannot do anything useful if there's no syscall number to - be caught. */ + /* Here we have to issue an error instead of a warning, + because GDB cannot do anything useful if there's no + syscall number to be caught. */ error (_("Unknown syscall name '%s'."), cur_name); } @@ -8888,11 +9808,11 @@ catch_syscall_command_1 (char *arg, int from_tty, /* Checking if the feature if supported. */ if (gdbarch_get_syscall_number_p (gdbarch) == 0) error (_("The feature 'catch syscall' is not supported on \ -this architeture yet.")); +this architecture yet.")); tempflag = get_cmd_context (command) == CATCH_TEMPORARY; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); /* We need to do this first "dummy" translation in order to get the syscall XML file loaded or, most important, @@ -8918,7 +9838,8 @@ this architeture yet.")); /* Implement the "catch assert" command. */ static void -catch_assert_command (char *arg, int from_tty, struct cmd_list_element *command) +catch_assert_command (char *arg, int from_tty, + struct cmd_list_element *command) { struct gdbarch *gdbarch = get_current_arch (); int tempflag; @@ -8971,7 +9892,7 @@ clear_command (char *arg, int from_tty) sals.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); - init_sal (&sal); /* initialize to zeroes */ + init_sal (&sal); /* Initialize to zeroes. */ sal.line = default_breakpoint_line; sal.symtab = default_breakpoint_symtab; sal.pc = default_breakpoint_address; @@ -8985,27 +9906,27 @@ clear_command (char *arg, int from_tty) default_match = 1; } - /* We don't call resolve_sal_pc here. That's not - as bad as it seems, because all existing breakpoints - typically have both file/line and pc set. So, if - clear is given file/line, we can match this to existing - breakpoint without obtaining pc at all. + /* We don't call resolve_sal_pc here. That's not as bad as it + seems, because all existing breakpoints typically have both + file/line and pc set. So, if clear is given file/line, we can + match this to existing breakpoint without obtaining pc at all. We only support clearing given the address explicitly present in breakpoint table. Say, we've set breakpoint - at file:line. There were several PC values for that file:line, + at file:line. There were several PC values for that file:line, due to optimization, all in one block. - We've picked one PC value. If "clear" is issued with another + + We've picked one PC value. If "clear" is issued with another PC corresponding to the same file:line, the breakpoint won't be cleared. We probably can still clear the breakpoint, but since the other PC value is never presented to user, user can only find it by guessing, and it does not seem important to support that. */ - /* For each line spec given, delete bps which correspond - to it. Do it in two passes, solely to preserve the current - behavior that from_tty is forced true if we delete more than - one breakpoint. */ + /* For each line spec given, delete bps which correspond to it. Do + it in two passes, solely to preserve the current behavior that + from_tty is forced true if we delete more than one + breakpoint. */ found = NULL; for (i = 0; i < sals.nelts; i++) @@ -9024,12 +9945,11 @@ clear_command (char *arg, int from_tty) sal = sals.sals[i]; - /* Find all matching breakpoints and add them to - 'found'. */ + /* Find all matching breakpoints and add them to 'found'. */ ALL_BREAKPOINTS (b) { int match = 0; - /* Are we going to delete b? */ + /* Are we going to delete b? */ if (b->type != bp_none && !is_watchpoint (b)) { struct bp_location *loc = b->loc; @@ -9044,7 +9964,8 @@ clear_command (char *arg, int from_tty) && b->source_file != NULL && sal.symtab != NULL && sal.pspace == loc->pspace - && strcmp (b->source_file, sal.symtab->filename) == 0 + && filename_cmp (b->source_file, + sal.symtab->filename) == 0 && b->line_number == sal.line); if (pc_match || line_match) { @@ -9068,7 +9989,7 @@ clear_command (char *arg, int from_tty) } if (VEC_length(breakpoint_p, found) > 1) - from_tty = 1; /* Always report if deleted more than one */ + from_tty = 1; /* Always report if deleted more than one. */ if (from_tty) { if (VEC_length(breakpoint_p, found) == 1) @@ -9095,27 +10016,27 @@ clear_command (char *arg, int from_tty) void breakpoint_auto_delete (bpstat bs) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; for (; bs; bs = bs->next) - if (bs->breakpoint_at - && bs->breakpoint_at->owner - && bs->breakpoint_at->owner->disposition == disp_del + if (bs->breakpoint_at + && bs->breakpoint_at->disposition == disp_del && bs->stop) - delete_breakpoint (bs->breakpoint_at->owner); + delete_breakpoint (bs->breakpoint_at); - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { if (b->disposition == disp_del_at_next_stop) delete_breakpoint (b); } } -/* A comparison function for bp_location AP and BP being interfaced to qsort. - Sort elements primarily by their ADDRESS (no matter what does - breakpoint_address_is_meaningful say for its OWNER), secondarily by ordering - first bp_permanent OWNERed elements and terciarily just ensuring the array - is sorted stable way despite qsort being an instable algorithm. */ +/* A comparison function for bp_location AP and BP being interfaced to + qsort. Sort elements primarily by their ADDRESS (no matter what + does breakpoint_address_is_meaningful say for its OWNER), + secondarily by ordering first bp_permanent OWNERed elements and + terciarily just ensuring the array is sorted stable way despite + qsort being an instable algorithm. */ static int bp_location_compare (const void *ap, const void *bp) @@ -9133,8 +10054,8 @@ bp_location_compare (const void *ap, const void *bp) if (a_perm != b_perm) return (a_perm < b_perm) - (a_perm > b_perm); - /* Make the user-visible order stable across GDB runs. Locations of the same - breakpoint can be sorted in arbitrary order. */ + /* Make the user-visible order stable across GDB runs. Locations of + the same breakpoint can be sorted in arbitrary order. */ if (a->owner->number != b->owner->number) return (a->owner->number > b->owner->number) @@ -9144,8 +10065,8 @@ bp_location_compare (const void *ap, const void *bp) } /* Set bp_location_placed_address_before_address_max and - bp_location_shadow_len_after_address_max according to the current content of - the bp_location array. */ + bp_location_shadow_len_after_address_max according to the current + content of the bp_location array. */ static void bp_location_target_extensions_update (void) @@ -9212,8 +10133,8 @@ update_global_location_list (int should_insert) struct bp_location *awp_loc_first; /* access watchpoint */ struct bp_location *rwp_loc_first; /* read watchpoint */ - /* Saved former bp_location array which we compare against the newly built - bp_location from the current state of ALL_BREAKPOINTS. */ + /* Saved former bp_location array which we compare against the newly + built bp_location from the current state of ALL_BREAKPOINTS. */ struct bp_location **old_location, **old_locp; unsigned old_location_count; @@ -9237,14 +10158,15 @@ update_global_location_list (int should_insert) bp_location_target_extensions_update (); - /* Identify bp_location instances that are no longer present in the new - list, and therefore should be freed. Note that it's not necessary that - those locations should be removed from inferior -- if there's another - location at the same address (previously marked as duplicate), - we don't need to remove/insert the location. + /* Identify bp_location instances that are no longer present in the + new list, and therefore should be freed. Note that it's not + necessary that those locations should be removed from inferior -- + if there's another location at the same address (previously + marked as duplicate), we don't need to remove/insert the + location. - LOCP is kept in sync with OLD_LOCP, each pointing to the current and - former bp_location array state respectively. */ + LOCP is kept in sync with OLD_LOCP, each pointing to the current + and former bp_location array state respectively. */ locp = bp_location; for (old_locp = old_location; old_locp < old_location + old_location_count; @@ -9253,15 +10175,15 @@ update_global_location_list (int should_insert) struct bp_location *old_loc = *old_locp; struct bp_location **loc2p; - /* Tells if 'old_loc' is found amoung the new locations. If not, we - have to free it. */ + /* Tells if 'old_loc' is found amoung the new locations. If + not, we have to free it. */ int found_object = 0; /* Tells if the location should remain inserted in the target. */ int keep_in_target = 0; int removed = 0; - /* Skip LOCP entries which will definitely never be needed. Stop either - at or being the one matching OLD_LOC. */ + /* Skip LOCP entries which will definitely never be needed. + Stop either at or being the one matching OLD_LOC. */ while (locp < bp_location + bp_location_count && (*locp)->address < old_loc->address) locp++; @@ -9278,27 +10200,29 @@ update_global_location_list (int should_insert) } } - /* If this location is no longer present, and inserted, look if there's - maybe a new location at the same address. If so, mark that one - inserted, and don't remove this one. This is needed so that we - don't have a time window where a breakpoint at certain location is not - inserted. */ + /* If this location is no longer present, and inserted, look if + there's maybe a new location at the same address. If so, + mark that one inserted, and don't remove this one. This is + needed so that we don't have a time window where a breakpoint + at certain location is not inserted. */ if (old_loc->inserted) { - /* If the location is inserted now, we might have to remove it. */ + /* If the location is inserted now, we might have to remove + it. */ if (found_object && should_be_inserted (old_loc)) { - /* The location is still present in the location list, and still - should be inserted. Don't do anything. */ + /* The location is still present in the location list, + and still should be inserted. Don't do anything. */ keep_in_target = 1; } else { - /* The location is either no longer present, or got disabled. - See if there's another location at the same address, in which - case we don't need to remove this one from the target. */ + /* The location is either no longer present, or got + disabled. See if there's another location at the + same address, in which case we don't need to remove + this one from the target. */ /* OLD_LOC comes from existing struct breakpoint. */ if (breakpoint_address_is_meaningful (old_loc->owner)) @@ -9313,7 +10237,8 @@ update_global_location_list (int should_insert) if (breakpoint_locations_match (loc2, old_loc)) { /* For the sake of should_be_inserted. - Duplicates check below will fix up this later. */ + Duplicates check below will fix up this + later. */ loc2->duplicate = 0; /* Read watchpoint locations are switched to @@ -9341,15 +10266,16 @@ update_global_location_list (int should_insert) { if (remove_breakpoint (old_loc, mark_uninserted)) { - /* This is just about all we can do. We could keep this - location on the global list, and try to remove it next - time, but there's no particular reason why we will - succeed next time. + /* This is just about all we can do. We could keep + this location on the global list, and try to + remove it next time, but there's no particular + reason why we will succeed next time. - Note that at this point, old_loc->owner is still valid, - as delete_breakpoint frees the breakpoint only - after calling us. */ - printf_filtered (_("warning: Error removing breakpoint %d\n"), + Note that at this point, old_loc->owner is still + valid, as delete_breakpoint frees the breakpoint + only after calling us. */ + printf_filtered (_("warning: Error removing " + "breakpoint %d\n"), old_loc->owner->number); } removed = 1; @@ -9413,7 +10339,10 @@ update_global_location_list (int should_insert) VEC_safe_push (bp_location_p, moribund_locations, old_loc); } else - free_bp_location (old_loc); + { + old_loc->owner = NULL; + decref_bp_location (&old_loc); + } } } @@ -9433,7 +10362,8 @@ update_global_location_list (int should_insert) rwp_loc_first = NULL; ALL_BP_LOCATIONS (loc, locp) { - /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */ + /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always + non-NULL. */ struct breakpoint *b = loc->owner; struct bp_location **loc_first_p; @@ -9496,7 +10426,7 @@ breakpoint_retire_moribund (void) for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) if (--(loc->events_till_retirement) == 0) { - free_bp_location (loc); + decref_bp_location (&loc); VEC_unordered_remove (bp_location_p, moribund_locations, ix); --ix; } @@ -9511,14 +10441,15 @@ update_global_location_list_nothrow (int inserting) update_global_location_list (inserting); } -/* Clear LOC from a BPS. */ +/* Clear BKP from a BPS. */ + static void -bpstat_remove_bp_location (bpstat bps, struct bp_location *loc) +bpstat_remove_bp_location (bpstat bps, struct breakpoint *bpt) { bpstat bs; for (bs = bps; bs; bs = bs->next) - if (bs->breakpoint_at == loc) + if (bs->breakpoint_at == bpt) { bs->breakpoint_at = NULL; bs->old_val = NULL; @@ -9528,16 +10459,16 @@ bpstat_remove_bp_location (bpstat bps, struct bp_location *loc) /* Callback for iterate_over_threads. */ static int -bpstat_remove_bp_location_callback (struct thread_info *th, void *data) +bpstat_remove_breakpoint_callback (struct thread_info *th, void *data) { - struct bp_location *loc = data; + struct breakpoint *bpt = data; - bpstat_remove_bp_location (th->stop_bpstat, loc); + bpstat_remove_bp_location (th->control.stop_bpstat, bpt); return 0; } /* Delete a breakpoint and clean up all traces of it in the data - structures. */ + structures. */ void delete_breakpoint (struct breakpoint *bpt) @@ -9546,30 +10477,41 @@ delete_breakpoint (struct breakpoint *bpt) gdb_assert (bpt != NULL); - /* Has this bp already been deleted? This can happen because multiple - lists can hold pointers to bp's. bpstat lists are especial culprits. - - One example of this happening is a watchpoint's scope bp. When the - scope bp triggers, we notice that the watchpoint is out of scope, and - delete it. We also delete its scope bp. But the scope bp is marked - "auto-deleting", and is already on a bpstat. That bpstat is then - checked for auto-deleting bp's, which are deleted. - - A real solution to this problem might involve reference counts in bp's, - and/or giving them pointers back to their referencing bpstat's, and - teaching delete_breakpoint to only free a bp's storage when no more - references were extent. A cheaper bandaid was chosen. */ + /* Has this bp already been deleted? This can happen because + multiple lists can hold pointers to bp's. bpstat lists are + especial culprits. + + One example of this happening is a watchpoint's scope bp. When + the scope bp triggers, we notice that the watchpoint is out of + scope, and delete it. We also delete its scope bp. But the + scope bp is marked "auto-deleting", and is already on a bpstat. + That bpstat is then checked for auto-deleting bp's, which are + deleted. + + A real solution to this problem might involve reference counts in + bp's, and/or giving them pointers back to their referencing + bpstat's, and teaching delete_breakpoint to only free a bp's + storage when no more references were extent. A cheaper bandaid + was chosen. */ if (bpt->type == bp_none) return; - /* At least avoid this stale reference until the reference counting of - breakpoints gets resolved. */ - if (bpt->related_breakpoint != NULL) + /* At least avoid this stale reference until the reference counting + of breakpoints gets resolved. */ + if (bpt->related_breakpoint != bpt) { - gdb_assert (bpt->related_breakpoint->related_breakpoint == bpt); - bpt->related_breakpoint->disposition = disp_del_at_next_stop; - bpt->related_breakpoint->related_breakpoint = NULL; - bpt->related_breakpoint = NULL; + struct breakpoint *related; + + if (bpt->type == bp_watchpoint_scope) + watchpoint_del_at_next_stop (bpt->related_breakpoint); + else if (bpt->related_breakpoint->type == bp_watchpoint_scope) + watchpoint_del_at_next_stop (bpt); + + /* Unlink bpt from the bpt->related_breakpoint ring. */ + for (related = bpt; related->related_breakpoint != bpt; + related = related->related_breakpoint); + related->related_breakpoint = bpt->related_breakpoint; + bpt->related_breakpoint = bpt; } observer_notify_breakpoint_deleted (bpt->number); @@ -9588,26 +10530,39 @@ delete_breakpoint (struct breakpoint *bpt) xfree (bpt->cond_string); xfree (bpt->cond_exp); xfree (bpt->addr_string); + xfree (bpt->addr_string_range_end); xfree (bpt->exp); xfree (bpt->exp_string); + xfree (bpt->exp_string_reparse); value_free (bpt->val); xfree (bpt->source_file); xfree (bpt->exec_pathname); clean_up_filters (&bpt->syscalls_to_be_caught); - /* Now that breakpoint is removed from breakpoint - list, update the global location list. This - will remove locations that used to belong to - this breakpoint. Do this before freeing - the breakpoint itself, since remove_breakpoint - looks at location's owner. It might be better - design to have location completely self-contained, - but it's not the case now. */ + + /* Be sure no bpstat's are pointing at the breakpoint after it's + been freed. */ + /* FIXME, how can we find all bpstat's? We just check stop_bpstat + in all threeds for now. Note that we cannot just remove bpstats + pointing at bpt from the stop_bpstat list entirely, as breakpoint + commands are associated with the bpstat; if we remove it here, + then the later call to bpstat_do_actions (&stop_bpstat); in + event-top.c won't do anything, and temporary breakpoints with + commands won't work. */ + + iterate_over_threads (bpstat_remove_breakpoint_callback, bpt); + + /* Now that breakpoint is removed from breakpoint list, update the + global location list. This will remove locations that used to + belong to this breakpoint. Do this before freeing the breakpoint + itself, since remove_breakpoint looks at location's owner. It + might be better design to have location completely + self-contained, but it's not the case now. */ update_global_location_list (0); - /* On the chance that someone will soon try again to delete this same - bp, we mark it as deleted before freeing its storage. */ + /* On the chance that someone will soon try again to delete this + same bp, we mark it as deleted before freeing its storage. */ bpt->type = bp_none; xfree (bpt); @@ -9637,7 +10592,7 @@ do_delete_breakpoint (struct breakpoint *b, void *ignore) void delete_command (char *arg, int from_tty) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; dont_repeat (); @@ -9646,8 +10601,8 @@ delete_command (char *arg, int from_tty) int breaks_to_delete = 0; /* Delete all breakpoints if no argument. - Do not delete internal or call-dummy breakpoints, these - have to be deleted with an explicit breakpoint number argument. */ + Do not delete internal or call-dummy breakpoints, these have + to be deleted with an explicit breakpoint number argument. */ ALL_BREAKPOINTS (b) { if (b->type != bp_call_dummy @@ -9658,6 +10613,7 @@ delete_command (char *arg, int from_tty) && b->type != bp_overlay_event && b->type != bp_longjmp_master && b->type != bp_std_terminate_master + && b->type != bp_exception_master && b->number >= 0) { breaks_to_delete = 1; @@ -9669,7 +10625,7 @@ delete_command (char *arg, int from_tty) if (!from_tty || (breaks_to_delete && query (_("Delete all breakpoints? ")))) { - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { if (b->type != bp_call_dummy && b->type != bp_std_terminate @@ -9679,6 +10635,7 @@ delete_command (char *arg, int from_tty) && b->type != bp_overlay_event && b->type != bp_longjmp_master && b->type != bp_std_terminate_master + && b->type != bp_exception_master && b->number >= 0) delete_breakpoint (b); } @@ -9721,8 +10678,8 @@ ambiguous_names_p (struct bp_location *loc) slot = (const char **) htab_find_slot (htab, (const void *) name, INSERT); - /* NOTE: We can assume slot != NULL here because xcalloc never returns - NULL. */ + /* NOTE: We can assume slot != NULL here because xcalloc never + returns NULL. */ if (*slot != NULL) { htab_delete (htab); @@ -9868,21 +10825,27 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) return sal; } -static void +/* Create new breakpoint locations for B (a hardware or software breakpoint) + based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is + a ranged breakpoint. */ + +void update_breakpoint_locations (struct breakpoint *b, - struct symtabs_and_lines sals) + struct symtabs_and_lines sals, + struct symtabs_and_lines sals_end) { int i; - char *s; struct bp_location *existing_locations = b->loc; - /* If there's no new locations, and all existing locations - are pending, don't do anything. This optimizes - the common case where all locations are in the same - shared library, that was unloaded. We'd like to - retain the location, so that when the library - is loaded again, we don't loose the enabled/disabled - status of the individual locations. */ + /* Ranged breakpoints have only one start location and one end location. */ + gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1)); + + /* If there's no new locations, and all existing locations are + pending, don't do anything. This optimizes the common case where + all locations are in the same shared library, that was unloaded. + We'd like to retain the location, so that when the library is + loaded again, we don't loose the enabled/disabled status of the + individual locations. */ if (all_locations_are_pending (existing_locations) && sals.nelts == 0) return; @@ -9897,6 +10860,7 @@ update_breakpoint_locations (struct breakpoint *b, old symtab. */ if (b->cond_string != NULL) { + char *s; struct gdb_exception e; s = b->cond_string; @@ -9907,7 +10871,8 @@ update_breakpoint_locations (struct breakpoint *b, } if (e.reason < 0) { - warning (_("failed to reevaluate condition for breakpoint %d: %s"), + warning (_("failed to reevaluate condition " + "for breakpoint %d: %s"), b->number, e.message); new_loc->enabled = 0; } @@ -9922,13 +10887,21 @@ update_breakpoint_locations (struct breakpoint *b, if (b->line_number == 0) b->line_number = sals.sals[i].line; + + if (sals_end.nelts) + { + CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]); + + new_loc->length = end - sals.sals[0].pc + 1; + } } /* Update locations of permanent breakpoints. */ if (b->enable_state == bp_permanent) make_breakpoint_permanent (b); - /* If possible, carry over 'disable' status from existing breakpoints. */ + /* If possible, carry over 'disable' status from existing + breakpoints. */ { struct bp_location *e = existing_locations; /* If there are multiple breakpoints with the same function name, @@ -9946,8 +10919,7 @@ update_breakpoint_locations (struct breakpoint *b, if (have_ambiguous_names) { for (; l; l = l->next) - if (breakpoint_address_match (e->pspace->aspace, e->address, - l->pspace->aspace, l->address)) + if (breakpoint_locations_match (e, l)) { l->enabled = 0; break; @@ -9970,6 +10942,135 @@ update_breakpoint_locations (struct breakpoint *b, update_global_location_list (1); } +/* Find the SaL locations corresponding to the given ADDR_STRING. + On return, FOUND will be 1 if any SaL was found, zero otherwise. */ + +static struct symtabs_and_lines +addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) +{ + char *s; + int marker_spec; + struct symtabs_and_lines sals = {0}; + struct gdb_exception e; + + s = addr_string; + marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s); + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + if (marker_spec) + { + sals = decode_static_tracepoint_spec (&s); + if (sals.nelts > b->static_trace_marker_id_idx) + { + sals.sals[0] = sals.sals[b->static_trace_marker_id_idx]; + sals.nelts = 1; + } + else + error (_("marker %s not found"), b->static_trace_marker_id); + } + else + sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL); + } + if (e.reason < 0) + { + int not_found_and_ok = 0; + /* For pending breakpoints, it's expected that parsing will + fail until the right shared library is loaded. User has + already told to create pending breakpoints and don't need + extra messages. If breakpoint is in bp_shlib_disabled + state, then user already saw the message about that + breakpoint being disabled, and don't want to see more + errors. */ + if (e.error == NOT_FOUND_ERROR + && (b->condition_not_parsed + || (b->loc && b->loc->shlib_disabled) + || b->enable_state == bp_disabled)) + not_found_and_ok = 1; + + if (!not_found_and_ok) + { + /* We surely don't want to warn about the same breakpoint + 10 times. One solution, implemented here, is disable + the breakpoint on error. Another solution would be to + have separate 'warning emitted' flag. Since this + happens only when a binary has changed, I don't know + which approach is better. */ + b->enable_state = bp_disabled; + throw_exception (e); + } + } + + if (e.reason == 0 || e.error != NOT_FOUND_ERROR) + { + gdb_assert (sals.nelts == 1); + + resolve_sal_pc (&sals.sals[0]); + if (b->condition_not_parsed && s && s[0]) + { + char *cond_string = 0; + int thread = -1; + int task = 0; + + find_condition_and_thread (s, sals.sals[0].pc, + &cond_string, &thread, &task); + if (cond_string) + b->cond_string = cond_string; + b->thread = thread; + b->task = task; + b->condition_not_parsed = 0; + } + + if (b->type == bp_static_tracepoint && !marker_spec) + sals.sals[0] = update_static_tracepoint (b, sals.sals[0]); + + *found = 1; + } + else + *found = 0; + + return sals; +} + +/* Reevaluate a hardware or software breakpoint and recreate its locations. + This is necessary after symbols are read (e.g., an executable or DSO + was loaded, or the inferior just started). */ + +static void +re_set_breakpoint (struct breakpoint *b) +{ + int found; + struct symtabs_and_lines sals, sals_end; + struct symtabs_and_lines expanded = {0}; + struct symtabs_and_lines expanded_end = {0}; + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); + + input_radix = b->input_radix; + save_current_space_and_thread (); + switch_to_program_space_and_thread (b->pspace); + set_language (b->language); + + sals = addr_string_to_sals (b, b->addr_string, &found); + if (found) + { + make_cleanup (xfree, sals.sals); + expanded = expand_line_sal_maybe (sals.sals[0]); + } + + if (b->addr_string_range_end) + { + sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found); + if (found) + { + make_cleanup (xfree, sals_end.sals); + expanded_end = expand_line_sal_maybe (sals_end.sals[0]); + } + } + + update_breakpoint_locations (b, expanded, expanded_end); + do_cleanups (cleanups); +} + /* Reset a breakpoint given it's struct breakpoint * BINT. The value we return ends up being the return value from catch_errors. Unused in this case. */ @@ -9977,16 +11078,8 @@ update_breakpoint_locations (struct breakpoint *b, static int breakpoint_re_set_one (void *bint) { - /* get past catch_errs */ + /* Get past catch_errs. */ struct breakpoint *b = (struct breakpoint *) bint; - int not_found = 0; - int *not_found_ptr = ¬_found; - struct symtabs_and_lines sals = {0}; - struct symtabs_and_lines expanded = {0}; - char *s; - struct gdb_exception e; - struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); - int marker_spec = 0; switch (b->type) { @@ -9999,127 +11092,48 @@ breakpoint_re_set_one (void *bint) case bp_tracepoint: case bp_fast_tracepoint: case bp_static_tracepoint: + case bp_gnu_ifunc_resolver: /* Do not attempt to re-set breakpoints disabled during startup. */ if (b->enable_state == bp_startup_disabled) return 0; if (b->addr_string == NULL) { - /* Anything without a string can't be re-set. */ + /* Anything without a string can't be re-set. */ delete_breakpoint (b); return 0; } - input_radix = b->input_radix; - s = b->addr_string; - - save_current_space_and_thread (); - switch_to_program_space_and_thread (b->pspace); - - marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s); - - set_language (b->language); - TRY_CATCH (e, RETURN_MASK_ERROR) - { - if (marker_spec) - { - sals = decode_static_tracepoint_spec (&s); - if (sals.nelts > b->static_trace_marker_id_idx) - { - sals.sals[0] = sals.sals[b->static_trace_marker_id_idx]; - sals.nelts = 1; - } - else - error (_("marker %s not found"), b->static_trace_marker_id); - } - else - sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, - not_found_ptr); - } - if (e.reason < 0) - { - int not_found_and_ok = 0; - /* For pending breakpoints, it's expected that parsing - will fail until the right shared library is loaded. - User has already told to create pending breakpoints and - don't need extra messages. If breakpoint is in bp_shlib_disabled - state, then user already saw the message about that breakpoint - being disabled, and don't want to see more errors. */ - if (not_found - && (b->condition_not_parsed - || (b->loc && b->loc->shlib_disabled) - || b->enable_state == bp_disabled)) - not_found_and_ok = 1; - - if (!not_found_and_ok) - { - /* We surely don't want to warn about the same breakpoint - 10 times. One solution, implemented here, is disable - the breakpoint on error. Another solution would be to - have separate 'warning emitted' flag. Since this - happens only when a binary has changed, I don't know - which approach is better. */ - b->enable_state = bp_disabled; - throw_exception (e); - } - } - - if (!not_found) - { - gdb_assert (sals.nelts == 1); - - resolve_sal_pc (&sals.sals[0]); - if (b->condition_not_parsed && s && s[0]) - { - char *cond_string = 0; - int thread = -1; - int task = 0; - - find_condition_and_thread (s, sals.sals[0].pc, - &cond_string, &thread, &task); - if (cond_string) - b->cond_string = cond_string; - b->thread = thread; - b->task = task; - b->condition_not_parsed = 0; - } - - if (b->type == bp_static_tracepoint && !marker_spec) - sals.sals[0] = update_static_tracepoint (b, sals.sals[0]); - - expanded = expand_line_sal_maybe (sals.sals[0]); - } - - make_cleanup (xfree, sals.sals); - update_breakpoint_locations (b, expanded); + re_set_breakpoint (b); break; case bp_watchpoint: case bp_hardware_watchpoint: case bp_read_watchpoint: case bp_access_watchpoint: - /* Watchpoint can be either on expression using entirely global variables, - or it can be on local variables. - - Watchpoints of the first kind are never auto-deleted, and even persist - across program restarts. Since they can use variables from shared - libraries, we need to reparse expression as libraries are loaded - and unloaded. - - Watchpoints on local variables can also change meaning as result - of solib event. For example, if a watchpoint uses both a local and - a global variables in expression, it's a local watchpoint, but - unloading of a shared library will make the expression invalid. - This is not a very common use case, but we still re-evaluate - expression, to avoid surprises to the user. + /* Watchpoint can be either on expression using entirely global + variables, or it can be on local variables. + + Watchpoints of the first kind are never auto-deleted, and + even persist across program restarts. Since they can use + variables from shared libraries, we need to reparse + expression as libraries are loaded and unloaded. + + Watchpoints on local variables can also change meaning as + result of solib event. For example, if a watchpoint uses + both a local and a global variables in expression, it's a + local watchpoint, but unloading of a shared library will make + the expression invalid. This is not a very common use case, + but we still re-evaluate expression, to avoid surprises to + the user. Note that for local watchpoints, we re-evaluate it only if watchpoints frame id is still valid. If it's not, it means - the watchpoint is out of scope and will be deleted soon. In fact, - I'm not sure we'll ever be called in this case. + the watchpoint is out of scope and will be deleted soon. In + fact, I'm not sure we'll ever be called in this case. If a local watchpoint's frame id is still valid, then - b->exp_valid_block is likewise valid, and we can safely use it. + b->exp_valid_block is likewise valid, and we can safely use it. Don't do anything about disabled watchpoints, since they will be reevaluated again when enabled. */ @@ -10127,7 +11141,7 @@ breakpoint_re_set_one (void *bint) break; /* We needn't really do anything to reset these, since the mask that requests them is unaffected by e.g., new libraries being - loaded. */ + loaded. */ case bp_catchpoint: break; @@ -10139,6 +11153,7 @@ breakpoint_re_set_one (void *bint) case bp_overlay_event: case bp_longjmp_master: case bp_std_terminate_master: + case bp_exception_master: delete_breakpoint (b); break; @@ -10150,10 +11165,11 @@ breakpoint_re_set_one (void *bint) Once it is set up, we do not want to touch it. */ case bp_thread_event: - /* Keep temporary breakpoints, which can be encountered when we step - over a dlopen call and SOLIB_ADD is resetting the breakpoints. - Otherwise these should have been blown away via the cleanup chain - or by breakpoint_init_inferior when we rerun the executable. */ + /* Keep temporary breakpoints, which can be encountered when we + step over a dlopen call and SOLIB_ADD is resetting the + breakpoints. Otherwise these should have been blown away via + the cleanup chain or by breakpoint_init_inferior when we + rerun the executable. */ case bp_until: case bp_finish: case bp_watchpoint_scope: @@ -10162,11 +11178,13 @@ breakpoint_re_set_one (void *bint) case bp_step_resume: case bp_longjmp: case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: case bp_jit_event: + case bp_gnu_ifunc_resolver_return: break; } - do_cleanups (cleanups); return 0; } @@ -10174,7 +11192,7 @@ breakpoint_re_set_one (void *bint) void breakpoint_re_set (void) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; enum language save_language; int save_input_radix; struct cleanup *old_chain; @@ -10183,9 +11201,9 @@ breakpoint_re_set (void) save_input_radix = input_radix; old_chain = save_current_program_space (); - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { - /* Format possible error msg */ + /* Format possible error msg. */ char *message = xstrprintf ("Error in re-setting breakpoint %d: ", b->number); struct cleanup *cleanups = make_cleanup (xfree, message); @@ -10199,18 +11217,16 @@ breakpoint_re_set (void) do_cleanups (old_chain); - create_overlay_event_breakpoint ("_ovly_debug_event"); - create_longjmp_master_breakpoint ("longjmp"); - create_longjmp_master_breakpoint ("_longjmp"); - create_longjmp_master_breakpoint ("siglongjmp"); - create_longjmp_master_breakpoint ("_siglongjmp"); - create_std_terminate_master_breakpoint ("std::terminate()"); + create_overlay_event_breakpoint (); + create_longjmp_master_breakpoint (); + create_std_terminate_master_breakpoint (); + create_exception_master_breakpoint (); } /* Reset the thread number of this breakpoint: - If the breakpoint is for all threads, leave it as-is. - - Else, reset it to the current thread for inferior_ptid. */ + - Else, reset it to the current thread for inferior_ptid. */ void breakpoint_re_set_thread (struct breakpoint *b) { @@ -10254,13 +11270,15 @@ set_ignore_count (int bptnum, int count, int from_tty) if (from_tty) { if (count == 0) - printf_filtered (_("Will stop next time breakpoint %d is reached."), + printf_filtered (_("Will stop next time " + "breakpoint %d is reached."), bptnum); else if (count == 1) printf_filtered (_("Will ignore next crossing of breakpoint %d."), bptnum); else - printf_filtered (_("Will ignore next %d crossings of breakpoint %d."), + printf_filtered (_("Will ignore next %d " + "crossings of breakpoint %d."), count, bptnum); } breakpoints_changed (); @@ -10271,13 +11289,6 @@ set_ignore_count (int bptnum, int count, int from_tty) error (_("No breakpoint number %d."), bptnum); } -void -make_breakpoint_silent (struct breakpoint *b) -{ - /* Silence the breakpoint. */ - b->silent = 1; -} - /* Command to set ignore-count of breakpoint N to COUNT. */ static void @@ -10310,21 +11321,23 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, void *), void *data) { - char *p = args; - char *p1; int num; struct breakpoint *b, *tmp; int match; + struct get_number_or_range_state state; - if (p == 0) + if (args == 0) error_no_arg (_("one or more breakpoint numbers")); - while (*p) + init_number_or_range (&state, args); + + while (!state.finished) { + char *p = state.string; + match = 0; - p1 = p; - num = get_number_or_range (&p1); + num = get_number_or_range (&state); if (num == 0) { warning (_("bad breakpoint number at or near '%s'"), p); @@ -10334,17 +11347,30 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, ALL_BREAKPOINTS_SAFE (b, tmp) if (b->number == num) { - struct breakpoint *related_breakpoint = b->related_breakpoint; + struct breakpoint *related_breakpoint; + match = 1; - function (b, data); - if (related_breakpoint) - function (related_breakpoint, data); + related_breakpoint = b; + do + { + struct breakpoint *next_related_b; + + /* FUNCTION can be also delete_breakpoint. */ + next_related_b = related_breakpoint->related_breakpoint; + function (related_breakpoint, data); + + /* For delete_breakpoint of the last entry of the ring we + were traversing we would never get back to B. */ + if (next_related_b == related_breakpoint) + break; + related_breakpoint = next_related_b; + } + while (related_breakpoint != b); break; } if (match == 0) printf_unfiltered (_("No breakpoint number %d.\n"), num); } - p = p1; } } @@ -10361,7 +11387,7 @@ find_location_by_number (char *number) *dot = '\0'; p1 = number; - bp_num = get_number_or_range (&p1); + bp_num = get_number (&p1); if (bp_num == 0) error (_("Bad breakpoint number '%s'"), number); @@ -10375,7 +11401,7 @@ find_location_by_number (char *number) error (_("Bad breakpoint number '%s'"), number); p1 = dot+1; - loc_num = get_number_or_range (&p1); + loc_num = get_number (&p1); if (loc_num == 0) error (_("Bad breakpoint location number '%s'"), number); @@ -10435,7 +11461,7 @@ disable_command (char *args, int from_tty) case bp_none: warning (_("attempted to disable apparently deleted breakpoint #%d?"), bpt->number); - continue; + break; case bp_breakpoint: case bp_tracepoint: case bp_fast_tracepoint: @@ -10447,8 +11473,9 @@ disable_command (char *args, int from_tty) case bp_read_watchpoint: case bp_access_watchpoint: disable_breakpoint (bpt); + break; default: - continue; + break; } else if (strchr (args, '.')) { @@ -10536,7 +11563,7 @@ enable_command (char *args, int from_tty) case bp_none: warning (_("attempted to enable apparently deleted breakpoint #%d?"), bpt->number); - continue; + break; case bp_breakpoint: case bp_tracepoint: case bp_fast_tracepoint: @@ -10548,8 +11575,9 @@ enable_command (char *args, int from_tty) case bp_read_watchpoint: case bp_access_watchpoint: enable_breakpoint (bpt); + break; default: - continue; + break; } else if (strchr (args, '.')) { @@ -10638,10 +11666,10 @@ decode_line_spec_1 (char *string, int funfirstline) sals = decode_line_1 (&string, funfirstline, default_breakpoint_symtab, default_breakpoint_line, - (char ***) NULL, NULL); + NULL); else sals = decode_line_1 (&string, funfirstline, - (struct symtab *) NULL, 0, (char ***) NULL, NULL); + (struct symtab *) NULL, 0, NULL); if (*string) error (_("Junk at end of line specification: %s"), string); return sals; @@ -10674,7 +11702,8 @@ deprecated_insert_raw_breakpoint (struct gdbarch *gdbarch, return bp_tgt; } -/* Remove a breakpoint BP inserted by deprecated_insert_raw_breakpoint. */ +/* Remove a breakpoint BP inserted by + deprecated_insert_raw_breakpoint. */ int deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) @@ -10688,7 +11717,8 @@ deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) return ret; } -/* One (or perhaps two) breakpoints used for software single stepping. */ +/* One (or perhaps two) breakpoints used for software single + stepping. */ static void *single_step_breakpoints[2]; static struct gdbarch *single_step_gdbarch[2]; @@ -10697,7 +11727,8 @@ static struct gdbarch *single_step_gdbarch[2]; void insert_single_step_breakpoint (struct gdbarch *gdbarch, - struct address_space *aspace, CORE_ADDR next_pc) + struct address_space *aspace, + CORE_ADDR next_pc) { void **bpt_p; @@ -10713,12 +11744,12 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch, single_step_gdbarch[1] = gdbarch; } - /* NOTE drow/2006-04-11: A future improvement to this function would be - to only create the breakpoints once, and actually put them on the - breakpoint chain. That would let us use set_raw_breakpoint. We could - adjust the addresses each time they were needed. Doing this requires - corresponding changes elsewhere where single step breakpoints are - handled, however. So, for now, we use this. */ + /* NOTE drow/2006-04-11: A future improvement to this function would + be to only create the breakpoints once, and actually put them on + the breakpoint chain. That would let us use set_raw_breakpoint. + We could adjust the addresses each time they were needed. Doing + this requires corresponding changes elsewhere where single step + breakpoints are handled, however. So, for now, we use this. */ *bpt_p = deprecated_insert_raw_breakpoint (gdbarch, aspace, next_pc); if (*bpt_p == NULL) @@ -10726,6 +11757,16 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch, paddress (gdbarch, next_pc)); } +/* Check if the breakpoints used for software single stepping + were inserted or not. */ + +int +single_step_breakpoints_inserted (void) +{ + return (single_step_breakpoints[0] != NULL + || single_step_breakpoints[1] != NULL); +} + /* Remove and delete any breakpoints used for software single step. */ void @@ -10782,7 +11823,8 @@ detach_single_step_breakpoints (void) single_step_breakpoints[i]); } -/* Check whether a software single-step breakpoint is inserted at PC. */ +/* Check whether a software single-step breakpoint is inserted at + PC. */ static int single_step_breakpoint_inserted_here_p (struct address_space *aspace, @@ -10854,8 +11896,11 @@ catch_syscall_completer (struct cmd_list_element *cmd, char *text, char *word) { const char **list = get_syscall_names (); + char **retlist + = (list == NULL) ? NULL : complete_on_enum (list, text, word); - return (list == NULL) ? NULL : complete_on_enum (list, text, word); + xfree (list); + return retlist; } /* Tracepoint-specific operations. */ @@ -10880,7 +11925,8 @@ trace_command (char *arg, int from_tty) pending_break_support, NULL, from_tty, - 1 /* enabled */)) + 1 /* enabled */, + 0 /* internal */)) set_tracepoint_count (breakpoint_count); } @@ -10896,7 +11942,8 @@ ftrace_command (char *arg, int from_tty) pending_break_support, NULL, from_tty, - 1 /* enabled */)) + 1 /* enabled */, + 0 /* internal */)) set_tracepoint_count (breakpoint_count); } @@ -10914,7 +11961,8 @@ strace_command (char *arg, int from_tty) pending_break_support, NULL, from_tty, - 1 /* enabled */)) + 1 /* enabled */, + 0 /* internal */)) set_tracepoint_count (breakpoint_count); } @@ -10956,7 +12004,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) address. Since there is no way to confirm that the address means the same thing as when the trace was started, warn the user. */ - warning (_("Uploaded tracepoint %d has no source location, using raw address"), + warning (_("Uploaded tracepoint %d has no " + "source location, using raw address"), utp->number); sprintf (small_buf, "*%s", hex_string (utp->addr)); addr_str = small_buf; @@ -10964,7 +12013,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) /* There's not much we can do with a sequence of bytecodes. */ if (utp->cond && !utp->cond_string) - warning (_("Uploaded tracepoint %d condition has no source form, ignoring it"), + warning (_("Uploaded tracepoint %d condition " + "has no source form, ignoring it"), utp->number); if (!create_breakpoint (get_current_arch (), @@ -10976,7 +12026,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) pending_break_support, NULL, 0 /* from_tty */, - utp->enabled /* enabled */)) + utp->enabled /* enabled */, + 0 /* internal */)) return NULL; set_tracepoint_count (breakpoint_count); @@ -11009,7 +12060,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) } else if (!VEC_empty (char_ptr, utp->actions) || !VEC_empty (char_ptr, utp->step_actions)) - warning (_("Uploaded tracepoint %d actions have no source form, ignoring them"), + warning (_("Uploaded tracepoint %d actions " + "have no source form, ignoring them"), utp->number); return tp; @@ -11019,27 +12071,24 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) omitted. */ static void -tracepoints_info (char *tpnum_exp, int from_tty) +tracepoints_info (char *args, int from_tty) { - int tpnum = -1, num_printed; - - if (tpnum_exp) - tpnum = parse_and_eval_long (tpnum_exp); + int num_printed; - num_printed = breakpoint_1 (tpnum, 0, is_tracepoint); + num_printed = breakpoint_1 (args, 0, is_tracepoint); if (num_printed == 0) { - if (tpnum == -1) + if (args == NULL || *args == '\0') ui_out_message (uiout, 0, "No tracepoints.\n"); else - ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum); + ui_out_message (uiout, 0, "No tracepoint matching '%s'.\n", args); } default_collect_info (); } -/* The 'enable trace' command enables tracepoints. +/* The 'enable trace' command enables tracepoints. Not supported by all targets. */ static void enable_trace_command (char *args, int from_tty) @@ -11047,7 +12096,7 @@ enable_trace_command (char *args, int from_tty) enable_command (args, from_tty); } -/* The 'disable trace' command disables tracepoints. +/* The 'disable trace' command disables tracepoints. Not supported by all targets. */ static void disable_trace_command (char *args, int from_tty) @@ -11055,11 +12104,11 @@ disable_trace_command (char *args, int from_tty) disable_command (args, from_tty); } -/* Remove a tracepoint (or all if no argument) */ +/* Remove a tracepoint (or all if no argument). */ static void delete_trace_command (char *arg, int from_tty) { - struct breakpoint *b, *temp; + struct breakpoint *b, *b_tmp; dont_repeat (); @@ -11069,7 +12118,8 @@ delete_trace_command (char *arg, int from_tty) /* Delete all breakpoints if no argument. Do not delete internal or call-dummy breakpoints, these - have to be deleted with an explicit breakpoint number argument. */ + have to be deleted with an explicit breakpoint number + argument. */ ALL_TRACEPOINTS (b) { if (b->number >= 0) @@ -11083,7 +12133,7 @@ delete_trace_command (char *arg, int from_tty) if (!from_tty || (breaks_to_delete && query (_("Delete all tracepoints? ")))) { - ALL_BREAKPOINTS_SAFE (b, temp) + ALL_BREAKPOINTS_SAFE (b, b_tmp) { if (is_tracepoint (b) && b->number >= 0) @@ -11095,6 +12145,18 @@ delete_trace_command (char *arg, int from_tty) map_breakpoint_numbers (arg, do_delete_breakpoint, NULL); } +/* Helper function for trace_pass_command. */ + +static void +trace_pass_set_count (struct breakpoint *bp, int count, int from_tty) +{ + bp->pass_count = count; + observer_notify_tracepoint_modified (bp->number); + if (from_tty) + printf_filtered (_("Setting tracepoint %d's passcount to %d\n"), + bp->number, count); +} + /* Set passcount for tracepoint. First command argument is passcount, second is tracepoint number. @@ -11104,14 +12166,14 @@ delete_trace_command (char *arg, int from_tty) static void trace_pass_command (char *args, int from_tty) { - struct breakpoint *t1 = (struct breakpoint *) -1, *t2; + struct breakpoint *t1; unsigned int count; - int all = 0; if (args == 0 || *args == 0) - error (_("passcount command requires an argument (count + optional TP num)")); + error (_("passcount command requires an " + "argument (count + optional TP num)")); - count = strtoul (args, &args, 10); /* Count comes first, then TP num. */ + count = strtoul (args, &args, 10); /* Count comes first, then TP num. */ while (*args && isspace ((int) *args)) args++; @@ -11119,31 +12181,32 @@ trace_pass_command (char *args, int from_tty) if (*args && strncasecmp (args, "all", 3) == 0) { args += 3; /* Skip special argument "all". */ - all = 1; if (*args) error (_("Junk at end of arguments.")); - } - else - t1 = get_tracepoint_by_number (&args, 1, 1); - do + ALL_TRACEPOINTS (t1) + { + trace_pass_set_count (t1, count, from_tty); + } + } + else if (*args == '\0') { + t1 = get_tracepoint_by_number (&args, NULL, 1); if (t1) + trace_pass_set_count (t1, count, from_tty); + } + else + { + struct get_number_or_range_state state; + + init_number_or_range (&state, args); + while (!state.finished) { - ALL_TRACEPOINTS (t2) - if (t1 == (struct breakpoint *) -1 || t1 == t2) - { - t2->pass_count = count; - observer_notify_tracepoint_modified (t2->number); - if (from_tty) - printf_filtered (_("Setting tracepoint %d's passcount to %d\n"), - t2->number, count); - } - if (! all && *args) - t1 = get_tracepoint_by_number (&args, 1, 0); + t1 = get_tracepoint_by_number (&args, &state, 1); + if (t1) + trace_pass_set_count (t1, count, from_tty); } } - while (*args); } struct breakpoint * @@ -11175,18 +12238,25 @@ get_tracepoint_by_number_on_target (int num) } /* Utility: parse a tracepoint number and look it up in the list. - If MULTI_P is true, there might be a range of tracepoints in ARG. - if OPTIONAL_P is true, then if the argument is missing, the most + If STATE is not NULL, use, get_number_or_range_state and ignore ARG. + If OPTIONAL_P is true, then if the argument is missing, the most recent tracepoint (tracepoint_count) is returned. */ struct breakpoint * -get_tracepoint_by_number (char **arg, int multi_p, int optional_p) +get_tracepoint_by_number (char **arg, + struct get_number_or_range_state *state, + int optional_p) { extern int tracepoint_count; struct breakpoint *t; int tpnum; char *instring = arg == NULL ? NULL : *arg; - if (arg == NULL || *arg == NULL || ! **arg) + if (state) + { + gdb_assert (!state->finished); + tpnum = get_number_or_range (state); + } + else if (arg == NULL || *arg == NULL || ! **arg) { if (optional_p) tpnum = tracepoint_count; @@ -11194,7 +12264,7 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p) error_no_arg (_("tracepoint number")); } else - tpnum = multi_p ? get_number_or_range (arg) : get_number (arg); + tpnum = get_number (arg); if (tpnum <= 0) { @@ -11202,7 +12272,8 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p) printf_filtered (_("bad tracepoint number at or near '%s'\n"), instring); else - printf_filtered (_("Tracepoint argument missing and no previous tracepoint\n")); + printf_filtered (_("Tracepoint argument missing " + "and no previous tracepoint\n")); return NULL; } @@ -11212,9 +12283,6 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p) return t; } - /* FIXME: if we are in the middle of a range we don't want to give - a message. The current interface to get_number_or_range doesn't - allow us to discover this. */ printf_unfiltered ("No tracepoint number %d.\n", tpnum); return NULL; } @@ -11242,7 +12310,7 @@ save_breakpoints (char *filename, int from_tty, ALL_BREAKPOINTS (tp) { /* Skip internal and momentary breakpoints. */ - if (!user_settable_breakpoint (tp)) + if (!user_breakpoint_p (tp)) continue; /* If we have a filter, only save the breakpoints it accepts. */ @@ -11280,14 +12348,14 @@ save_breakpoints (char *filename, int from_tty, ALL_BREAKPOINTS (tp) { /* Skip internal and momentary breakpoints. */ - if (!user_settable_breakpoint (tp)) + if (!user_breakpoint_p (tp)) continue; /* If we have a filter, only save the breakpoints it accepts. */ if (filter && !filter (tp)) continue; - if (tp->ops != NULL) + if (tp->ops != NULL && tp->ops->print_recreate != NULL) (tp->ops->print_recreate) (tp, fp); else { @@ -11359,7 +12427,7 @@ save_breakpoints (char *filename, int from_tty, fprintf_unfiltered (fp, " commands\n"); ui_out_redirect (uiout, fp); - TRY_CATCH (ex, RETURN_MASK_ERROR) + TRY_CATCH (ex, RETURN_MASK_ALL) { print_command_lines (uiout, tp->commands->commands, 2); } @@ -11415,7 +12483,7 @@ save_tracepoints_command (char *args, int from_tty) /* Create a vector of all tracepoints. */ VEC(breakpoint_p) * -all_tracepoints () +all_tracepoints (void) { VEC(breakpoint_p) *tp_vec = 0; struct breakpoint *tp; @@ -11429,9 +12497,10 @@ all_tracepoints () } -/* This help string is used for the break, hbreak, tbreak and thbreak commands. - It is defined as a macro to prevent duplication. - COMMAND should be a string constant containing the name of the command. */ +/* This help string is used for the break, hbreak, tbreak and thbreak + commands. It is defined as a macro to prevent duplication. + COMMAND should be a string constant containing the name of the + command. */ #define BREAK_ARGS_HELP(command) \ command" [LOCATION] [thread THREADNUM] [if CONDITION]\n\ LOCATION may be a line number, function name, or \"*\" and an address.\n\ @@ -11492,11 +12561,26 @@ clear_syscall_counts (struct inferior *inf) static void save_command (char *arg, int from_tty) { - printf_unfiltered (_("\ -\"save\" must be followed by the name of a save subcommand.\n")); + printf_unfiltered (_("\"save\" must be followed by " + "the name of a save subcommand.\n")); help_list (save_cmdlist, "save ", -1, gdb_stdout); } +struct breakpoint * +iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *), + void *data) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + { + if ((*callback) (b, data)) + return b; + } + + return NULL; +} + void _initialize_breakpoint (void) { @@ -11506,6 +12590,8 @@ _initialize_breakpoint (void) observer_attach_inferior_exit (clear_syscall_counts); observer_attach_memory_changed (invalidate_bp_value_on_memory_change); + breakpoint_objfile_key = register_objfile_data (); + breakpoint_chain = 0; /* Don't bother to call set_breakpoint_count. $bpnum isn't useful before a breakpoint is set. */ @@ -11543,7 +12629,7 @@ BREAK_ARGS_HELP ("tbreak"))); set_cmd_completer (c, location_completer); c = add_com ("hbreak", class_breakpoint, hbreak_command, _("\ -Set a hardware assisted breakpoint.\n\ +Set a hardware assisted breakpoint.\n\ Like \"break\" except the breakpoint requires hardware support,\n\ some target hardware may not have this support.\n\ \n" @@ -11701,7 +12787,7 @@ breakpoint set.")); } add_info ("breakpoints", breakpoints_info, _("\ -Status of user-settable breakpoints, or breakpoint number NUMBER.\n\ +Status of specified breakpoints (all user-settable breakpoints if no argument).\n\ The \"Type\" column indicates one of:\n\ \tbreakpoint - normal breakpoint\n\ \twatchpoint - watchpoint\n\ @@ -11823,26 +12909,33 @@ With an argument, catch only exceptions with the given name."), c = add_com ("watch", class_breakpoint, watch_command, _("\ Set a watchpoint for an expression.\n\ +Usage: watch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression changes.")); +an expression changes.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\ Set a read watchpoint for an expression.\n\ +Usage: rwatch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression is read.")); +an expression is read.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); c = add_com ("awatch", class_breakpoint, awatch_command, _("\ Set a watchpoint for an expression.\n\ +Usage: awatch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression is either read or written.")); +an expression is either read or written.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); add_info ("watchpoints", watchpoints_info, _("\ -Status of watchpoints, or watchpoint number NUMBER.")); - - +Status of specified watchpoints (all watchpoints if no argument).")); /* XXX: cagney/2005-02-23: This should be a boolean, and should respond to changes - contrary to the description. */ @@ -11908,7 +13001,7 @@ Do \"help tracepoints\" for info on other tracepoint commands.")); set_cmd_completer (c, location_completer); add_info ("tracepoints", tracepoints_info, _("\ -Status of tracepoints, or tracepoint number NUMBER.\n\ +Status of specified tracepoints (all tracepoints if no argument).\n\ Convenience variable \"$tpnum\" contains the number of the\n\ last tracepoint set.")); @@ -12018,7 +13111,23 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."), &show_always_inserted_mode, &breakpoint_set_cmdlist, &breakpoint_show_cmdlist); - + + add_com ("break-range", class_breakpoint, break_range_command, _("\ +Set a breakpoint for an address range.\n\ +break-range START-LOCATION, END-LOCATION\n\ +where START-LOCATION and END-LOCATION can be one of the following:\n\ + LINENUM, for that line in the current file,\n\ + FILE:LINENUM, for that line in that file,\n\ + +OFFSET, for that number of lines after the current line\n\ + or the start of the range\n\ + FUNCTION, for the first line in that function,\n\ + FILE:FUNCTION, to distinguish among like-named static functions.\n\ + *ADDRESS, for the instruction at that address.\n\ +\n\ +The breakpoint will stop execution of the inferior whenever it executes\n\ +an instruction at any address within the [START-LOCATION, END-LOCATION]\n\ +range (including START-LOCATION and END-LOCATION).")); + automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed); diff --git a/contrib/gdb-7/gdb/breakpoint.h b/contrib/gdb-7/gdb/breakpoint.h index 6f5d050d4a..7a9c2d4729 100644 --- a/contrib/gdb-7/gdb/breakpoint.h +++ b/contrib/gdb-7/gdb/breakpoint.h @@ -1,6 +1,7 @@ /* Data structures associated with breakpoints in GDB. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -26,25 +27,28 @@ struct value; struct block; +struct breakpoint_object; +struct get_number_or_range_state; -/* This is the maximum number of bytes a breakpoint instruction can take. - Feel free to increase it. It's just used in a few places to size - arrays that should be independent of the target architecture. */ +/* This is the maximum number of bytes a breakpoint instruction can + take. Feel free to increase it. It's just used in a few places to + size arrays that should be independent of the target + architecture. */ #define BREAKPOINT_MAX 16 /* Type of breakpoint. */ -/* FIXME In the future, we should fold all other breakpoint-like things into - here. This includes: +/* FIXME In the future, we should fold all other breakpoint-like + things into here. This includes: - * single-step (for machines where we have to simulate single stepping) - (probably, though perhaps it is better for it to look as much as - possible like a single-step to wait_for_inferior). */ + * single-step (for machines where we have to simulate single + stepping) (probably, though perhaps it is better for it to look as + much as possible like a single-step to wait_for_inferior). */ enum bptype { - bp_none = 0, /* Eventpoint has been deleted. */ + bp_none = 0, /* Eventpoint has been deleted */ bp_breakpoint, /* Normal breakpoint */ bp_hardware_breakpoint, /* Hardware assisted breakpoint */ bp_until, /* used by until command */ @@ -56,8 +60,16 @@ enum bptype bp_longjmp, /* secret breakpoint to find longjmp() */ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */ - /* Used by wait_for_inferior for stepping over subroutine calls, for - stepping over signal handlers, and for skipping prologues. */ + /* An internal breakpoint that is installed on the unwinder's + debug hook. */ + bp_exception, + /* An internal breakpoint that is set at the point where an + exception will land. */ + bp_exception_resume, + + /* Used by wait_for_inferior for stepping over subroutine calls, + for stepping over signal handlers, and for skipping + prologues. */ bp_step_resume, /* Used to detect when a watchpoint expression has gone out of @@ -75,12 +87,13 @@ enum bptype bp_watchpoint_scope, /* The breakpoint at the end of a call dummy. */ - /* FIXME: What if the function we are calling longjmp()s out of the - call, or the user gets out with the "return" command? We currently - have no way of cleaning up the breakpoint in these (obscure) situations. - (Probably can solve this by noticing longjmp, "return", etc., it's - similar to noticing when a watchpoint on a local variable goes out - of scope (with hardware support for watchpoints)). */ + /* FIXME: What if the function we are calling longjmp()s out of + the call, or the user gets out with the "return" command? We + currently have no way of cleaning up the breakpoint in these + (obscure) situations. (Probably can solve this by noticing + longjmp, "return", etc., it's similar to noticing when a + watchpoint on a local variable goes out of scope (with hardware + support for watchpoints)). */ bp_call_dummy, /* A breakpoint set on std::terminate, that is used to catch @@ -125,6 +138,9 @@ enum bptype /* Master copies of std::terminate breakpoints. */ bp_std_terminate_master, + /* Like bp_longjmp_master, but for exceptions. */ + bp_exception_master, + bp_catchpoint, bp_tracepoint, @@ -133,41 +149,61 @@ enum bptype /* Event for JIT compiled code generation or deletion. */ bp_jit_event, + + /* Breakpoint is placed at the STT_GNU_IFUNC resolver. When hit GDB + inserts new bp_gnu_ifunc_resolver_return at the caller. + bp_gnu_ifunc_resolver is still being kept here as a different thread + may still hit it before bp_gnu_ifunc_resolver_return is hit by the + original thread. */ + bp_gnu_ifunc_resolver, + + /* On its hit GDB now know the resolved address of the target + STT_GNU_IFUNC function. Associated bp_gnu_ifunc_resolver can be + deleted now and the breakpoint moved to the target function entry + point. */ + bp_gnu_ifunc_resolver_return, }; -/* States of enablement of breakpoint. */ +/* States of enablement of breakpoint. */ enum enable_state { - bp_disabled, /* The eventpoint is inactive, and cannot trigger. */ - bp_enabled, /* The eventpoint is active, and can trigger. */ - bp_call_disabled, /* The eventpoint has been disabled while a call - into the inferior is "in flight", because some - eventpoints interfere with the implementation of - a call on some targets. The eventpoint will be - automatically enabled and reset when the call - "lands" (either completes, or stops at another - eventpoint). */ - bp_startup_disabled,/* The eventpoint has been disabled during inferior - startup. This is necessary on some targets where - the main executable will get relocated during - startup, making breakpoint addresses invalid. - The eventpoint will be automatically enabled and - reset once inferior startup is complete. */ - bp_permanent /* There is a breakpoint instruction hard-wired into - the target's code. Don't try to write another - breakpoint instruction on top of it, or restore - its value. Step over it using the architecture's - SKIP_INSN macro. */ + bp_disabled, /* The eventpoint is inactive, and cannot + trigger. */ + bp_enabled, /* The eventpoint is active, and can + trigger. */ + bp_call_disabled, /* The eventpoint has been disabled while a + call into the inferior is "in flight", + because some eventpoints interfere with + the implementation of a call on some + targets. The eventpoint will be + automatically enabled and reset when the + call "lands" (either completes, or stops + at another eventpoint). */ + bp_startup_disabled, /* The eventpoint has been disabled during + inferior startup. This is necessary on + some targets where the main executable + will get relocated during startup, making + breakpoint addresses invalid. The + eventpoint will be automatically enabled + and reset once inferior startup is + complete. */ + bp_permanent /* There is a breakpoint instruction + hard-wired into the target's code. Don't + try to write another breakpoint + instruction on top of it, or restore its + value. Step over it using the + architecture's SKIP_INSN macro. */ }; -/* Disposition of breakpoint. Ie: what to do after hitting it. */ +/* Disposition of breakpoint. Ie: what to do after hitting it. */ enum bpdisp { disp_del, /* Delete it */ - disp_del_at_next_stop, /* Delete at next stop, whether hit or not */ + disp_del_at_next_stop, /* Delete at next stop, + whether hit or not */ disp_disable, /* Disable it */ disp_donttouch /* Leave it alone */ }; @@ -195,6 +231,10 @@ struct bp_target_info is used to determine the type of breakpoint to insert. */ CORE_ADDR placed_address; + /* If this is a ranged breakpoint, then this field contains the + length of the range that will be watched for execution. */ + int length; + /* If the breakpoint lives in memory and reading that memory would give back the breakpoint, instead of the original contents, then the original contents are cached here. Only SHADOW_LEN bytes of @@ -205,11 +245,11 @@ struct bp_target_info int shadow_len; /* The size of the placed breakpoint, according to - gdbarch_breakpoint_from_pc, when the breakpoint was inserted. This is - generally the same as SHADOW_LEN, unless we did not need + gdbarch_breakpoint_from_pc, when the breakpoint was inserted. + This is generally the same as SHADOW_LEN, unless we did not need to read from the target to implement the memory breakpoint - (e.g. if a remote stub handled the details). We may still - need the size to remove the breakpoint safely. */ + (e.g. if a remote stub handled the details). We may still need + the size to remove the breakpoint safely. */ int placed_size; }; @@ -240,13 +280,18 @@ struct bp_location the same parent breakpoint. */ struct bp_location *next; + /* The reference count. */ + int refc; + /* Type of this breakpoint location. */ enum bp_loc_type loc_type; /* Each breakpoint location must belong to exactly one higher-level - breakpoint. This and the DUPLICATE flag are more straightforward - than reference counting. This pointer is NULL iff this bp_location is in - (and therefore only in) moribund_locations. */ + breakpoint. This pointer is NULL iff this bp_location is no + longer attached to a breakpoint. For example, when a breakpoint + is deleted, its locations may still be found in the + moribund_locations list, or if we had stopped for it, in + bpstats. */ struct breakpoint *owner; /* Conditional. Break only if this expression's value is nonzero. @@ -297,14 +342,17 @@ struct bp_location bp_loc_other. */ CORE_ADDR address; - /* For hardware watchpoints, the size of data ad ADDRESS being watches. */ + /* For hardware watchpoints, the size of the memory region being + watched. For hardware ranged breakpoints, the size of the + breakpoint range. */ int length; - /* Type of hardware watchpoint. */ + /* Type of hardware watchpoint. */ enum target_hw_bp_type watchpoint_type; /* For any breakpoint type with an address, this is the section - associated with the address. Used primarily for overlay debugging. */ + associated with the address. Used primarily for overlay + debugging. */ struct obj_section *section; /* Address at which breakpoint was requested, either by the user or @@ -339,30 +387,53 @@ struct bp_location will be called instead of the performing the default action for this bptype. */ -struct breakpoint_ops +struct breakpoint_ops { - /* Insert the breakpoint or activate the catchpoint. Should raise - an exception if the operation failed. */ - void (*insert) (struct breakpoint *); + /* Insert the breakpoint or watchpoint or activate the catchpoint. + Return 0 for success, 1 if the breakpoint, watchpoint or catchpoint + type is not supported, -1 for failure. */ + int (*insert_location) (struct bp_location *); /* Remove the breakpoint/catchpoint that was previously inserted - with the "insert" method above. Return non-zero if the operation - succeeded. */ - int (*remove) (struct breakpoint *); + with the "insert" method above. Return 0 for success, 1 if the + breakpoint, watchpoint or catchpoint type is not supported, + -1 for failure. */ + int (*remove_location) (struct bp_location *); /* Return non-zero if the debugger should tell the user that this breakpoint was hit. */ - int (*breakpoint_hit) (struct breakpoint *); + int (*breakpoint_hit) (const struct bp_location *, struct address_space *, + CORE_ADDR); + + /* Tell how many hardware resources (debug registers) are needed + for this breakpoint. If this function is not provided, then + the breakpoint or watchpoint needs one debug register. */ + int (*resources_needed) (const struct bp_location *); /* The normal print routine for this breakpoint, called when we hit it. */ enum print_stop_action (*print_it) (struct breakpoint *); - /* Display information about this breakpoint, for "info breakpoints". */ + /* Display information about this breakpoint, for "info + breakpoints". */ void (*print_one) (struct breakpoint *, struct bp_location **); - /* Display information about this breakpoint after setting it (roughly - speaking; this is called from "mention"). */ + /* Display extra information about this breakpoint, below the normal + breakpoint description in "info breakpoints". + + In the example below, the "address range" line was printed + by print_one_detail_ranged_breakpoint. + + (gdb) info breakpoints + Num Type Disp Enb Address What + 2 hw breakpoint keep y in main at test-watch.c:70 + address range: [0x10000458, 0x100004c7] + + */ + void (*print_one_detail) (const struct breakpoint *, struct ui_out *); + + /* Display information about this breakpoint after setting it + (roughly speaking; this is called from "mention"). */ void (*print_mention) (struct breakpoint *); /* Print to FP the CLI command that recreates this breakpoint. */ @@ -393,6 +464,13 @@ DEF_VEC_P(bp_location_p); detail to the breakpoints module. */ struct counted_command_line; +/* Some targets (e.g., embedded PowerPC) need two debug registers to set + a watchpoint over a memory region. If this flag is true, GDB will use + only one register per watchpoint, thus assuming that all acesses that + modify a memory location happen at its starting address. */ + +extern int target_exact_watchpoints; + /* Note that the ->silent field is not currently used by any commands (though the code is in there if it was to be, and set_raw_breakpoint does set it to 0). I implemented it because I thought it would be @@ -404,11 +482,11 @@ struct counted_command_line; struct breakpoint { struct breakpoint *next; - /* Type of breakpoint. */ + /* Type of breakpoint. */ enum bptype type; /* Zero means disabled; remember the info but don't break here. */ enum enable_state enable_state; - /* What to do with this breakpoint after we hit it. */ + /* What to do with this breakpoint after we hit it. */ enum bpdisp disposition; /* Number assigned to distinguish breakpoints. */ int number; @@ -425,12 +503,15 @@ struct breakpoint char *source_file; /* Non-zero means a silent breakpoint (don't print frame info - if we stop here). */ + if we stop here). */ unsigned char silent; + /* Non-zero means display ADDR_STRING to the user verbatim. */ + unsigned char display_canonical; /* Number of stops at this breakpoint that should be continued automatically before really stopping. */ int ignore_count; - /* Chain of command lines to execute when this breakpoint is hit. */ + /* Chain of command lines to execute when this breakpoint is + hit. */ struct counted_command_line *commands; /* Stack depth (address of frame). If nonzero, break only if fp equals this. */ @@ -441,17 +522,25 @@ struct breakpoint /* String we used to set the breakpoint (malloc'd). */ char *addr_string; + + /* For a ranged breakpoint, the string we used to find + the end of the range (malloc'd). */ + char *addr_string_range_end; + /* Architecture we used to set the breakpoint. */ struct gdbarch *gdbarch; /* Language we used to set the breakpoint. */ enum language language; /* Input radix we used to set the breakpoint. */ int input_radix; - /* String form of the breakpoint condition (malloc'd), or NULL if there - is no condition. */ + /* String form of the breakpoint condition (malloc'd), or NULL if + there is no condition. */ char *cond_string; - /* String form of exp (malloc'd), or NULL if none. */ + /* String form of exp to use for displaying to the user + (malloc'd), or NULL if none. */ char *exp_string; + /* String form to use for reparsing of EXP (malloc'd) or NULL. */ + char *exp_string_reparse; /* The expression we are watching, or NULL if not a watchpoint. */ struct expression *exp; @@ -472,9 +561,10 @@ struct breakpoint int val_valid; /* Holds the address of the related watchpoint_scope breakpoint - when using watchpoints on local variables (might the concept - of a related breakpoint be useful elsewhere, if not just call - it the watchpoint_scope breakpoint or something like that. FIXME). */ + when using watchpoints on local variables (might the concept of + a related breakpoint be useful elsewhere, if not just call it + the watchpoint_scope breakpoint or something like that. + FIXME). */ struct breakpoint *related_breakpoint; /* Holds the frame address which identifies the frame this @@ -491,10 +581,12 @@ struct breakpoint hardware. */ enum watchpoint_triggered watchpoint_triggered; - /* Thread number for thread-specific breakpoint, or -1 if don't care. */ + /* Thread number for thread-specific breakpoint, + or -1 if don't care. */ int thread; - /* Ada task number for task-specific breakpoint, or 0 if don't care. */ + /* Ada task number for task-specific breakpoint, + or 0 if don't care. */ int task; /* Count of the number of times this breakpoint was taken, dumped @@ -513,10 +605,10 @@ struct breakpoint triggered. */ char *exec_pathname; - /* Syscall numbers used for the 'catch syscall' feature. - If no syscall has been specified for filtering, its value is NULL. - Otherwise, it holds a list of all syscalls to be caught. - The list elements are allocated with xmalloc. */ + /* Syscall numbers used for the 'catch syscall' feature. If no + syscall has been specified for filtering, its value is NULL. + Otherwise, it holds a list of all syscalls to be caught. The + list elements are allocated with xmalloc. */ VEC(int) *syscalls_to_be_caught; /* Methods associated with this breakpoint. */ @@ -549,6 +641,16 @@ struct breakpoint breakpoints, we will use this index to try to find the same marker again. */ int static_trace_marker_id_idx; + + /* With a Python scripting enabled GDB, store a reference to the + Python object that has been associated with this breakpoint. + This is always NULL for a GDB that is not script enabled. It + can sometimes be NULL for enabled GDBs as not all breakpoint + types are tracked by the Python scripting API. */ + struct breakpoint_object *py_bp_object; + + /* Whether this watchpoint is exact (see target_exact_watchpoints). */ + int exact; }; typedef struct breakpoint *breakpoint_p; @@ -560,10 +662,6 @@ DEF_VEC_P(breakpoint_p); typedef struct bpstats *bpstat; -/* Frees any storage that is part of a bpstat. - Does not walk the 'next' chain. */ -extern void bpstat_free (bpstat); - /* Clears a chain of bpstat, freeing storage of each. */ extern void bpstat_clear (bpstat *); @@ -599,15 +697,16 @@ enum bpstat_what_main_action BPSTAT_WHAT_KEEP_CHECKING, /* Remove breakpoints, single step once, then put them back in and - go back to what we were doing. It's possible that this should be - removed from the main_action and put into a separate field, to more - cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */ + go back to what we were doing. It's possible that this should + be removed from the main_action and put into a separate field, + to more cleanly handle + BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */ BPSTAT_WHAT_SINGLE, /* Set longjmp_resume breakpoint, remove all other breakpoints, - and continue. The "remove all other breakpoints" part is required - if we are also stepping over another breakpoint as well as doing - the longjmp handling. */ + and continue. The "remove all other breakpoints" part is + required if we are also stepping over another breakpoint as + well as doing the longjmp handling. */ BPSTAT_WHAT_SET_LONGJMP_RESUME, /* Clear longjmp_resume breakpoint, then handle as @@ -617,8 +716,8 @@ enum bpstat_what_main_action /* Rather than distinguish between noisy and silent stops here, it might be cleaner to have bpstat_print make that decision (also taking into account stop_print_frame and source_only). But the - implications are a bit scary (interaction with auto-displays, etc.), - so I won't try it. */ + implications are a bit scary (interaction with auto-displays, + etc.), so I won't try it. */ /* Stop silently. */ BPSTAT_WHAT_STOP_SILENT, @@ -648,15 +747,20 @@ struct bpstat_what { enum bpstat_what_main_action main_action; - /* Did we hit a call dummy breakpoint? This only goes with a main_action - of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of - continuing from a call dummy without popping the frame is not a - useful one). */ + /* Did we hit a call dummy breakpoint? This only goes with a + main_action of BPSTAT_WHAT_STOP_SILENT or + BPSTAT_WHAT_STOP_NOISY (the concept of continuing from a call + dummy without popping the frame is not a useful one). */ enum stop_stack_kind call_dummy; + + /* Used for BPSTAT_WHAT_SET_LONGJMP_RESUME and + BPSTAT_WHAT_CLEAR_LONGJMP_RESUME. True if we are handling a + longjmp, false if we are handling an exception. */ + int is_longjmp; }; /* The possible return values for print_bpstat, print_it_normal, - print_it_done, print_it_noop. */ + print_it_done, print_it_noop. */ enum print_stop_action { PRINT_UNKNOWN = -1, @@ -668,7 +772,7 @@ enum print_stop_action /* Tell what to do about this bpstat. */ struct bpstat_what bpstat_what (bpstat); -/* Find the bpstat associated with a breakpoint. NULL otherwise. */ +/* Find the bpstat associated with a breakpoint. NULL otherwise. */ bpstat bpstat_find_breakpoint (bpstat, struct breakpoint *); /* Nonzero if a signal that we got in wait() was due to circumstances @@ -690,10 +794,11 @@ extern int bpstat_should_step (void); return means print the frame as well as the source line). */ extern enum print_stop_action bpstat_print (bpstat); -/* Put in *NUM the breakpoint number of the first breakpoint we are stopped - at. *BSP upon return is a bpstat which points to the remaining - breakpoints stopped at (but which is not guaranteed to be good for - anything but further calls to bpstat_num). +/* Put in *NUM the breakpoint number of the first breakpoint we are + stopped at. *BSP upon return is a bpstat which points to the + remaining breakpoints stopped at (but which is not guaranteed to be + good for anything but further calls to bpstat_num). + Return 0 if passed a bpstat which does not indicate any breakpoints. Return -1 if stopped at a breakpoint that has been deleted since we set it. @@ -711,15 +816,17 @@ extern void bpstat_clear_actions (bpstat); /* Implementation: */ -/* Values used to tell the printing routine how to behave for this bpstat. */ +/* Values used to tell the printing routine how to behave for this + bpstat. */ enum bp_print_how { /* This is used when we want to do a normal printing of the reason - for stopping. The output will depend on the type of eventpoint - we are dealing with. This is the default value, most commonly - used. */ + for stopping. The output will depend on the type of eventpoint + we are dealing with. This is the default value, most commonly + used. */ print_it_normal, - /* This is used when nothing should be printed for this bpstat entry. */ + /* This is used when nothing should be printed for this bpstat + entry. */ print_it_noop, /* This is used when everything which needs to be printed has already been printed. But we still want to print the frame. */ @@ -728,16 +835,41 @@ enum bp_print_how struct bpstats { - /* Linked list because there can be two breakpoints at the same - place, and a bpstat reflects the fact that both have been hit. */ + /* Linked list because there can be more than one breakpoint at + the same place, and a bpstat reflects the fact that all have + been hit. */ bpstat next; - /* Breakpoint that we are at. */ - const struct bp_location *breakpoint_at; + + /* Location that caused the stop. Locations are refcounted, so + this will never be NULL. Note that this location may end up + detached from a breakpoint, but that does not necessary mean + that the struct breakpoint is gone. E.g., consider a + watchpoint with a condition that involves an inferior function + call. Watchpoint locations are recreated often (on resumes, + hence on infcalls too). Between creating the bpstat and after + evaluating the watchpoint condition, this location may hence + end up detached from its original owner watchpoint, even though + the watchpoint is still listed. If it's condition evaluates as + true, we still want this location to cause a stop, and we will + still need to know which watchpoint it was originally attached. + What this means is that we should not (in most cases) follow + the `bpstat->bp_location->owner' link, but instead use the + `breakpoint_at' field below. */ + struct bp_location *bp_location_at; + + /* Breakpoint that caused the stop. This is nullified if the + breakpoint ends up being deleted. See comments on + `bp_location_at' above for why do we need this field instead of + following the location's owner. */ + struct breakpoint *breakpoint_at; + /* The associated command list. */ struct counted_command_line *commands; + /* Commands left to be done. This points somewhere in base_command. */ struct command_line *commands_left; + /* Old value associated with a watchpoint. */ struct value *old_val; @@ -772,15 +904,18 @@ enum breakpoint_here /* Prototypes for breakpoint-related functions. */ -extern enum breakpoint_here breakpoint_here_p (struct address_space *, CORE_ADDR); +extern enum breakpoint_here breakpoint_here_p (struct address_space *, + CORE_ADDR); extern int moribund_breakpoint_here_p (struct address_space *, CORE_ADDR); extern int breakpoint_inserted_here_p (struct address_space *, CORE_ADDR); -extern int regular_breakpoint_inserted_here_p (struct address_space *, CORE_ADDR); +extern int regular_breakpoint_inserted_here_p (struct address_space *, + CORE_ADDR); -extern int software_breakpoint_inserted_here_p (struct address_space *, CORE_ADDR); +extern int software_breakpoint_inserted_here_p (struct address_space *, + CORE_ADDR); /* Returns true if there's a hardware watchpoint or access watchpoint inserted in the range defined by ADDR and LEN. */ @@ -788,10 +923,15 @@ extern int hardware_watchpoint_inserted_in_range (struct address_space *, CORE_ADDR addr, ULONGEST len); -extern int breakpoint_thread_match (struct address_space *, CORE_ADDR, ptid_t); +extern int breakpoint_thread_match (struct address_space *, + CORE_ADDR, ptid_t); extern void until_break_command (char *, int, int); +extern void update_breakpoint_locations (struct breakpoint *b, + struct symtabs_and_lines sals, + struct symtabs_and_lines sals_end); + extern void breakpoint_re_set (void); extern void breakpoint_re_set_thread (struct breakpoint *); @@ -821,14 +961,18 @@ extern void breakpoint_auto_delete (bpstat); is hit. */ extern struct command_line *breakpoint_commands (struct breakpoint *b); +/* Return a string image of DISP. The string is static, and thus should + NOT be deallocated after use. */ +const char *bpdisp_text (enum bpdisp disp); + extern void break_command (char *, int); extern void hbreak_command_wrapper (char *, int); extern void thbreak_command_wrapper (char *, int); extern void rbreak_command_wrapper (char *, int); -extern void watch_command_wrapper (char *, int); -extern void awatch_command_wrapper (char *, int); -extern void rwatch_command_wrapper (char *, int); +extern void watch_command_wrapper (char *, int, int); +extern void awatch_command_wrapper (char *, int, int); +extern void rwatch_command_wrapper (char *, int, int); extern void tbreak_command (char *, int); extern int create_breakpoint (struct gdbarch *gdbarch, char *arg, @@ -839,7 +983,8 @@ extern int create_breakpoint (struct gdbarch *gdbarch, char *arg, enum auto_boolean pending_break_support, struct breakpoint_ops *ops, int from_tty, - int enabled); + int enabled, + int internal); extern void insert_breakpoints (void); @@ -849,9 +994,9 @@ extern int remove_breakpoints_pid (int pid); /* This function can be used to physically insert eventpoints from the specified traced inferior process, without modifying the breakpoint - package's state. This can be useful for those targets which support - following the processes of a fork() or vfork() system call, when both - of the resulting two processes are to be followed. */ + package's state. This can be useful for those targets which + support following the processes of a fork() or vfork() system call, + when both of the resulting two processes are to be followed. */ extern int reattach_breakpoints (int); /* This function can be used to update the breakpoint package's state @@ -868,7 +1013,7 @@ extern int reattach_breakpoints (int); - A step-resume breakpoint, if any, is explicitly removed from the breakpoint list. - All eventpoints without a symbolic address are removed from the - breakpoint list. */ + breakpoint list. */ extern void update_breakpoints_after_exec (void); /* This function can be used to physically remove hardware breakpoints @@ -887,7 +1032,8 @@ extern int detach_breakpoints (int); this PSPACE anymore. */ extern void breakpoint_program_space_exit (struct program_space *pspace); -extern void set_longjmp_breakpoint (int thread); +extern void set_longjmp_breakpoint (struct thread_info *tp, + struct frame_id frame); extern void delete_longjmp_breakpoint (int thread); extern void enable_overlay_breakpoints (void); @@ -935,20 +1081,17 @@ extern void disable_breakpoints_before_startup (void); extern void enable_breakpoints_after_startup (void); /* For script interpreters that need to define breakpoint commands - after they've already read the commands into a struct command_line. */ + after they've already read the commands into a struct + command_line. */ extern enum command_control_type commands_from_control_command (char *arg, struct command_line *cmd); extern void clear_breakpoint_hit_counts (void); -extern int get_number (char **); - -extern int get_number_or_range (char **); - extern struct breakpoint *get_breakpoint (int num); -/* The following are for displays, which aren't really breakpoints, but - here is as good a place as any for them. */ +/* The following are for displays, which aren't really breakpoints, + but here is as good a place as any for them. */ extern void disable_current_display (void); @@ -965,6 +1108,12 @@ extern void enable_breakpoint (struct breakpoint *); extern void breakpoint_set_commands (struct breakpoint *b, struct command_line *commands); +extern void breakpoint_set_silent (struct breakpoint *b, int silent); + +extern void breakpoint_set_thread (struct breakpoint *b, int thread); + +extern void breakpoint_set_task (struct breakpoint *b, int task); + /* Clear the "inserted" flag in all breakpoints. */ extern void mark_breakpoints_out (void); @@ -979,27 +1128,31 @@ extern struct breakpoint *create_solib_event_breakpoint (struct gdbarch *, extern struct breakpoint *create_thread_event_breakpoint (struct gdbarch *, CORE_ADDR); +extern void remove_jit_event_breakpoints (void); + extern void remove_solib_event_breakpoints (void); extern void remove_thread_event_breakpoints (void); extern void disable_breakpoints_in_shlibs (void); -/* This function returns TRUE if ep is a catchpoint. */ +/* This function returns TRUE if ep is a catchpoint. */ extern int ep_is_catchpoint (struct breakpoint *); /* Enable breakpoints and delete when hit. Called with ARG == NULL - deletes all breakpoints. */ + deletes all breakpoints. */ extern void delete_command (char *arg, int from_tty); -/* Pull all H/W watchpoints from the target. Return non-zero if the - remove fails. */ +/* Pull all H/W watchpoints from the target. Return non-zero if the + remove fails. */ extern int remove_hw_watchpoints (void); -/* Manage a software single step breakpoint (or two). Insert may be called - twice before remove is called. */ +/* Manage a software single step breakpoint (or two). Insert may be + called twice before remove is called. */ extern void insert_single_step_breakpoint (struct gdbarch *, - struct address_space *, CORE_ADDR); + struct address_space *, + CORE_ADDR); +extern int single_step_breakpoints_inserted (void); extern void remove_single_step_breakpoints (void); extern void cancel_single_step_breakpoints (void); @@ -1007,7 +1160,8 @@ extern void cancel_single_step_breakpoints (void); breakpoints. These functions are used in murky target-specific ways. Please do not add more uses! */ extern void *deprecated_insert_raw_breakpoint (struct gdbarch *, - struct address_space *, CORE_ADDR); + struct address_space *, + CORE_ADDR); extern int deprecated_remove_raw_breakpoint (struct gdbarch *, void *); /* Check if any hardware watchpoints have triggered, according to the @@ -1039,17 +1193,16 @@ extern int catch_syscall_enabled (void); Returns 0 if not, greater than 0 if we are. */ extern int catching_syscall_number (int syscall_number); -/* Tell a breakpoint to be quiet. */ -extern void make_breakpoint_silent (struct breakpoint *); - /* Return a tracepoint with the given number if found. */ extern struct breakpoint *get_tracepoint (int num); extern struct breakpoint *get_tracepoint_by_number_on_target (int num); /* Find a tracepoint by parsing a number in the supplied string. */ -extern struct breakpoint *get_tracepoint_by_number (char **arg, int multi_p, - int optional_p); +extern struct breakpoint * + get_tracepoint_by_number (char **arg, + struct get_number_or_range_state *state, + int optional_p); /* Return a vector of all tracepoints currently defined. The vector is newly allocated; the caller should free when done with it. */ @@ -1071,4 +1224,17 @@ extern void check_tracepoint_command (char *line, void *closure); extern void start_rbreak_breakpoints (void); extern void end_rbreak_breakpoints (void); +/* Breakpoint iterator function. + + Calls a callback function once for each breakpoint, so long as the + callback function returns false. If the callback function returns + true, the iteration will end and the current breakpoint will be + returned. This can be useful for implementing a search for a + breakpoint with arbitrary attributes, or for applying an operation + to every breakpoint. */ +extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *, + void *), void *); + +extern int user_breakpoint_p (struct breakpoint *); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/contrib/gdb-7/gdb/bsd-kvm.c b/contrib/gdb-7/gdb/bsd-kvm.c index c7d6c9d957..f224835f66 100644 --- a/contrib/gdb-7/gdb/bsd-kvm.c +++ b/contrib/gdb-7/gdb/bsd-kvm.c @@ -1,6 +1,6 @@ /* BSD Kernel Data Access Library (libkvm) interface. - Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -194,7 +194,7 @@ bsd_kvm_fetch_registers (struct target_ops *ops, if (nl[0].n_value != 0) { - /* Found dumppcb. If it contains a valid context, return + /* Found dumppcb. If it contains a valid context, return immediately. */ if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value)) return; @@ -248,7 +248,7 @@ bsd_kvm_fetch_registers (struct target_ops *ops, } #endif - /* i18n: PCB == "Process Control Block" */ + /* i18n: PCB == "Process Control Block". */ error (_("Cannot find a valid PCB")); } @@ -297,7 +297,7 @@ static void bsd_kvm_pcb_cmd (char *arg, int fromtty) { if (arg == NULL) - /* i18n: PCB == "Process Control Block" */ + /* i18n: PCB == "Process Control Block". */ error_no_arg (_("pcb address")); if (core_kd == NULL) @@ -370,7 +370,7 @@ Generic command for manipulating the kernel memory interface."), _("Set current context from proc address"), &bsd_kvm_cmdlist); #endif add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd, - /* i18n: PCB == "Process Control Block" */ + /* i18n: PCB == "Process Control Block". */ _("Set current context from pcb address"), &bsd_kvm_cmdlist); /* Some notes on the ptid usage on this target. @@ -385,7 +385,7 @@ Generic command for manipulating the kernel memory interface."), ptid (1, 1, 0) -> kvm inferior 1, in kernel ptid (1, 1, 1) -> kvm inferior 1, process 1 ptid (1, 1, 2) -> kvm inferior 1, process 2 - ptid (1, 1, n) -> kvm inferior 1, process n - */ + ptid (1, 1, n) -> kvm inferior 1, process n */ + bsd_kvm_ptid = ptid_build (1, 1, 0); } diff --git a/contrib/gdb-7/gdb/bsd-kvm.h b/contrib/gdb-7/gdb/bsd-kvm.h index dc8e231a39..4af3927c0a 100644 --- a/contrib/gdb-7/gdb/bsd-kvm.h +++ b/contrib/gdb-7/gdb/bsd-kvm.h @@ -1,6 +1,7 @@ /* BSD Kernel Data Access Library (libkvm) interface. - Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bsd-uthread.c b/contrib/gdb-7/gdb/bsd-uthread.c index bb54f2d1c0..1f09415521 100644 --- a/contrib/gdb-7/gdb/bsd-uthread.c +++ b/contrib/gdb-7/gdb/bsd-uthread.c @@ -1,6 +1,7 @@ /* BSD user-level threads support. - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -104,7 +105,7 @@ bsd_uthread_check_magic (CORE_ADDR addr) #define BSD_UTHREAD_PS_RUNNING 0 #define BSD_UTHREAD_PS_DEAD 18 -/* Address of the pointer to the the thread structure for the running +/* Address of the pointer to the thread structure for the running thread. */ static CORE_ADDR bsd_uthread_thread_run_addr; diff --git a/contrib/gdb-7/gdb/bsd-uthread.h b/contrib/gdb-7/gdb/bsd-uthread.h index 0d9e311012..a282fde1ea 100644 --- a/contrib/gdb-7/gdb/bsd-uthread.h +++ b/contrib/gdb-7/gdb/bsd-uthread.h @@ -1,6 +1,7 @@ /* BSD user-level threads support. - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/buildsym.c b/contrib/gdb-7/gdb/buildsym.c index e690a0ca0e..cd159a71cd 100644 --- a/contrib/gdb-7/gdb/buildsym.c +++ b/contrib/gdb-7/gdb/buildsym.c @@ -1,7 +1,7 @@ /* Support routines for building symbol tables in GDB's internal format. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ file-reading routines. Routines to support specific debugging information formats (stabs, - DWARF, etc) belong somewhere else. */ + DWARF, etc) belong somewhere else. */ #include "defs.h" #include "bfd.h" @@ -35,9 +35,9 @@ #include "gdb_assert.h" #include "complaints.h" #include "gdb_string.h" -#include "expression.h" /* For "enum exp_opcode" used by... */ +#include "expression.h" /* For "enum exp_opcode" used by... */ #include "bcache.h" -#include "filenames.h" /* For DOSish file names */ +#include "filenames.h" /* For DOSish file names. */ #include "macrotab.h" #include "demangle.h" /* Needed by SYMBOL_INIT_DEMANGLED_NAME. */ #include "block.h" @@ -48,7 +48,7 @@ /* Ask buildsym.h to define the vars it normally declares `extern'. */ #define EXTERN /**/ -#include "buildsym.h" /* Our own declarations */ +#include "buildsym.h" /* Our own declarations. */ #undef EXTERN /* For cleanup_undefined_types and finish_global_stabs (somewhat @@ -97,9 +97,9 @@ static int compare_line_numbers (const void *ln1p, const void *ln2p); #define INITIAL_LINE_VECTOR_LENGTH 1000 -/* maintain the lists of symbols and blocks */ +/* Maintain the lists of symbols and blocks. */ -/* Add a pending list to free_pendings. */ +/* Add a pending list to free_pendings. */ void add_free_pendings (struct pending *list) { @@ -127,7 +127,7 @@ add_symbol_to_list (struct symbol *symbol, struct pending **listhead) if (symbol->ginfo.name && symbol->ginfo.name[0] == '#') return; - /* We keep PENDINGSIZE symbols in each link of the list. If we + /* We keep PENDINGSIZE symbols in each link of the list. If we don't have a link with room in it, add a new link. */ if (*listhead == NULL || (*listhead)->nsyms == PENDINGSIZE) { @@ -175,7 +175,7 @@ find_symbol_in_list (struct pending *list, char *name, int length) } /* At end of reading syms, or in case of quit, really free as many - `struct pending's as we can easily find. */ + `struct pending's as we can easily find. */ void really_free_pendings (void *dummy) @@ -215,7 +215,7 @@ really_free_pendings (void *dummy) } } -/* This function is called to discard any pending blocks. */ +/* This function is called to discard any pending blocks. */ void free_pending_blocks (void) @@ -256,7 +256,7 @@ finish_block (struct symbol *symbol, struct pending **listhead, BLOCK_START (block) = start; BLOCK_END (block) = end; - /* Superblock filled in when containing block is made */ + /* Superblock filled in when containing block is made. */ BLOCK_SUPERBLOCK (block) = NULL; BLOCK_NAMESPACE (block) = NULL; @@ -273,7 +273,7 @@ finish_block (struct symbol *symbol, struct pending **listhead, { /* No parameter type information is recorded with the function's type. Set that from the type of the - parameter symbols. */ + parameter symbols. */ int nparams = 0, iparams; struct symbol *sym; ALL_BLOCK_SYMBOLS (block, iter, sym) @@ -319,24 +319,26 @@ finish_block (struct symbol *symbol, struct pending **listhead, *listhead = NULL; /* Check to be sure that the blocks have an end address that is - greater than starting address */ + greater than starting address. */ if (BLOCK_END (block) < BLOCK_START (block)) { if (symbol) { complaint (&symfile_complaints, - _("block end address less than block start address in %s (patched it)"), + _("block end address less than block " + "start address in %s (patched it)"), SYMBOL_PRINT_NAME (symbol)); } else { complaint (&symfile_complaints, - _("block end address %s less than block start address %s (patched it)"), + _("block end address %s less than block " + "start address %s (patched it)"), paddress (gdbarch, BLOCK_END (block)), paddress (gdbarch, BLOCK_START (block))); } - /* Better than nothing */ + /* Better than nothing. */ BLOCK_END (block) = BLOCK_START (block); } @@ -351,7 +353,7 @@ finish_block (struct symbol *symbol, struct pending **listhead, if (BLOCK_SUPERBLOCK (pblock->block) == NULL) { /* Check to be sure the blocks are nested as we receive - them. If the compiler/assembler/linker work, this just + them. If the compiler/assembler/linker work, this just burns a small amount of time. Skip blocks which correspond to a function; they're not @@ -370,7 +372,8 @@ finish_block (struct symbol *symbol, struct pending **listhead, else { complaint (&symfile_complaints, - _("inner block (%s-%s) not inside outer block (%s-%s)"), + _("inner block (%s-%s) not " + "inside outer block (%s-%s)"), paddress (gdbarch, BLOCK_START (pblock->block)), paddress (gdbarch, BLOCK_END (pblock->block)), paddress (gdbarch, BLOCK_START (block)), @@ -473,9 +476,9 @@ make_blockvector (struct objfile *objfile) (sizeof (struct blockvector) + (i - 1) * sizeof (struct block *))); - /* Copy the blocks into the blockvector. This is done in reverse + /* Copy the blocks into the blockvector. This is done in reverse order, which happens to put the blocks into the proper order - (ascending starting address). finish_block has hair to insert + (ascending starting address). finish_block has hair to insert each block into the list after its subblocks in order to make sure this is true. */ @@ -496,7 +499,7 @@ make_blockvector (struct objfile *objfile) BLOCKVECTOR_MAP (blockvector) = 0; /* Some compilers output blocks in the wrong order, but we depend on - their being in the right order so we can binary search. Check the + their being in the right order so we can binary search. Check the order and moan about it. */ if (BLOCKVECTOR_NBLOCKS (blockvector) > 1) { @@ -520,10 +523,11 @@ make_blockvector (struct objfile *objfile) /* Start recording information about source code that came from an included (or otherwise merged-in) source file with a different name. NAME is the name of the file (cannot be NULL), DIRNAME is - the directory in which the file was compiled (or NULL if not known). */ + the directory in which the file was compiled (or NULL if not + known). */ void -start_subfile (char *name, char *dirname) +start_subfile (const char *name, const char *dirname) { struct subfile *subfile; @@ -555,7 +559,7 @@ start_subfile (char *name, char *dirname) xfree (subfile_name); } - /* This subfile is not known. Add an entry for it. Make an entry + /* This subfile is not known. Add an entry for it. Make an entry for this subfile in the list of all subfiles of the current main source file. */ @@ -565,7 +569,7 @@ start_subfile (char *name, char *dirname) subfiles = subfile; current_subfile = subfile; - /* Save its name and compilation directory name */ + /* Save its name and compilation directory name. */ subfile->name = (name == NULL) ? NULL : xstrdup (name); subfile->dirname = (dirname == NULL) ? NULL : xstrdup (dirname); @@ -581,7 +585,7 @@ start_subfile (char *name, char *dirname) language then as well, but it is too late for us to use that information while reading symbols, since symtabs aren't allocated until after all the symbols have been processed for a given - source file. */ + source file. */ subfile->language = deduce_language_from_filename (subfile->name); if (subfile->language == language_unknown @@ -591,7 +595,7 @@ start_subfile (char *name, char *dirname) } /* Initialize the debug format string to NULL. We may supply it - later via a call to record_debugformat. */ + later via a call to record_debugformat. */ subfile->debugformat = NULL; /* Similarly for the producer. */ @@ -633,13 +637,13 @@ start_subfile (char *name, char *dirname) value to dirname and remembering the new name. Some sanity checking is performed to ensure that the state of the subfile struct is reasonable and that the old name we are assuming to be a - directory name actually is (by checking for a trailing '/'). */ + directory name actually is (by checking for a trailing '/'). */ void patch_subfile_names (struct subfile *subfile, char *name) { if (subfile != NULL && subfile->dirname == NULL && subfile->name != NULL - && subfile->name[strlen (subfile->name) - 1] == '/') + && IS_DIR_SEPARATOR (subfile->name[strlen (subfile->name) - 1])) { subfile->dirname = subfile->name; subfile->name = xstrdup (name); @@ -654,7 +658,7 @@ patch_subfile_names (struct subfile *subfile, char *name) are allocated we try to deduce a language then as well, but it is too late for us to use that information while reading symbols, since symtabs aren't allocated until after all the - symbols have been processed for a given source file. */ + symbols have been processed for a given source file. */ subfile->language = deduce_language_from_filename (subfile->name); if (subfile->language == language_unknown @@ -680,7 +684,8 @@ push_subfile (void) subfile_stack = tem; if (current_subfile == NULL || current_subfile->name == NULL) { - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); } tem->name = current_subfile->name; } @@ -693,7 +698,8 @@ pop_subfile (void) if (link == NULL) { - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); } name = link->name; subfile_stack = link->next; @@ -825,14 +831,14 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr) start_subfile (name, dirname); } -/* Subroutine of end_symtab to simplify it. - Look for a subfile that matches the main source file's basename. - If there is only one, and if the main source file doesn't have any - symbol or line number information, then copy this file's symtab and - line_vector to the main source file's subfile and discard the other subfile. - This can happen because of a compiler bug or from the user playing games - with #line or from things like a distributed build system that manipulates - the debug info. */ +/* Subroutine of end_symtab to simplify it. Look for a subfile that + matches the main source file's basename. If there is only one, and + if the main source file doesn't have any symbol or line number + information, then copy this file's symtab and line_vector to the + main source file's subfile and discard the other subfile. This can + happen because of a compiler bug or from the user playing games + with #line or from things like a distributed build system that + manipulates the debug info. */ static void watch_main_source_file_lossage (void) @@ -849,10 +855,12 @@ watch_main_source_file_lossage (void) mainsub = subfile; } - /* If the main source file doesn't have any line number or symbol info, - look for an alias in another subfile. - We have to watch for mainsub == NULL here. It's a quirk of end_symtab, - it can return NULL so there may not be a main subfile. */ + /* If the main source file doesn't have any line number or symbol + info, look for an alias in another subfile. + + We have to watch for mainsub == NULL here. It's a quirk of + end_symtab, it can return NULL so there may not be a main + subfile. */ if (mainsub && mainsub->line_vector == NULL @@ -870,7 +878,7 @@ watch_main_source_file_lossage (void) subfile->next; subfile = subfile->next) { - if (strcmp (lbasename (subfile->name), mainbase) == 0) + if (filename_cmp (lbasename (subfile->name), mainbase) == 0) { ++nr_matches; mainsub_alias = subfile; @@ -928,7 +936,7 @@ block_compar (const void *ap, const void *bp) TAG_compile_unit DIE. This can happen when we link in an object file that was compiled from an empty source file. Returning NULL is probably not the correct thing to do, because then gdb will - never know about this empty file (FIXME). */ + never know about this empty file (FIXME). */ struct symtab * end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) @@ -1017,10 +1025,10 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) { /* Define the STATIC_BLOCK & GLOBAL_BLOCK, and build the blockvector. */ - finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr, - objfile); - finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr, - objfile); + finish_block (0, &file_symbols, 0, last_source_start_addr, + end_addr, objfile); + finish_block (0, &global_symbols, 0, last_source_start_addr, + end_addr, objfile); blockvector = make_blockvector (objfile); } @@ -1041,7 +1049,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) int linetablesize = 0; symtab = NULL; - /* If we have blocks of symbols, make a symtab. Otherwise, just + /* If we have blocks of symbols, make a symtab. Otherwise, just ignore this file and any line number info in it. */ if (blockvector) { @@ -1070,7 +1078,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) symtab->macro_table = pending_macros; if (subfile->line_vector) { - /* Reallocate the line table on the symbol obstack */ + /* Reallocate the line table on the symbol obstack. */ symtab->linetable = (struct linetable *) obstack_alloc (&objfile->objfile_obstack, linetablesize); memcpy (symtab->linetable, subfile->line_vector, linetablesize); @@ -1082,7 +1090,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) symtab->block_line_section = section; if (subfile->dirname) { - /* Reallocate the dirname on the symbol obstack */ + /* Reallocate the dirname on the symbol obstack. */ symtab->dirname = (char *) obstack_alloc (&objfile->objfile_obstack, strlen (subfile->dirname) + 1); @@ -1100,10 +1108,10 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) from the filename. We already did our own deducing when we created the subfile, and we may have altered our opinion of what language it is from things we found in - the symbols. */ + the symbols. */ symtab->language = subfile->language; - /* Save the debug format string (if any) in the symtab */ + /* Save the debug format string (if any) in the symtab. */ if (subfile->debugformat != NULL) { symtab->debugformat = obsavestring (subfile->debugformat, @@ -1190,8 +1198,8 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) struct symbol *sym; struct dict_iterator iter; - /* Inlined functions may have symbols not in the global or static - symbol lists. */ + /* Inlined functions may have symbols not in the global or + static symbol lists. */ if (BLOCK_FUNCTION (block) != NULL) if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL) SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab; @@ -1250,7 +1258,7 @@ push_context (int desc, CORE_ADDR valu) } /* Pop a context block. Returns the address of the context block just - popped. */ + popped. */ struct context_stack * pop_context (void) @@ -1261,7 +1269,7 @@ pop_context (void) -/* Compute a small integer hash code for the given name. */ +/* Compute a small integer hash code for the given name. */ int hashname (char *name) @@ -1293,7 +1301,7 @@ record_producer (const char *producer) free_pendings list. Caller must set SRCLIST to a null list after calling this function. - Void return. */ + Void return. */ void merge_symbol_lists (struct pending **srclist, struct pending **targetlist) diff --git a/contrib/gdb-7/gdb/buildsym.h b/contrib/gdb-7/gdb/buildsym.h index f559b4b04b..37fe69cd9b 100644 --- a/contrib/gdb-7/gdb/buildsym.h +++ b/contrib/gdb-7/gdb/buildsym.h @@ -1,6 +1,6 @@ /* Build symbol tables in GDB's internal format. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1996, - 1997, 1998, 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010 + 1997, 1998, 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -44,11 +44,11 @@ struct block; #endif #define HASHSIZE 127 /* Size of things hashed via - hashname() */ + hashname(). */ /* Name of source file whose symbol data we are now processing. This - comes from a symbol of type N_SO for stabs. For Dwarf it comes from the - DW_AT_name attribute of a DW_TAG_compile_unit DIE. */ + comes from a symbol of type N_SO for stabs. For Dwarf it comes + from the DW_AT_name attribute of a DW_TAG_compile_unit DIE. */ EXTERN char *last_source_file; @@ -158,7 +158,7 @@ struct context_stack CORE_ADDR start_addr; - /* Temp slot for exception handling. */ + /* Temp slot for exception handling. */ CORE_ADDR end_addr; @@ -198,7 +198,7 @@ struct pending_block /* Pointer to the head of a linked list of symbol blocks which have already been finalized (lexical contexts already closed) and which are just waiting to be built into a blockvector when finalizing the - associated symtab. */ + associated symtab. */ EXTERN struct pending_block *pending_blocks; @@ -213,7 +213,7 @@ EXTERN struct subfile_stack *subfile_stack; #define next_symbol_text(objfile) (*next_symbol_text_func)(objfile) -/* Function to invoke get the next symbol. Return the symbol name. */ +/* Function to invoke get the next symbol. Return the symbol name. */ EXTERN char *(*next_symbol_text_func) (struct objfile *); @@ -253,7 +253,7 @@ extern void record_block_range (struct block *, extern void really_free_pendings (void *dummy); -extern void start_subfile (char *name, char *dirname); +extern void start_subfile (const char *name, const char *dirname); extern void patch_subfile_names (struct subfile *subfile, char *name); @@ -286,7 +286,7 @@ extern void free_pending_blocks (void); /* FIXME: Note that this is used only in buildsym.c and dstread.c, which should be fixed to not need direct access to - record_pending_block. */ + record_pending_block. */ extern void record_pending_block (struct objfile *objfile, struct block *block, @@ -300,7 +300,8 @@ extern void merge_symbol_lists (struct pending **srclist, struct pending **targetlist); /* The macro table for the compilation unit whose symbols we're - currently reading. All the symtabs for this CU will point to this. */ + currently reading. All the symtabs for this CU will point to + this. */ EXTERN struct macro_table *pending_macros; #undef EXTERN diff --git a/contrib/gdb-7/gdb/c-exp.y b/contrib/gdb-7/gdb/c-exp.y index d83bbf4d8a..3a02e9d973 100644 --- a/contrib/gdb-7/gdb/c-exp.y +++ b/contrib/gdb-7/gdb/c-exp.y @@ -1,6 +1,6 @@ /* YACC parser for C expressions, for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -612,7 +612,9 @@ exp : VARIABLE exp : SIZEOF '(' type ')' %prec UNARY { write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (parse_type->builtin_int); + write_exp_elt_type (lookup_signed_typename + (parse_language, parse_gdbarch, + "int")); CHECK_TYPEDEF ($3); write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3)); write_exp_elt_opcode (OP_LONG); } @@ -696,7 +698,7 @@ exp : string_exp case C_STRING_32: if (type != C_STRING && type != $1.tokens[i].type) - error ("Undefined string concatenation."); + error (_("Undefined string concatenation.")); type = $1.tokens[i].type; break; default: @@ -735,7 +737,7 @@ block : BLOCKNAME if ($1.sym) $$ = SYMBOL_BLOCK_VALUE ($1.sym); else - error ("No file or function \"%s\".", + error (_("No file or function \"%s\"."), copy_name ($1.stoken)); } | FILENAME @@ -749,7 +751,7 @@ block : block COLONCOLON name = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) - error ("No function \"%s\" in specified context.", + error (_("No function \"%s\" in specified context."), copy_name ($3)); $$ = SYMBOL_BLOCK_VALUE (tem); } ; @@ -759,7 +761,7 @@ variable: block COLONCOLON name sym = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (sym == 0) - error ("No symbol \"%s\" in specified context.", + error (_("No symbol \"%s\" in specified context."), copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); @@ -776,7 +778,7 @@ qualified_name: TYPENAME COLONCOLON name if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) - error ("`%s' is not defined as an aggregate type.", + error (_("`%s' is not defined as an aggregate type."), TYPE_NAME (type)); write_exp_elt_opcode (OP_SCOPE); @@ -792,7 +794,7 @@ qualified_name: TYPENAME COLONCOLON name if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) - error ("`%s' is not defined as an aggregate type.", + error (_("`%s' is not defined as an aggregate type."), TYPE_NAME (type)); tmp_token.ptr = (char*) alloca ($4.length + 2); @@ -840,9 +842,9 @@ variable: qualified_name if (msymbol != NULL) write_exp_msymbol (msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + error (_("No symbol table is loaded. Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", name); + error (_("No symbol \"%s\" in current context."), name); } ; @@ -892,9 +894,9 @@ variable: name_not_typename if (msymbol != NULL) write_exp_msymbol (msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + error (_("No symbol table is loaded. Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name ($1.stoken)); } } @@ -980,61 +982,117 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ : TYPENAME { $$ = $1.type; } | INT_KEYWORD - { $$ = parse_type->builtin_int; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "int"); } | LONG - { $$ = parse_type->builtin_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | SHORT - { $$ = parse_type->builtin_short; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "short"); } | LONG INT_KEYWORD - { $$ = parse_type->builtin_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | LONG SIGNED_KEYWORD INT_KEYWORD - { $$ = parse_type->builtin_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | LONG SIGNED_KEYWORD - { $$ = parse_type->builtin_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | SIGNED_KEYWORD LONG INT_KEYWORD - { $$ = parse_type->builtin_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | UNSIGNED LONG INT_KEYWORD - { $$ = parse_type->builtin_unsigned_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long"); } | LONG UNSIGNED INT_KEYWORD - { $$ = parse_type->builtin_unsigned_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long"); } | LONG UNSIGNED - { $$ = parse_type->builtin_unsigned_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long"); } | LONG LONG - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | LONG LONG INT_KEYWORD - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | LONG LONG SIGNED_KEYWORD INT_KEYWORD - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | LONG LONG SIGNED_KEYWORD - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | SIGNED_KEYWORD LONG LONG - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | SIGNED_KEYWORD LONG LONG INT_KEYWORD - { $$ = parse_type->builtin_long_long; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "long long"); } | UNSIGNED LONG LONG - { $$ = parse_type->builtin_unsigned_long_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long long"); } | UNSIGNED LONG LONG INT_KEYWORD - { $$ = parse_type->builtin_unsigned_long_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long long"); } | LONG LONG UNSIGNED - { $$ = parse_type->builtin_unsigned_long_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long long"); } | LONG LONG UNSIGNED INT_KEYWORD - { $$ = parse_type->builtin_unsigned_long_long; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "long long"); } | SHORT INT_KEYWORD - { $$ = parse_type->builtin_short; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "short"); } | SHORT SIGNED_KEYWORD INT_KEYWORD - { $$ = parse_type->builtin_short; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "short"); } | SHORT SIGNED_KEYWORD - { $$ = parse_type->builtin_short; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "short"); } | UNSIGNED SHORT INT_KEYWORD - { $$ = parse_type->builtin_unsigned_short; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "short"); } | SHORT UNSIGNED - { $$ = parse_type->builtin_unsigned_short; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "short"); } | SHORT UNSIGNED INT_KEYWORD - { $$ = parse_type->builtin_unsigned_short; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "short"); } | DOUBLE_KEYWORD - { $$ = parse_type->builtin_double; } + { $$ = lookup_typename (parse_language, parse_gdbarch, + "double", (struct block *) NULL, + 0); } | LONG DOUBLE_KEYWORD - { $$ = parse_type->builtin_long_double; } + { $$ = lookup_typename (parse_language, parse_gdbarch, + "long double", + (struct block *) NULL, 0); } | STRUCT name { $$ = lookup_struct (copy_name ($2), expression_context_block); } @@ -1052,13 +1110,17 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ parse_gdbarch, TYPE_NAME($2.type)); } | UNSIGNED - { $$ = parse_type->builtin_unsigned_int; } + { $$ = lookup_unsigned_typename (parse_language, + parse_gdbarch, + "int"); } | SIGNED_KEYWORD typename { $$ = lookup_signed_typename (parse_language, parse_gdbarch, TYPE_NAME($2.type)); } | SIGNED_KEYWORD - { $$ = parse_type->builtin_int; } + { $$ = lookup_signed_typename (parse_language, + parse_gdbarch, + "int"); } /* It appears that this rule for templates is never reduced; template recognition happens by lookahead in the token processing code in yylex. */ @@ -1077,19 +1139,25 @@ typename: TYPENAME { $$.stoken.ptr = "int"; $$.stoken.length = 3; - $$.type = parse_type->builtin_int; + $$.type = lookup_signed_typename (parse_language, + parse_gdbarch, + "int"); } | LONG { $$.stoken.ptr = "long"; $$.stoken.length = 4; - $$.type = parse_type->builtin_long; + $$.type = lookup_signed_typename (parse_language, + parse_gdbarch, + "long"); } | SHORT { $$.stoken.ptr = "short"; $$.stoken.length = 5; - $$.type = parse_type->builtin_short; + $$.type = lookup_signed_typename (parse_language, + parse_gdbarch, + "short"); } ; @@ -1323,10 +1391,8 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere) if (parsed_float) { - /* It's a float since it contains a point or an exponent. */ - char *s; - int num; /* number of tokens scanned by scanf */ - char saved_char; + const char *suffix; + int suffix_len; /* If it ends at "df", "dd" or "dl", take it as type of decimal floating point. Return DECFLOAT. */ @@ -1364,41 +1430,10 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere) return DECFLOAT; } - s = malloc (len); - saved_char = p[len]; - p[len] = 0; /* null-terminate the token */ - num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%s", - &putithere->typed_val_float.dval, s); - p[len] = saved_char; /* restore the input stream */ - - if (num == 0) - { - free (s); - return ERROR; - } - - if (num == 1) - putithere->typed_val_float.type = - parse_type->builtin_double; - - if (num == 2 ) - { - /* See if it has any float suffix: 'f' for float, 'l' for long - double. */ - if (!strcasecmp (s, "f")) - putithere->typed_val_float.type = - parse_type->builtin_float; - else if (!strcasecmp (s, "l")) - putithere->typed_val_float.type = - parse_type->builtin_long_double; - else - { - free (s); - return ERROR; - } - } - - free (s); + if (! parse_c_float (parse_gdbarch, p, len, + &putithere->typed_val_float.dval, + &putithere->typed_val_float.type)) + return ERROR; return FLOAT; } @@ -1492,7 +1527,7 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere) if (c != 'l' && c != 'u' && n != 0) { if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n)) - error ("Numeric constant too large."); + error (_("Numeric constant too large.")); } prevn = n; } @@ -1809,9 +1844,9 @@ parse_string_or_char (char *tokptr, char **outptr, struct typed_stoken *value, if (*tokptr != quote) { if (quote == '"') - error ("Unterminated string in expression."); + error (_("Unterminated string in expression.")); else - error ("Unmatched single quote."); + error (_("Unmatched single quote.")); } ++tokptr; @@ -2183,7 +2218,7 @@ lex_one_token (void) memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - error ("Invalid number \"%s\".", err_copy); + error (_("Invalid number \"%s\"."), err_copy); } lexptr = p; return toktype; @@ -2226,7 +2261,7 @@ lex_one_token (void) if (result == CHAR) { if (host_len == 0) - error ("Empty character constant."); + error (_("Empty character constant.")); else if (host_len > 2 && c == '\'') { ++tokstart; @@ -2234,7 +2269,7 @@ lex_one_token (void) goto tryname; } else if (host_len > 1) - error ("Invalid character constant."); + error (_("Invalid character constant.")); } return result; } @@ -2243,7 +2278,7 @@ lex_one_token (void) if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; @@ -2422,6 +2457,7 @@ classify_name (struct block *block) if (sym == NULL && parse_language->la_language == language_cplus + && !is_a_field_of_this && !lookup_minimal_symbol (copy, NULL, NULL)) return UNKNOWN_CPP_NAME; @@ -2622,5 +2658,5 @@ yyerror (char *msg) if (prev_lexptr) lexptr = prev_lexptr; - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); } diff --git a/contrib/gdb-7/gdb/c-lang.c b/contrib/gdb-7/gdb/c-lang.c index 40c417256b..255fabe2bf 100644 --- a/contrib/gdb-7/gdb/c-lang.c +++ b/contrib/gdb-7/gdb/c-lang.c @@ -1,7 +1,7 @@ /* C language support routines for GDB, the GNU debugger. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -35,6 +35,7 @@ #include "cp-support.h" #include "gdb_obstack.h" #include +#include "exceptions.h" extern void _initialize_c_language (void); @@ -64,13 +65,14 @@ charset_for_string_type (enum c_string_type str_type, else return "UTF-32LE"; } - internal_error (__FILE__, __LINE__, "unhandled c_string_type"); + internal_error (__FILE__, __LINE__, _("unhandled c_string_type")); } /* Classify ELTTYPE according to what kind of character it is. Return the enum constant representing the character type. Also set *ENCODING to the name of the character set to use when converting - characters of this type in target BYTE_ORDER to the host character set. */ + characters of this type in target BYTE_ORDER to the host character + set. */ static enum c_string_type classify_type (struct type *elttype, struct gdbarch *gdbarch, @@ -155,7 +157,8 @@ wchar_printable (gdb_wchar_t w) characters and then appends them to OUTPUT. */ static void -append_string_as_wide (const char *string, struct obstack *output) +append_string_as_wide (const char *string, + struct obstack *output) { for (; *string; ++string) { @@ -174,8 +177,10 @@ append_string_as_wide (const char *string, struct obstack *output) escapes across calls. */ static void -print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len, - int width, enum bfd_endian byte_order, struct obstack *output, +print_wchar (gdb_wint_t w, const gdb_byte *orig, + int orig_len, int width, + enum bfd_endian byte_order, + struct obstack *output, int quoter, int *need_escapep) { int need_escape = *need_escapep; @@ -225,7 +230,8 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len, char octal[30]; ULONGEST value; - value = extract_unsigned_integer (&orig[i], width, byte_order); + value = extract_unsigned_integer (&orig[i], width, + byte_order); /* If the value fits in 3 octal digits, print it that way. Otherwise, print it as a hex escape. */ if (value <= 0777) @@ -251,15 +257,16 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len, } } -/* Print the character C on STREAM as part of the contents of a literal - string whose delimiter is QUOTER. Note that that format for printing - characters and strings is language specific. */ +/* Print the character C on STREAM as part of the contents of a + literal string whose delimiter is QUOTER. Note that that format + for printing characters and strings is language specific. */ void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order + = gdbarch_byte_order (get_type_arch (type)); struct obstack wchar_buf, output; struct cleanup *cleanups; const char *encoding; @@ -272,8 +279,8 @@ c_emit_char (int c, struct type *type, buf = alloca (TYPE_LENGTH (type)); pack_long (buf, type, c); - iter = make_wchar_iterator (buf, TYPE_LENGTH (type), encoding, - TYPE_LENGTH (type)); + iter = make_wchar_iterator (buf, TYPE_LENGTH (type), + encoding, TYPE_LENGTH (type)); cleanups = make_cleanup_wchar_iterator (iter); /* This holds the printable form of the wchar_t data. */ @@ -312,15 +319,16 @@ c_emit_char (int c, struct type *type, if (!print_escape) { for (i = 0; i < num_chars; ++i) - print_wchar (chars[i], buf, buflen, TYPE_LENGTH (type), - byte_order, &wchar_buf, quoter, &need_escape); + print_wchar (chars[i], buf, buflen, + TYPE_LENGTH (type), byte_order, + &wchar_buf, quoter, &need_escape); } } /* This handles the NUM_CHARS == 0 case as well. */ if (print_escape) - print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type), byte_order, - &wchar_buf, quoter, &need_escape); + print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type), + byte_order, &wchar_buf, quoter, &need_escape); } /* The output in the host encoding. */ @@ -364,15 +372,17 @@ c_printchar (int c, struct type *type, struct ui_file *stream) fputc_filtered ('\'', stream); } -/* Print the character string STRING, printing at most LENGTH characters. - LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes - long. Printing stops early if the number hits print_max; repeat counts are - printed as appropriate. Print ellipses at the end if we had to stop before - printing LENGTH characters, or if FORCE_ELLIPSES. */ +/* Print the character string STRING, printing at most LENGTH + characters. LENGTH is -1 if the string is nul terminated. Each + character is WIDTH bytes long. Printing stops early if the number + hits print_max; repeat counts are printed as appropriate. Print + ellipses at the end if we had to stop before printing LENGTH + characters, or if FORCE_ELLIPSES. */ void -c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, - unsigned int length, const char *user_encoding, int force_ellipses, +c_printstr (struct ui_file *stream, struct type *type, + const gdb_byte *string, unsigned int length, + const char *user_encoding, int force_ellipses, const struct value_print_options *options) { enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); @@ -404,8 +414,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, } /* If the string was not truncated due to `set print elements', and - the last byte of it is a null, we don't print that, in traditional C - style. */ + the last byte of it is a null, we don't print that, in + traditional C style. */ if (!force_ellipses && length > 0 && (extract_unsigned_integer (string + (length - 1) * width, @@ -429,7 +439,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, break; } - encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding; + encoding = (user_encoding && *user_encoding) + ? user_encoding : type_encoding; if (length == 0) { @@ -483,7 +494,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, while (num_chars == 1 && current_char == chars[0]) { - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); + num_chars = wchar_iterate (iter, &result, &chars, + &buf, &buflen); ++reps; } @@ -535,8 +547,10 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, while (reps-- > 0) { - print_wchar (current_char, orig_buf, orig_len, width, - byte_order, &wchar_buf, '"', &need_escape); + print_wchar (current_char, orig_buf, + orig_len, width, + byte_order, &wchar_buf, + '"', &need_escape); ++things_printed; } } @@ -563,8 +577,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, in_quotes = 1; } need_escape = 0; - print_wchar (gdb_WEOF, buf, buflen, width, byte_order, &wchar_buf, - '"', &need_escape); + print_wchar (gdb_WEOF, buf, buflen, width, byte_order, + &wchar_buf, '"', &need_escape); break; case wchar_iterate_incomplete: @@ -576,8 +590,10 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, obstack_grow_wstr (&wchar_buf, LCST ("\",")); in_quotes = 0; } - obstack_grow_wstr (&wchar_buf, LCST (" ")); finished = 1; @@ -613,28 +629,30 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, } /* Obtain a C string from the inferior storing it in a newly allocated - buffer in BUFFER, which should be freed by the caller. If the - in- and out-parameter *LENGTH is specified at -1, the string is read + buffer in BUFFER, which should be freed by the caller. If the in- + and out-parameter *LENGTH is specified at -1, the string is read until a null character of the appropriate width is found, otherwise - the string is read to the length of characters specified. - The size of a character is determined by the length of the target - type of the pointer or array. If VALUE is an array with a known - length, the function will not read past the end of the array. - On completion, *LENGTH will be set to the size of the string read in + the string is read to the length of characters specified. The size + of a character is determined by the length of the target type of + the pointer or array. If VALUE is an array with a known length, + the function will not read past the end of the array. On + completion, *LENGTH will be set to the size of the string read in characters. (If a length of -1 is specified, the length returned will not include the null character). CHARSET is always set to the target charset. */ void -c_get_string (struct value *value, gdb_byte **buffer, int *length, - struct type **char_type, const char **charset) +c_get_string (struct value *value, gdb_byte **buffer, + int *length, struct type **char_type, + const char **charset) { int err, width; unsigned int fetchlimit; struct type *type = check_typedef (value_type (value)); struct type *element_type = TYPE_TARGET_TYPE (type); int req_length = *length; - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order + = gdbarch_byte_order (get_type_arch (type)); enum c_string_type kind; if (element_type == NULL) @@ -642,8 +660,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (TYPE_CODE (type) == TYPE_CODE_ARRAY) { - /* If we know the size of the array, we can use it as a limit on the - number of characters to be fetched. */ + /* If we know the size of the array, we can use it as a limit on + the number of characters to be fetched. */ if (TYPE_NFIELDS (type) == 1 && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_RANGE) { @@ -669,9 +687,10 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, charset); width = TYPE_LENGTH (element_type); - /* If the string lives in GDB's memory instead of the inferior's, then we - just need to copy it to BUFFER. Also, since such strings are arrays - with known size, FETCHLIMIT will hold the size of the array. */ + /* If the string lives in GDB's memory instead of the inferior's, + then we just need to copy it to BUFFER. Also, since such strings + are arrays with known size, FETCHLIMIT will hold the size of the + array. */ if ((VALUE_LVAL (value) == not_lval || VALUE_LVAL (value) == lval_internalvar) && fetchlimit != UINT_MAX) @@ -685,8 +704,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, else /* Otherwise, look for a null character. */ for (i = 0; i < fetchlimit; i++) - if (extract_unsigned_integer (contents + i * width, width, - byte_order) == 0) + if (extract_unsigned_integer (contents + i * width, + width, byte_order) == 0) break; /* I is now either a user-defined length, the number of non-null @@ -698,13 +717,19 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, } else { - err = read_string (value_as_address (value), *length, width, fetchlimit, - byte_order, buffer, length); + CORE_ADDR addr = value_as_address (value); + + err = read_string (addr, *length, width, fetchlimit, + byte_order, buffer, length); if (err) { xfree (*buffer); - error (_("Error reading string from inferior: %s"), - safe_strerror (err)); + if (err == EIO) + throw_error (MEMORY_ERROR, "Address %s out of bounds", + paddress (get_type_arch (type), addr)); + else + error (_("Error reading string from inferior: %s"), + safe_strerror (err)); } } @@ -715,8 +740,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (req_length == -1) /* If the last character is null, subtract it from LENGTH. */ if (*length > 0 - && extract_unsigned_integer (*buffer + *length - width, width, - byte_order) == 0) + && extract_unsigned_integer (*buffer + *length - width, + width, byte_order) == 0) *length -= width; /* The read_string function will return the number of bytes read. @@ -771,8 +796,8 @@ convert_ucn (char *p, char *limit, const char *dest_charset, result >>= 8; } - convert_between_encodings ("UTF-32BE", dest_charset, data, 4, 4, output, - translit_none); + convert_between_encodings ("UTF-32BE", dest_charset, data, + 4, 4, output, translit_none); return p; } @@ -797,7 +822,8 @@ emit_numeric_character (struct type *type, unsigned long value, pointer to just after the final digit of the escape sequence. */ static char * -convert_octal (struct type *type, char *p, char *limit, struct obstack *output) +convert_octal (struct type *type, char *p, + char *limit, struct obstack *output) { int i; unsigned long value = 0; @@ -821,7 +847,8 @@ convert_octal (struct type *type, char *p, char *limit, struct obstack *output) just after the final digit of the escape sequence. */ static char * -convert_hex (struct type *type, char *p, char *limit, struct obstack *output) +convert_hex (struct type *type, char *p, + char *limit, struct obstack *output) { unsigned long value = 0; @@ -921,7 +948,8 @@ parse_one_string (struct obstack *output, char *data, int len, /* If we saw a run of characters, convert them all. */ if (p > data) convert_between_encodings (host_charset (), dest_charset, - data, p - data, 1, output, translit_none); + data, p - data, 1, + output, translit_none); /* If we saw an escape, convert it. */ if (p < limit) p = convert_escape (type, dest_charset, p, limit, output); @@ -933,7 +961,7 @@ parse_one_string (struct obstack *output, char *data, int len, are delegated to evaluate_subexp_standard; see that function for a description of the arguments. */ -static struct value * +struct value * evaluate_subexp_c (struct type *expect_type, struct expression *exp, int *pos, enum noside noside) { @@ -950,6 +978,7 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, struct value *result; enum c_string_type dest_type; const char *dest_charset; + int satisfy_expected = 0; obstack_init (&output); cleanup = make_cleanup_obstack_free (&output); @@ -980,12 +1009,28 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, "char32_t", NULL, 0); break; default: - internal_error (__FILE__, __LINE__, "unhandled c_string_type"); + internal_error (__FILE__, __LINE__, _("unhandled c_string_type")); } /* Ensure TYPE_LENGTH is valid for TYPE. */ check_typedef (type); + /* If the caller expects an array of some integral type, + satisfy them. If something odder is expected, rely on the + caller to cast. */ + if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_ARRAY) + { + struct type *element_type + = check_typedef (TYPE_TARGET_TYPE (expect_type)); + + if (TYPE_CODE (element_type) == TYPE_CODE_INT + || TYPE_CODE (element_type) == TYPE_CODE_CHAR) + { + type = element_type; + satisfy_expected = 1; + } + } + dest_charset = charset_for_string_type (dest_type, exp->gdbarch); ++*pos; @@ -1008,7 +1053,9 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, if (noside == EVAL_SKIP) { /* Return a dummy value of the appropriate type. */ - if ((dest_type & C_CHAR) != 0) + if (expect_type != NULL) + result = allocate_value (expect_type); + else if ((dest_type & C_CHAR) != 0) result = allocate_value (type); else result = value_cstring ("", 0, type); @@ -1021,7 +1068,8 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, LONGEST value; if (obstack_object_size (&output) != TYPE_LENGTH (type)) - error (_("Could not convert character constant to target character set")); + error (_("Could not convert character " + "constant to target character set")); value = unpack_long (type, obstack_base (&output)); result = value_from_longest (type, value); } @@ -1032,9 +1080,30 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, /* Write the terminating character. */ for (i = 0; i < TYPE_LENGTH (type); ++i) obstack_1grow (&output, 0); - result = value_cstring (obstack_base (&output), - obstack_object_size (&output), - type); + + if (satisfy_expected) + { + LONGEST low_bound, high_bound; + int element_size = TYPE_LENGTH (type); + + if (get_discrete_bounds (TYPE_INDEX_TYPE (expect_type), + &low_bound, &high_bound) < 0) + { + low_bound = 0; + high_bound = (TYPE_LENGTH (expect_type) / element_size) - 1; + } + if (obstack_object_size (&output) / element_size + > (high_bound - low_bound + 1)) + error (_("Too many array elements")); + + result = allocate_value (expect_type); + memcpy (value_contents_raw (result), obstack_base (&output), + obstack_object_size (&output)); + } + else + result = value_cstring (obstack_base (&output), + obstack_object_size (&output), + type); } do_cleanups (cleanup); return result; @@ -1179,7 +1248,8 @@ const struct language_defn c_language_defn = basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ @@ -1299,7 +1369,8 @@ const struct language_defn cplus_language_defn = cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ cp_lookup_transparent_type, /* lookup_transparent_type */ cplus_demangle, /* Language specific symbol demangler */ - cp_class_name_from_physname, /* Language specific class_name_from_physname */ + cp_class_name_from_physname, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ @@ -1337,13 +1408,14 @@ const struct language_defn asm_language_defn = basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, default_make_symbol_completion_list, - c_language_arch_info, /* FIXME: la_language_arch_info. */ + c_language_arch_info, /* FIXME: la_language_arch_info. */ default_print_array_index, default_pass_by_reference, c_get_string, @@ -1380,7 +1452,8 @@ const struct language_defn minimal_language_defn = basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ diff --git a/contrib/gdb-7/gdb/c-lang.h b/contrib/gdb-7/gdb/c-lang.h index a04fbb2943..747d079c48 100644 --- a/contrib/gdb-7/gdb/c-lang.h +++ b/contrib/gdb-7/gdb/c-lang.h @@ -1,7 +1,7 @@ /* C language support definitions for GDB, the GNU debugger. Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005, 2006, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -27,6 +27,7 @@ struct language_arch_info; #include "value.h" #include "macroexp.h" +#include "parser-defs.h" /* The various kinds of C string and character. Note that these @@ -63,12 +64,15 @@ extern void c_error (char *); extern int c_parse_escape (char **, struct obstack *); /* Defined in c-typeprint.c */ -extern void c_print_type (struct type *, const char *, struct ui_file *, int, - int); +extern void c_print_type (struct type *, const char *, + struct ui_file *, int, int); -extern void c_print_typedef (struct type *, struct symbol *, struct ui_file *); +extern void c_print_typedef (struct type *, + struct symbol *, + struct ui_file *); -extern int c_val_print (struct type *, const gdb_byte *, int, CORE_ADDR, +extern int c_val_print (struct type *, const gdb_byte *, + int, CORE_ADDR, struct ui_file *, int, const struct value *, const struct value_print_options *); @@ -78,11 +82,19 @@ extern int c_value_print (struct value *, struct ui_file *, /* These are in c-lang.c: */ +extern struct value *evaluate_subexp_c (struct type *expect_type, + struct expression *exp, + int *pos, + enum noside noside); + extern void c_printchar (int, struct type *, struct ui_file *); -extern void c_printstr (struct ui_file * stream, struct type *elttype, - const gdb_byte *string, unsigned int length, - const char *user_encoding, int force_ellipses, +extern void c_printstr (struct ui_file * stream, + struct type *elttype, + const gdb_byte *string, + unsigned int length, + const char *user_encoding, + int force_ellipses, const struct value_print_options *options); extern void c_language_arch_info (struct gdbarch *gdbarch, @@ -93,9 +105,12 @@ extern const struct exp_descriptor exp_descriptor_c; extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter); +extern const struct op_print c_op_print_tab[]; + /* These are in c-typeprint.c: */ -extern void c_type_print_base (struct type *, struct ui_file *, int, int); +extern void c_type_print_base (struct type *, struct ui_file *, + int, int); /* These are in cp-valprint.c */ diff --git a/contrib/gdb-7/gdb/c-typeprint.c b/contrib/gdb-7/gdb/c-typeprint.c index 926ae2fc5e..2e23dd7f9f 100644 --- a/contrib/gdb-7/gdb/c-typeprint.c +++ b/contrib/gdb-7/gdb/c-typeprint.c @@ -1,6 +1,6 @@ /* Support for printing C and C++ types for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, - 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +20,7 @@ #include "defs.h" #include "gdb_obstack.h" -#include "bfd.h" /* Binary File Description */ +#include "bfd.h" /* Binary File Description. */ #include "symtab.h" #include "gdbtypes.h" #include "expression.h" @@ -33,30 +33,24 @@ #include "typeprint.h" #include "cp-abi.h" #include "jv-lang.h" - #include "gdb_string.h" #include -static void cp_type_print_method_args (struct type *mtype, char *prefix, - char *varstring, int staticp, - struct ui_file *stream); - -static void cp_type_print_derivation_info (struct ui_file *, struct type *); - -static void c_type_print_varspec_prefix (struct type *, struct ui_file *, int, - int, int); +static void c_type_print_varspec_prefix (struct type *, + struct ui_file *, + int, int, int); -/* Print "const", "volatile", or address space modifiers. */ -static void c_type_print_modifier (struct type *, struct ui_file *, +/* Print "const", "volatile", or address space modifiers. */ +static void c_type_print_modifier (struct type *, + struct ui_file *, int, int); - - - /* LEVEL is the depth to indent lines by. */ void -c_print_type (struct type *type, const char *varstring, struct ui_file *stream, +c_print_type (struct type *type, + const char *varstring, + struct ui_file *stream, int show, int level) { enum type_code code; @@ -86,11 +80,12 @@ c_print_type (struct type *type, const char *varstring, struct ui_file *stream, { fputs_filtered (varstring, stream); - /* For demangled function names, we have the arglist as part of the name, - so don't print an additional pair of ()'s */ + /* For demangled function names, we have the arglist as part of + the name, so don't print an additional pair of ()'s. */ demangled_args = strchr (varstring, '(') != NULL; - c_type_print_varspec_suffix (type, stream, show, 0, demangled_args); + c_type_print_varspec_suffix (type, stream, show, + 0, demangled_args); } } @@ -99,7 +94,8 @@ c_print_type (struct type *type, const char *varstring, struct ui_file *stream, which to print. */ void -c_print_typedef (struct type *type, struct symbol *new_symbol, +c_print_typedef (struct type *type, + struct symbol *new_symbol, struct ui_file *stream) { CHECK_TYPEDEF (type); @@ -114,8 +110,8 @@ c_print_typedef (struct type *type, struct symbol *new_symbol, } /* If TYPE is a derived type, then print out derivation information. - Print only the actual base classes of this type, not the base classes - of the base classes. I.E. for the derivation hierarchy: + Print only the actual base classes of this type, not the base + classes of the base classes. I.e. for the derivation hierarchy: class A { int a; }; class B : public A {int b; }; @@ -127,21 +123,25 @@ c_print_typedef (struct type *type, struct symbol *new_symbol, int c; } - Not as the following (like gdb used to), which is not legal C++ syntax for - derived types and may be confused with the multiple inheritance form: + Not as the following (like gdb used to), which is not legal C++ + syntax for derived types and may be confused with the multiple + inheritance form: class C : public B : public A { int c; } - In general, gdb should try to print the types as closely as possible to - the form that they appear in the source code. - Note that in case of protected derivation gcc will not say 'protected' - but 'private'. The HP's aCC compiler emits specific information for - derivation via protected inheritance, so gdb can print it out */ + In general, gdb should try to print the types as closely as + possible to the form that they appear in the source code. + + Note that in case of protected derivation gcc will not say + 'protected' but 'private'. The HP's aCC compiler emits specific + information for derivation via protected inheritance, so gdb can + print it out */ static void -cp_type_print_derivation_info (struct ui_file *stream, struct type *type) +cp_type_print_derivation_info (struct ui_file *stream, + struct type *type) { char *name; int i; @@ -150,8 +150,9 @@ cp_type_print_derivation_info (struct ui_file *stream, struct type *type) { fputs_filtered (i == 0 ? ": " : ", ", stream); fprintf_filtered (stream, "%s%s ", - BASETYPE_VIA_PUBLIC (type, i) ? "public" - : (TYPE_FIELD_PROTECTED (type, i) ? "protected" : "private"), + BASETYPE_VIA_PUBLIC (type, i) + ? "public" : (TYPE_FIELD_PROTECTED (type, i) + ? "protected" : "private"), BASETYPE_VIA_VIRTUAL (type, i) ? " virtual" : ""); name = type_name_no_tag (TYPE_BASECLASS (type, i)); fprintf_filtered (stream, "%s", name ? name : "(null)"); @@ -165,16 +166,19 @@ cp_type_print_derivation_info (struct ui_file *stream, struct type *type) /* Print the C++ method arguments ARGS to the file STREAM. */ static void -cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring, - int staticp, struct ui_file *stream) +cp_type_print_method_args (struct type *mtype, char *prefix, + char *varstring, int staticp, + struct ui_file *stream) { struct field *args = TYPE_FIELDS (mtype); int nargs = TYPE_NFIELDS (mtype); int varargs = TYPE_VARARGS (mtype); int i; - fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI); - fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI); + fprintf_symbol_filtered (stream, prefix, + language_cplus, DMGL_ANSI); + fprintf_symbol_filtered (stream, varstring, + language_cplus, DMGL_ANSI); fputs_filtered ("(", stream); /* Skip the class variable. */ @@ -229,9 +233,11 @@ cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring, between a trailing qualifier and a field, variable, or function name. */ -void -c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, - int show, int passed_a_ptr, int need_post_space) +static void +c_type_print_varspec_prefix (struct type *type, + struct ui_file *stream, + int show, int passed_a_ptr, + int need_post_space) { char *name; @@ -246,53 +252,62 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 1); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 1, 1); fprintf_filtered (stream, "*"); c_type_print_modifier (type, stream, 1, need_post_space); break; case TYPE_CODE_MEMBERPTR: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 0, 0); name = type_name_no_tag (TYPE_DOMAIN_TYPE (type)); if (name) fputs_filtered (name, stream); else - c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); + c_type_print_base (TYPE_DOMAIN_TYPE (type), + stream, 0, passed_a_ptr); fprintf_filtered (stream, "::*"); break; case TYPE_CODE_METHODPTR: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 0, 0); fprintf_filtered (stream, "("); name = type_name_no_tag (TYPE_DOMAIN_TYPE (type)); if (name) fputs_filtered (name, stream); else - c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); + c_type_print_base (TYPE_DOMAIN_TYPE (type), + stream, 0, passed_a_ptr); fprintf_filtered (stream, "::*"); break; case TYPE_CODE_REF: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 1, 0); fprintf_filtered (stream, "&"); c_type_print_modifier (type, stream, 1, need_post_space); break; case TYPE_CODE_METHOD: case TYPE_CODE_FUNC: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 0, 0); if (passed_a_ptr) fprintf_filtered (stream, "("); break; case TYPE_CODE_ARRAY: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 0, 0); if (passed_a_ptr) fprintf_filtered (stream, "("); break; case TYPE_CODE_TYPEDEF: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, show, 0, 0); break; case TYPE_CODE_UNDEF: @@ -321,10 +336,12 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, } } -/* Print out "const" and "volatile" attributes. +/* Print out "const" and "volatile" attributes, + and address space id if present. TYPE is a pointer to the type being printed out. STREAM is the output destination. - NEED_SPACE = 1 indicates an initial white space is needed */ + NEED_PRE_SPACE = 1 indicates an initial white space is needed. + NEED_POST_SPACE = 1 indicates a final white space is needed. */ static void c_type_print_modifier (struct type *type, struct ui_file *stream, @@ -370,14 +387,16 @@ c_type_print_modifier (struct type *type, struct ui_file *stream, /* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD or TYPE_CODE_FUNC, to STREAM. Artificial arguments, such as "this" - in non-static methods, are displayed if SHOW_ARTIFICIAL is - non-zero. LANGUAGE is the language in which TYPE was defined. This is - a necessary evil since this code is used by the C, C++, and Java - backends. */ + in non-static methods, are displayed if LINKAGE_NAME is zero. If + LINKAGE_NAME is non-zero and LANGUAGE is language_cplus the topmost + parameter types get removed their possible const and volatile qualifiers to + match demangled linkage name parameters part of such function type. + LANGUAGE is the language in which TYPE was defined. This is a necessary + evil since this code is used by the C, C++, and Java backends. */ void c_type_print_args (struct type *type, struct ui_file *stream, - int show_artificial, enum language language) + int linkage_name, enum language language) { int i, len; struct field *args; @@ -389,7 +408,9 @@ c_type_print_args (struct type *type, struct ui_file *stream, for (i = 0; i < TYPE_NFIELDS (type); i++) { - if (TYPE_FIELD_ARTIFICIAL (type, i) && !show_artificial) + struct type *param_type; + + if (TYPE_FIELD_ARTIFICIAL (type, i) && linkage_name) continue; if (printed_any) @@ -398,10 +419,24 @@ c_type_print_args (struct type *type, struct ui_file *stream, wrap_here (" "); } + param_type = TYPE_FIELD_TYPE (type, i); + + if (language == language_cplus && linkage_name) + { + /* C++ standard, 13.1 Overloadable declarations, point 3, item: + - Parameter declarations that differ only in the presence or + absence of const and/or volatile are equivalent. + + And the const/volatile qualifiers are not present in the mangled + names as produced by GCC. */ + + param_type = make_cv_type (0, 0, param_type, NULL); + } + if (language == language_java) - java_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0); + java_print_type (param_type, "", stream, -1, 0); else - c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0); + c_print_type (param_type, "", stream, -1, 0); printed_any = 1; } @@ -425,11 +460,11 @@ c_type_print_args (struct type *type, struct ui_file *stream, fprintf_filtered (stream, ")"); } - /* Return true iff the j'th overloading of the i'th method of TYPE is a type conversion operator, like `operator int () { ... }'. When listing a class's methods, we don't print the return type of such operators. */ + static int is_type_conversion_operator (struct type *type, int i, int j) { @@ -474,11 +509,11 @@ is_type_conversion_operator (struct type *type, int i, int j) return 1; /* That was indeed the end of the name, so it was `operator new' or - `operator delete', neither of which are type conversion operators. */ + `operator delete', neither of which are type conversion + operators. */ return 0; } - /* Given a C++ qualified identifier QID, strip off the qualifiers, yielding the unqualified name. The return value is a pointer into the original string. @@ -486,17 +521,18 @@ is_type_conversion_operator (struct type *type, int i, int j) It's a pity we don't have this information in some more structured form. Even the author of this function feels that writing little parsers like this everywhere is stupid. */ + static char * remove_qualifiers (char *qid) { - int quoted = 0; /* zero if we're not in quotes; - '"' if we're in a double-quoted string; - '\'' if we're in a single-quoted string. */ - int depth = 0; /* number of unclosed parens we've seen */ + int quoted = 0; /* Zero if we're not in quotes; + '"' if we're in a double-quoted string; + '\'' if we're in a single-quoted string. */ + int depth = 0; /* Number of unclosed parens we've seen. */ char *parenstack = (char *) alloca (strlen (qid)); char *scan; - char *last = 0; /* The character after the rightmost - `::' token we've seen so far. */ + char *last = 0; /* The character after the rightmost + `::' token we've seen so far. */ for (scan = qid; *scan; scan++) { @@ -512,8 +548,8 @@ remove_qualifiers (char *qid) /* If we're inside parenthesis (i.e., an argument list) or angle brackets (i.e., a list of template arguments), then we don't record the position of this :: token, since it's - not relevant to the top-level structure we're trying - to operate on. */ + not relevant to the top-level structure we're trying to + operate on. */ if (depth == 0) { last = scan + 2; @@ -537,10 +573,10 @@ remove_qualifiers (char *qid) depth--; else { - /* We're going to do a little error recovery here. If we - don't find a match for *scan on the paren stack, but - there is something lower on the stack that does match, we - pop the stack to that point. */ + /* We're going to do a little error recovery here. If + we don't find a match for *scan on the paren stack, + but there is something lower on the stack that does + match, we pop the stack to that point. */ int i; for (i = depth - 1; i >= 0; i--) @@ -561,14 +597,15 @@ remove_qualifiers (char *qid) return qid; } - /* Print any array sizes, function arguments or close parentheses needed after the variable name (to describe its type). Args work like c_type_print_varspec_prefix. */ void -c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, - int show, int passed_a_ptr, int demangled_args) +c_type_print_varspec_suffix (struct type *type, + struct ui_file *stream, + int show, int passed_a_ptr, + int demangled_args) { if (type == 0) return; @@ -581,36 +618,38 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - if (passed_a_ptr) - fprintf_filtered (stream, ")"); + { + LONGEST low_bound, high_bound; - fprintf_filtered (stream, "["); - if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 - && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) - fprintf_filtered (stream, "%d", - (TYPE_LENGTH (type) - / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); - fprintf_filtered (stream, "]"); + if (passed_a_ptr) + fprintf_filtered (stream, ")"); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - 0, 0); + fprintf_filtered (stream, "["); + if (get_array_bounds (type, &low_bound, &high_bound)) + fprintf_filtered (stream, "%d", + (int) (high_bound - low_bound + 1)); + fprintf_filtered (stream, "]"); + + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, 0, 0); + } break; case TYPE_CODE_MEMBERPTR: - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - 0, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, 0, 0); break; case TYPE_CODE_METHODPTR: fprintf_filtered (stream, ")"); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - 0, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, 0, 0); break; case TYPE_CODE_PTR: case TYPE_CODE_REF: - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - 1, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, 1, 0); break; case TYPE_CODE_METHOD: @@ -618,14 +657,14 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, if (passed_a_ptr) fprintf_filtered (stream, ")"); if (!demangled_args) - c_type_print_args (type, stream, 1, current_language->la_language); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - passed_a_ptr, 0); + c_type_print_args (type, stream, 0, current_language->la_language); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, passed_a_ptr, 0); break; case TYPE_CODE_TYPEDEF: - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, - passed_a_ptr, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, + show, passed_a_ptr, 0); break; case TYPE_CODE_UNDEF: @@ -646,7 +685,8 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, case TYPE_CODE_NAMESPACE: case TYPE_CODE_DECFLOAT: /* These types do not need a suffix. They are listed so that - gcc -Wall will report types that may not have been considered. */ + gcc -Wall will report types that may not have been + considered. */ break; default: error (_("type not handled in c_type_print_varspec_suffix()")); @@ -655,24 +695,26 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, } /* Print the name of the type (or the ultimate pointer target, - function value or array element), or the description of a - structure or union. - - SHOW positive means print details about the type (e.g. enum values), - and print structure elements passing SHOW - 1 for show. - SHOW negative means just print the type name or struct tag if there is one. - If there is no name, print something sensible but concise like - "struct {...}". - SHOW zero means just print the type name or struct tag if there is one. - If there is no name, print something sensible but not as concise like - "struct {int x; int y;}". + function value or array element), or the description of a structure + or union. + + SHOW positive means print details about the type (e.g. enum + values), and print structure elements passing SHOW - 1 for show. + + SHOW negative means just print the type name or struct tag if there + is one. If there is no name, print something sensible but concise + like "struct {...}". + + SHOW zero means just print the type name or struct tag if there is + one. If there is no name, print something sensible but not as + concise like "struct {int x; int y;}". LEVEL is the number of spaces to indent by. We increase it for some recursive calls. */ void -c_type_print_base (struct type *type, struct ui_file *stream, int show, - int level) +c_type_print_base (struct type *type, struct ui_file *stream, + int show, int level) { int i; int len, real_len; @@ -697,11 +739,12 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, return; } - /* When SHOW is zero or less, and there is a valid type name, then always - just print the type name directly from the type. */ - /* If we have "typedef struct foo {. . .} bar;" do we want to print it - as "struct foo" or as "bar"? Pick the latter, because C++ folk tend - to expect things like "class5 *foo" rather than "struct class5 *foo". */ + /* When SHOW is zero or less, and there is a valid type name, then + always just print the type name directly from the type. */ + /* If we have "typedef struct foo {. . .} bar;" do we want to print + it as "struct foo" or as "bar"? Pick the latter, because C++ + folk tend to expect things like "class5 *foo" rather than "struct + class5 *foo". */ if (show <= 0 && TYPE_NAME (type) != NULL) @@ -716,6 +759,13 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, switch (TYPE_CODE (type)) { case TYPE_CODE_TYPEDEF: + /* If we get here, the typedef doesn't have a name, and we + couldn't resolve TYPE_TARGET_TYPE. Not much we can do. */ + gdb_assert (TYPE_NAME (type) == NULL); + gdb_assert (TYPE_TARGET_TYPE (type) == NULL); + fprintf_filtered (stream, _("")); + break; + case TYPE_CODE_ARRAY: case TYPE_CODE_PTR: case TYPE_CODE_MEMBERPTR: @@ -723,7 +773,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, case TYPE_CODE_FUNC: case TYPE_CODE_METHOD: case TYPE_CODE_METHODPTR: - c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); + c_type_print_base (TYPE_TARGET_TYPE (type), + stream, show, level); break; case TYPE_CODE_STRUCT: @@ -740,12 +791,10 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, struct_union: - /* Print the tag if it exists. - * The HP aCC compiler emits - * a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}" - * tag for unnamed struct/union/enum's, which we don't - * want to print. - */ + /* Print the tag if it exists. The HP aCC compiler emits a + spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed + enum}" tag for unnamed struct/union/enum's, which we don't + want to print. */ if (TYPE_TAG_NAME (type) != NULL && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8)) { @@ -756,7 +805,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, wrap_here (" "); if (show < 0) { - /* If we just printed a tag name, no need to print anything else. */ + /* If we just printed a tag name, no need to print anything + else. */ if (TYPE_TAG_NAME (type) == NULL) fprintf_filtered (stream, "{...}"); } @@ -772,21 +822,23 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, && TYPE_TYPEDEF_FIELD_COUNT (type) == 0) { if (TYPE_STUB (type)) - fprintfi_filtered (level + 4, stream, _("\n")); + fprintfi_filtered (level + 4, stream, + _("\n")); else - fprintfi_filtered (level + 4, stream, _("\n")); + fprintfi_filtered (level + 4, stream, + _("\n")); } /* Start off with no specific section type, so we can print one for the first field we find, and use that section type - thereafter until we find another type. */ + thereafter until we find another type. */ section_type = s_none; /* For a class, if all members are private, there's no need for a "private:" label; similarly, for a struct or union masquerading as a class, if all members are public, there's - no need for a "public:" label. */ + no need for a "public:" label. */ if (TYPE_DECLARED_CLASS (type)) { @@ -806,7 +858,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, { len = TYPE_FN_FIELDLIST_LENGTH (type, j); for (i = 0; i < len; i++) - if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i)) + if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, + j), i)) { need_access_label = 1; break; @@ -821,7 +874,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, QUIT; len = TYPE_NFIELDS (type); for (i = TYPE_N_BASECLASSES (type); i < len; i++) - if (TYPE_FIELD_PRIVATE (type, i) || TYPE_FIELD_PROTECTED (type, i)) + if (TYPE_FIELD_PRIVATE (type, i) + || TYPE_FIELD_PROTECTED (type, i)) { need_access_label = 1; break; @@ -835,8 +889,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, QUIT; len = TYPE_FN_FIELDLIST_LENGTH (type, j); for (i = 0; i < len; i++) - if (TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i) - || TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type, j), i)) + if (TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type, + j), i) + || TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, + j), + i)) { need_access_label = 1; break; @@ -879,7 +936,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (section_type != s_private) { section_type = s_private; - fprintfi_filtered (level + 2, stream, "private:\n"); + fprintfi_filtered (level + 2, stream, + "private:\n"); } } else @@ -887,7 +945,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (section_type != s_public) { section_type = s_public; - fprintfi_filtered (level + 2, stream, "public:\n"); + fprintfi_filtered (level + 2, stream, + "public:\n"); } } } @@ -913,8 +972,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, } /* If there are both fields and methods, put a blank line - between them. Make sure to count only method that we will - display; artificial methods will be hidden. */ + between them. Make sure to count only method that we + will display; artificial methods will be hidden. */ len = TYPE_NFN_FIELDS (type); real_len = 0; for (i = 0; i < len; i++) @@ -930,14 +989,15 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (real_len > 0 && section_type != s_none) fprintf_filtered (stream, "\n"); - /* C++: print out the methods */ + /* C++: print out the methods. */ for (i = 0; i < len; i++) { struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); char *name = type_name_no_tag (type); - int is_constructor = name && strcmp (method_name, name) == 0; + int is_constructor = name && strcmp (method_name, + name) == 0; for (j = 0; j < len2; j++) { @@ -966,7 +1026,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (section_type != s_private) { section_type = s_private; - fprintfi_filtered (level + 2, stream, "private:\n"); + fprintfi_filtered (level + 2, stream, + "private:\n"); } } else @@ -974,7 +1035,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (section_type != s_public) { section_type = s_public; - fprintfi_filtered (level + 2, stream, "public:\n"); + fprintfi_filtered (level + 2, stream, + "public:\n"); } } @@ -986,12 +1048,15 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) { /* Keep GDB from crashing here. */ - fprintf_filtered (stream, _(" %s;\n"), + fprintf_filtered (stream, + _(" %s;\n"), TYPE_FN_FIELD_PHYSNAME (f, j)); break; } - else if (!is_constructor /* constructors don't have declared types */ - && !is_full_physname_constructor /* " " */ + else if (!is_constructor /* Constructors don't + have declared + types. */ + && !is_full_physname_constructor /* " " */ && !is_type_conversion_operator (type, i, j)) { type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), @@ -1009,11 +1074,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, DMGL_ANSI | DMGL_PARAMS); if (demangled_name == NULL) { - /* in some cases (for instance with the HP demangling), - if a function has more than 10 arguments, - the demangling will fail. - Let's try to reconstruct the function signature from - the symbol information */ + /* In some cases (for instance with the HP + demangling), if a function has more than 10 + arguments, the demangling will fail. + Let's try to reconstruct the function + signature from the symbol information. */ if (!TYPE_FN_FIELD_STUB (f, j)) { int staticp = TYPE_FN_FIELD_STATIC_P (f, j); @@ -1026,7 +1091,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, stream); } else - fprintf_filtered (stream, _(""), + fprintf_filtered (stream, + _(""), mangled_name); } else @@ -1035,14 +1101,17 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, char *demangled_no_class = remove_qualifiers (demangled_name); - /* get rid of the `static' appended by the demangler */ + /* Get rid of the `static' appended by the + demangler. */ p = strstr (demangled_no_class, " static"); if (p != NULL) { int length = p - demangled_no_class; - demangled_no_static = (char *) xmalloc (length + 1); - strncpy (demangled_no_static, demangled_no_class, length); + demangled_no_static + = (char *) xmalloc (length + 1); + strncpy (demangled_no_static, + demangled_no_class, length); *(demangled_no_static + length) = '\0'; fputs_filtered (demangled_no_static, stream); xfree (demangled_no_static); @@ -1085,7 +1154,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, fprintfi_filtered (level, stream, "}"); if (TYPE_LOCALTYPE_PTR (type) && show >= 0) - fprintfi_filtered (level, stream, _(" (Local at %s:%d)\n"), + fprintfi_filtered (level, + stream, _(" (Local at %s:%d)\n"), TYPE_LOCALTYPE_FILE (type), TYPE_LOCALTYPE_LINE (type)); } @@ -1098,7 +1168,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, The aCC compiler emits a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}" tag for unnamed struct/union/enum's, which we don't - want to print. */ + want to print. */ if (TYPE_TAG_NAME (type) != NULL && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8)) { @@ -1110,7 +1180,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, wrap_here (" "); if (show < 0) { - /* If we just printed a tag name, no need to print anything else. */ + /* If we just printed a tag name, no need to print anything + else. */ if (TYPE_TAG_NAME (type) == NULL) fprintf_filtered (stream, "{...}"); } @@ -1128,7 +1199,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, fputs_filtered (TYPE_FIELD_NAME (type, i), stream); if (lastval != TYPE_FIELD_BITPOS (type, i)) { - fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i)); + fprintf_filtered (stream, " = %d", + TYPE_FIELD_BITPOS (type, i)); lastval = TYPE_FIELD_BITPOS (type, i); } lastval++; @@ -1150,7 +1222,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_RANGE: - /* This should not occur */ + /* This should not occur. */ fprintf_filtered (stream, _("")); break; @@ -1160,10 +1232,10 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; default: - /* Handle types not explicitly handled by the other cases, - such as fundamental types. For these, just print whatever - the type name is, as recorded in the type itself. If there - is no type name, then complain. */ + /* Handle types not explicitly handled by the other cases, such + as fundamental types. For these, just print whatever the + type name is, as recorded in the type itself. If there is no + type name, then complain. */ if (TYPE_NAME (type) != NULL) { c_type_print_modifier (type, stream, 0, 1); @@ -1171,8 +1243,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, } else { - /* At least for dump_symtab, it is important that this not be - an error (). */ + /* At least for dump_symtab, it is important that this not + be an error (). */ fprintf_filtered (stream, _(""), TYPE_CODE (type)); } diff --git a/contrib/gdb-7/gdb/c-valprint.c b/contrib/gdb-7/gdb/c-valprint.c index f0895a4d9c..76579d2116 100644 --- a/contrib/gdb-7/gdb/c-valprint.c +++ b/contrib/gdb-7/gdb/c-valprint.c @@ -1,7 +1,7 @@ /* Support for printing C values for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -36,14 +36,17 @@ stream STREAM. */ static void -print_function_pointer_address (struct gdbarch *gdbarch, CORE_ADDR address, - struct ui_file *stream, int addressprint) +print_function_pointer_address (struct gdbarch *gdbarch, + CORE_ADDR address, + struct ui_file *stream, + int addressprint) { - CORE_ADDR func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, address, - ¤t_target); + CORE_ADDR func_addr + = gdbarch_convert_from_func_ptr_addr (gdbarch, address, + ¤t_target); - /* If the function pointer is represented by a description, print the - address of the description. */ + /* If the function pointer is represented by a description, print + the address of the description. */ if (addressprint && func_addr != address) { fputs_filtered ("@", stream); @@ -69,8 +72,8 @@ textual_name (const char *name) /* Apply a heuristic to decide whether an array of TYPE or a pointer to TYPE should be printed as a textual string. Return non-zero if it should, or zero if it should be treated as an array of integers - or pointer to integers. FORMAT is the current format letter, - or 0 if none. + or pointer to integers. FORMAT is the current format letter, or 0 + if none. We guess that "char" is a character. Explicitly signed and unsigned character types are also characters. Integer data from @@ -119,8 +122,8 @@ c_textual_element_type (struct type *type, char format) if (format == 's') { - /* Print this as a string if we can manage it. For now, no - wide character support. */ + /* Print this as a string if we can manage it. For now, no wide + character support. */ if (TYPE_CODE (true_type) == TYPE_CODE_INT && TYPE_LENGTH (true_type) == 1) return 1; @@ -139,23 +142,20 @@ c_textual_element_type (struct type *type, char format) return 0; } - -/* Print data of type TYPE located at VALADDR (within GDB), which came from - the inferior at address ADDRESS, onto stdio stream STREAM according to - OPTIONS. The data at VALADDR is in target byte order. - - If the data are a string pointer, returns the number of string characters - printed. */ +/* See val_print for a description of the various parameters of this + function; they are identical. The semantics of the return value is + also identical to val_print. */ int -c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, - CORE_ADDR address, struct ui_file *stream, int recurse, +c_val_print (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, const struct value *original_value, const struct value_print_options *options) { struct gdbarch *gdbarch = get_type_arch (type); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - unsigned int i = 0; /* Number of characters printed */ + unsigned int i = 0; /* Number of characters printed. */ unsigned len; struct type *elttype, *unresolved_elttype; struct type *unresolved_type = type; @@ -171,8 +171,13 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, elttype = check_typedef (unresolved_elttype); if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0) { + LONGEST low_bound, high_bound; + + if (!get_array_bounds (type, &low_bound, &high_bound)) + error (_("Could not determine the array high bound")); + eltlen = TYPE_LENGTH (elttype); - len = TYPE_LENGTH (type) / eltlen; + len = high_bound - low_bound + 1; if (options->prettyprint_arrays) { print_spaces_filtered (2 + 2 * recurse, stream); @@ -180,14 +185,16 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Print arrays of textual chars with a string syntax, as long as the entire array is valid. */ - if (!TYPE_VECTOR (type) - && c_textual_element_type (unresolved_elttype, options->format) + if (c_textual_element_type (unresolved_elttype, + options->format) + && value_bytes_available (original_value, embedded_offset, + TYPE_LENGTH (type)) && value_bits_valid (original_value, TARGET_CHAR_BIT * embedded_offset, TARGET_CHAR_BIT * TYPE_LENGTH (type))) { - /* If requested, look for the first null char and only print - elements up to it. */ + /* If requested, look for the first null char and only + print elements up to it. */ if (options->stop_print_at_null) { unsigned int temp_len; @@ -212,32 +219,35 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { fprintf_filtered (stream, "{"); /* If this is a virtual function table, print the 0th - entry specially, and the rest of the members normally. */ + entry specially, and the rest of the members + normally. */ if (cp_is_vtbl_ptr_type (elttype)) { i = 1; - fprintf_filtered (stream, _("%d vtable entries"), len - 1); + fprintf_filtered (stream, _("%d vtable entries"), + len - 1); } else { i = 0; } - val_print_array_elements (type, valaddr + embedded_offset, - address + embedded_offset, stream, + val_print_array_elements (type, valaddr, embedded_offset, + address, stream, recurse, original_value, options, i); fprintf_filtered (stream, "}"); } break; } - /* Array of unspecified length: treat like pointer to first elt. */ - addr = address; + /* Array of unspecified length: treat like pointer to first + elt. */ + addr = address + embedded_offset; goto print_unpacked_pointer; case TYPE_CODE_MEMBERPTR: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } cp_print_class_member (valaddr + embedded_offset, type, stream, "&"); @@ -250,15 +260,16 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_PTR: if (options->format && options->format != 's') { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } if (options->vtblprint && cp_is_vtbl_ptr_type (type)) { /* Print the unmangled name if desired. */ /* Print vtable entry - we only get here if we ARE using - -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ + -fvtable_thunks. (Otherwise, look under + TYPE_CODE_STRUCT.) */ CORE_ADDR addr = extract_typed_address (valaddr + embedded_offset, type); @@ -277,7 +288,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Try to print what function it points to. */ print_function_pointer_address (gdbarch, addr, stream, options->addressprint); - /* Return value is irrelevant except for string pointers. */ + /* Return value is irrelevant except for string + pointers. */ return (0); } @@ -287,16 +299,20 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* For a pointer to a textual type, also print the string pointed to, unless pointer is null. */ - if (c_textual_element_type (unresolved_elttype, options->format) + if (c_textual_element_type (unresolved_elttype, + options->format) && addr != 0) { - i = val_print_string (unresolved_elttype, addr, -1, stream, - options); + i = val_print_string (unresolved_elttype, NULL, + addr, -1, + stream, options); } else if (cp_is_vtbl_member (type)) { - /* print vtbl's nicely */ - CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset); + /* Print vtbl's nicely. */ + CORE_ADDR vt_address = unpack_pointer (type, + valaddr + + embedded_offset); struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (vt_address); @@ -316,8 +332,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, int is_this_fld; if (msymbol != NULL) - wsym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol), block, - VAR_DOMAIN, &is_this_fld); + wsym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol), + block, VAR_DOMAIN, + &is_this_fld); if (wsym) { @@ -328,8 +345,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, wtype = unresolved_elttype; } vt_val = value_at (wtype, vt_address); - common_val_print (vt_val, stream, recurse + 1, options, - current_language); + common_val_print (vt_val, stream, recurse + 1, + options, current_language); if (options->pretty) { fprintf_filtered (stream, "\n"); @@ -338,9 +355,10 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, } } - /* Return number of characters printed, including the terminating - '\0' if we reached the end. val_print_string takes care including - the terminating '\0' if necessary. */ + /* Return number of characters printed, including the + terminating '\0' if we reached the end. val_print_string + takes care including the terminating '\0' if + necessary. */ return i; } break; @@ -383,15 +401,18 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, } /* Fall through. */ case TYPE_CODE_STRUCT: - /*FIXME: Abstract this away */ + /*FIXME: Abstract this away. */ if (options->vtblprint && cp_is_vtbl_ptr_type (type)) { /* Print the unmangled name if desired. */ /* Print vtable entry - we only get here if NOT using - -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */ - int offset = (embedded_offset + - TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8); - struct type *field_type = TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET); + -fvtable_thunks. (Otherwise, look under + TYPE_CODE_PTR.) */ + int offset = (embedded_offset + + TYPE_FIELD_BITPOS (type, + VTBL_FNADDR_OFFSET) / 8); + struct type *field_type = TYPE_FIELD_TYPE (type, + VTBL_FNADDR_OFFSET); CORE_ADDR addr = extract_typed_address (valaddr + offset, field_type); @@ -400,15 +421,17 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, } else cp_print_value_fields_rtti (type, valaddr, - embedded_offset, address, stream, - recurse, original_value, options, NULL, 0); + embedded_offset, address, + stream, recurse, + original_value, options, + NULL, 0); break; case TYPE_CODE_ENUM: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } len = TYPE_NFIELDS (type); @@ -433,22 +456,24 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_FLAGS: if (options->format) - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else - val_print_type_code_flags (type, valaddr + embedded_offset, stream); + val_print_type_code_flags (type, valaddr + embedded_offset, + stream); break; case TYPE_CODE_FUNC: case TYPE_CODE_METHOD: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } - /* FIXME, we should consider, at least for ANSI C language, eliminating - the distinction made between FUNCs and POINTERs to FUNCs. */ + /* FIXME, we should consider, at least for ANSI C language, + eliminating the distinction made between FUNCs and POINTERs + to FUNCs. */ fprintf_filtered (stream, "{"); type_print (type, "", stream, -1); fprintf_filtered (stream, "} "); @@ -462,8 +487,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, struct value_print_options opts = *options; opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -479,12 +504,12 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_RANGE: /* FIXME: create_range_type does not set the unsigned bit in a - range type (I think it probably should copy it from the target - type), so we won't print values which are too large to + range type (I think it probably should copy it from the + target type), so we won't print values which are too large to fit in a signed integer correctly. */ /* FIXME: Doesn't handle ranges of enums correctly. (Can't just - print with the target type, though, because the size of our type - and the target type might differ). */ + print with the target type, though, because the size of our + type and the target type might differ). */ /* FALLTHROUGH */ case TYPE_CODE_INT: @@ -494,20 +519,21 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { - val_print_type_code_int (type, valaddr + embedded_offset, stream); - /* C and C++ has no single byte int type, char is used instead. - Since we don't know whether the value is really intended to - be used as an integer or a character, print the character - equivalent as well. */ + val_print_type_code_int (type, valaddr + embedded_offset, + stream); + /* C and C++ has no single byte int type, char is used + instead. Since we don't know whether the value is really + intended to be used as an integer or a character, print + the character equivalent as well. */ if (c_textual_element_type (unresolved_type, options->format)) { fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), + LA_PRINT_CHAR (unpack_long (type, valaddr + embedded_offset), unresolved_type, stream); } } @@ -519,8 +545,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, struct value_print_options opts = *options; opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -530,15 +556,15 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, else fprintf_filtered (stream, "%d", (int) val); fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) val, unresolved_type, stream); + LA_PRINT_CHAR (val, unresolved_type, stream); } break; case TYPE_CODE_FLT: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); } else { @@ -548,10 +574,11 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_DECFLOAT: if (options->format) - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else - print_decimal_floating (valaddr + embedded_offset, type, stream); + print_decimal_floating (valaddr + embedded_offset, + type, stream); break; case TYPE_CODE_VOID: @@ -563,26 +590,30 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, break; case TYPE_CODE_UNDEF: - /* This happens (without TYPE_FLAG_STUB set) on systems which don't use - dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar" - and no complete type for struct foo in that file. */ + /* This happens (without TYPE_FLAG_STUB set) on systems which + don't use dbx xrefs (NO_DBX_XREFS in gcc) if a file has a + "struct foo *bar" and no complete type for struct foo in that + file. */ fprintf_filtered (stream, _("")); break; case TYPE_CODE_COMPLEX: if (options->format) - print_scalar_formatted (valaddr + embedded_offset, - TYPE_TARGET_TYPE (type), - options, 0, stream); + val_print_scalar_formatted (TYPE_TARGET_TYPE (type), + valaddr, embedded_offset, + original_value, options, 0, stream); else - print_floating (valaddr + embedded_offset, TYPE_TARGET_TYPE (type), + print_floating (valaddr + embedded_offset, + TYPE_TARGET_TYPE (type), stream); fprintf_filtered (stream, " + "); if (options->format) - print_scalar_formatted (valaddr + embedded_offset - + TYPE_LENGTH (TYPE_TARGET_TYPE (type)), - TYPE_TARGET_TYPE (type), - options, 0, stream); + val_print_scalar_formatted (TYPE_TARGET_TYPE (type), + valaddr, + embedded_offset + + TYPE_LENGTH (TYPE_TARGET_TYPE (type)), + original_value, + options, 0, stream); else print_floating (valaddr + embedded_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)), @@ -592,7 +623,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, break; default: - error (_("Invalid C/C++ type code %d in symbol table."), TYPE_CODE (type)); + error (_("Invalid C/C++ type code %d in symbol table."), + TYPE_CODE (type)); } gdb_flush (stream); return (0); @@ -631,10 +663,11 @@ c_value_print (struct value *val, struct ui_file *stream, if (TYPE_CODE (val_type) == TYPE_CODE_PTR && TYPE_NAME (val_type) == NULL && TYPE_NAME (TYPE_TARGET_TYPE (val_type)) != NULL - && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)), "char") == 0 + && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)), + "char") == 0 || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type))))) { - /* Print nothing */ + /* Print nothing. */ } else if (options->objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) @@ -643,36 +676,43 @@ c_value_print (struct value *val, struct ui_file *stream, if (TYPE_CODE(type) == TYPE_CODE_REF) { /* Copy value, change to pointer, so we don't get an - * error about a non-pointer type in value_rtti_target_type - */ + error about a non-pointer type in + value_rtti_target_type. */ struct value *temparg; temparg=value_copy(val); - deprecated_set_value_type (temparg, lookup_pointer_type (TYPE_TARGET_TYPE(type))); - val=temparg; + deprecated_set_value_type + (temparg, lookup_pointer_type (TYPE_TARGET_TYPE (type))); + val = temparg; } - /* Pointer to class, check real type of object */ + /* Pointer to class, check real type of object. */ fprintf_filtered (stream, "("); - real_type = value_rtti_target_type (val, &full, &top, &using_enc); - if (real_type) - { - /* RTTI entry found */ - if (TYPE_CODE (type) == TYPE_CODE_PTR) - { - /* create a pointer type pointing to the real type */ - type = lookup_pointer_type (real_type); - } - else - { - /* create a reference type referencing the real type */ - type = lookup_reference_type (real_type); - } - /* JYG: Need to adjust pointer value. */ - /* NOTE: cagney/2005-01-02: THIS IS BOGUS. */ - value_contents_writeable (val)[0] -= top; - - /* Note: When we look up RTTI entries, we don't get any - information on const or volatile attributes */ - } + + if (value_entirely_available (val)) + { + real_type = value_rtti_target_type (val, &full, &top, &using_enc); + if (real_type) + { + /* RTTI entry found. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR) + { + /* Create a pointer type pointing to the real + type. */ + type = lookup_pointer_type (real_type); + } + else + { + /* Create a reference type referencing the real + type. */ + type = lookup_reference_type (real_type); + } + /* Need to adjust pointer value. */ + val = value_from_pointer (type, value_as_address (val) - top); + + /* Note: When we look up RTTI entries, we don't get + any information on const or volatile + attributes. */ + } + } type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); val_type = type; @@ -691,26 +731,28 @@ c_value_print (struct value *val, struct ui_file *stream, if (options->objectprint && (TYPE_CODE (type) == TYPE_CODE_CLASS)) { - /* Attempt to determine real type of object */ + /* Attempt to determine real type of object. */ real_type = value_rtti_type (val, &full, &top, &using_enc); if (real_type) { - /* We have RTTI information, so use it */ - val = value_full_object (val, real_type, full, top, using_enc); + /* We have RTTI information, so use it. */ + val = value_full_object (val, real_type, + full, top, using_enc); fprintf_filtered (stream, "(%s%s) ", TYPE_NAME (real_type), full ? "" : _(" [incomplete object]")); - /* Print out object: enclosing type is same as real_type if full */ + /* Print out object: enclosing type is same as real_type if + full. */ return val_print (value_enclosing_type (val), value_contents_for_printing (val), 0, value_address (val), stream, 0, val, &opts, current_language); - /* Note: When we look up RTTI entries, we don't get any information on - const or volatile attributes */ + /* Note: When we look up RTTI entries, we don't get any + information on const or volatile attributes. */ } else if (type != check_typedef (value_enclosing_type (val))) { - /* No RTTI information, so let's do our best */ + /* No RTTI information, so let's do our best. */ fprintf_filtered (stream, "(%s ?) ", TYPE_NAME (value_enclosing_type (val))); return val_print (value_enclosing_type (val), @@ -718,7 +760,7 @@ c_value_print (struct value *val, struct ui_file *stream, value_address (val), stream, 0, val, &opts, current_language); } - /* Otherwise, we end up at the return outside this "if" */ + /* Otherwise, we end up at the return outside this "if". */ } return val_print (val_type, value_contents_for_printing (val), diff --git a/contrib/gdb-7/gdb/call-cmds.h b/contrib/gdb-7/gdb/call-cmds.h index 5937e26647..f0c41fc12e 100644 --- a/contrib/gdb-7/gdb/call-cmds.h +++ b/contrib/gdb-7/gdb/call-cmds.h @@ -6,7 +6,7 @@ 2000-12-01 fnasser@redhat.com */ /* Prototypes for GDB commands that are called internally by other functions. - Copyright (C) 1992, 2000, 2001, 2007, 2008, 2009, 2010 + Copyright (C) 1992, 2000, 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify diff --git a/contrib/gdb-7/gdb/cc-with-index.sh b/contrib/gdb-7/gdb/cc-with-index.sh new file mode 100644 index 0000000000..9c95bef907 --- /dev/null +++ b/contrib/gdb-7/gdb/cc-with-index.sh @@ -0,0 +1,123 @@ +#! /bin/sh +# Wrapper around gcc to add the .gdb_index section when running the testsuite. + +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This program requires gdb and objcopy in addition to gcc. +# The default values are gdb from the build tree and objdump from $PATH. +# They may be overridden by setting environment variables GDB and OBJDUMP +# respectively. +# We assume the current directory is either $obj/gdb or $obj/gdb/testsuite. +# +# Example usage: +# +# bash$ cd $objdir/gdb/testsuite +# bash$ runtest \ +# CC_FOR_TARGET="/bin/sh $srcdir/cc-with-index.sh gcc" \ +# CXX_FOR_TARGET="/bin/sh $srcdir/cc-with-index.sh g++" +# +# For documentation on index files: info -f gdb.info -n "Index Files" + +myname=cc-with-index.sh + +if [ -z "$GDB" ] +then + if [ -f ./gdb ] + then + GDB="./gdb" + elif [ -f ../gdb ] + then + GDB="../gdb" + else + echo "$myname: unable to find usable gdb" >&2 + exit 1 + fi +fi + +OBJCOPY=${OBJCOPY:-objcopy} + +have_link=unknown +next_is_output_file=no +output_file=a.out + +for arg in "$@" +do + if [ "$next_is_output_file" = "yes" ] + then + output_file="$arg" + next_is_output_file=no + continue + fi + + # Poor man's gcc argument parser. + # We don't need to handle all arguments, we just need to know if we're + # doing a link and what the output file is. + # It's not perfect, but it seems to work well enough for the task at hand. + case "$arg" in + "-c") have_link=no ;; + "-E") have_link=no ;; + "-S") have_link=no ;; + "-o") next_is_output_file=yes ;; + esac +done + +if [ "$next_is_output_file" = "yes" ] +then + echo "$myname: Unable to find output file" >&2 + exit 1 +fi + +if [ "$have_link" = "no" ] +then + "$@" + exit $? +fi + +index_file="${output_file}.gdb-index" +if [ -f "$index_file" ] +then + echo "$myname: Index file $index_file exists, won't clobber." >&2 + exit 1 +fi + +output_dir="${output_file%/*}" +[ "$output_dir" = "$output_file" ] && output_dir="." + +"$@" +rc=$? +[ $rc != 0 ] && exit $rc +if [ ! -f "$output_file" ] +then + echo "$myname: Internal error: $output_file missing." >&2 + exit 1 +fi + +$GDB --batch-silent -nx -ex "file $output_file" -ex "save gdb-index $output_dir" +rc=$? +[ $rc != 0 ] && exit $rc + +# GDB might not always create an index. Cope. +if [ -f "$index_file" ] +then + $OBJCOPY --add-section .gdb_index="$index_file" \ + --set-section-flags .gdb_index=readonly \ + "$output_file" "$output_file" + rc=$? +else + rc=0 +fi + +rm -f "$index_file" +exit $rc diff --git a/contrib/gdb-7/gdb/charset-list.h b/contrib/gdb-7/gdb/charset-list.h index cc8a05c3cc..e6aea21f19 100644 --- a/contrib/gdb-7/gdb/charset-list.h +++ b/contrib/gdb-7/gdb/charset-list.h @@ -1,6 +1,6 @@ /* List of character set names for GDB. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/charset.c b/contrib/gdb-7/gdb/charset.c index 43b7fa8f22..a84085ac3a 100644 --- a/contrib/gdb-7/gdb/charset.c +++ b/contrib/gdb-7/gdb/charset.c @@ -1,6 +1,6 @@ /* Character set conversion support for GDB. - Copyright (C) 2001, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -90,8 +90,11 @@ #undef iconv_t #define iconv_t int #undef iconv_open +#define iconv_open phony_iconv_open #undef iconv +#define iconv phony_iconv #undef iconv_close +#define iconv_close phony_iconv_close #undef ICONV_CONST #define ICONV_CONST const @@ -106,7 +109,7 @@ #endif iconv_t -iconv_open (const char *to, const char *from) +phony_iconv_open (const char *to, const char *from) { /* We allow conversions from UTF-32BE, wchar_t, and the host charset. We allow conversions to wchar_t and the host charset. */ @@ -122,14 +125,14 @@ iconv_open (const char *to, const char *from) } int -iconv_close (iconv_t arg) +phony_iconv_close (iconv_t arg) { return 0; } size_t -iconv (iconv_t utf_flag, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) +phony_iconv (iconv_t utf_flag, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) { if (utf_flag) { @@ -235,8 +238,10 @@ show_target_charset_name (struct ui_file *file, int from_tty, static const char *target_wide_charset_name = "auto"; static void -show_target_wide_charset_name (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) +show_target_wide_charset_name (struct ui_file *file, + int from_tty, + struct cmd_list_element *c, + const char *value) { if (!strcmp (value, "auto")) fprintf_filtered (file, @@ -319,13 +324,13 @@ validate (struct gdbarch *gdbarch) desc = iconv_open (target_wide_cset, host_cset); if (desc == (iconv_t) -1) - error ("Cannot convert between character sets `%s' and `%s'", + error (_("Cannot convert between character sets `%s' and `%s'"), target_wide_cset, host_cset); iconv_close (desc); desc = iconv_open (target_cset, host_cset); if (desc == (iconv_t) -1) - error ("Cannot convert between character sets `%s' and `%s'", + error (_("Cannot convert between character sets `%s' and `%s'"), target_cset, host_cset); iconv_close (desc); @@ -335,9 +340,10 @@ validate (struct gdbarch *gdbarch) /* This is the sfunc for the 'set charset' command. */ static void -set_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) +set_charset_sfunc (char *charset, int from_tty, + struct cmd_list_element *c) { - /* CAREFUL: set the target charset here as well. */ + /* CAREFUL: set the target charset here as well. */ target_charset_name = host_charset_name; validate (get_current_arch ()); } @@ -369,12 +375,14 @@ set_target_wide_charset_sfunc (char *charset, int from_tty, /* sfunc for the 'show charset' command. */ static void -show_charset (struct ui_file *file, int from_tty, struct cmd_list_element *c, +show_charset (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *name) { show_host_charset_name (file, from_tty, c, host_charset_name); show_target_charset_name (file, from_tty, c, target_charset_name); - show_target_wide_charset_name (file, from_tty, c, target_wide_charset_name); + show_target_wide_charset_name (file, from_tty, c, + target_wide_charset_name); } @@ -478,7 +486,7 @@ convert_between_encodings (const char *from, const char *to, desc = iconv_open (to, from); if (desc == (iconv_t) -1) - perror_with_name ("Converting character sets"); + perror_with_name (_("Converting character sets")); cleanups = make_cleanup (cleanup_iconv, &desc); inleft = num_bytes; @@ -514,8 +522,8 @@ convert_between_encodings (const char *from, const char *to, /* Invalid input sequence. */ if (translit == translit_none) - error (_("Could not convert character to `%s' character set"), - to); + error (_("Could not convert character " + "to `%s' character set"), to); /* We emit escape sequence for the bytes, skip them, and try again. */ @@ -545,7 +553,8 @@ convert_between_encodings (const char *from, const char *to, break; default: - perror_with_name ("Internal error while converting character sets"); + perror_with_name (_("Internal error while " + "converting character sets")); } } } @@ -576,15 +585,15 @@ struct wchar_iterator /* Create a new iterator. */ struct wchar_iterator * -make_wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset, - size_t width) +make_wchar_iterator (const gdb_byte *input, size_t bytes, + const char *charset, size_t width) { struct wchar_iterator *result; iconv_t desc; desc = iconv_open (INTERMEDIATE_ENCODING, charset); if (desc == (iconv_t) -1) - perror_with_name ("Converting character sets"); + perror_with_name (_("Converting character sets")); result = XNEW (struct wchar_iterator); result->desc = desc; @@ -637,16 +646,21 @@ wchar_iterate (struct wchar_iterator *iter, size_t out_avail = out_request * sizeof (gdb_wchar_t); size_t num; size_t r = iconv (iter->desc, - (ICONV_CONST char **) &iter->input, &iter->bytes, - &outptr, &out_avail); + (ICONV_CONST char **) &iter->input, + &iter->bytes, &outptr, &out_avail); if (r == (size_t) -1) { switch (errno) { case EILSEQ: - /* Invalid input sequence. Skip it, and let the caller - know about it. */ + /* Invalid input sequence. We still might have + converted a character; if so, return it. */ + if (out_avail < out_request * sizeof (gdb_wchar_t)) + break; + + /* Otherwise skip the first invalid character, and let + the caller know about it. */ *out_result = wchar_iterate_invalid; *ptr = iter->input; *len = iter->width; @@ -680,7 +694,8 @@ wchar_iterate (struct wchar_iterator *iter, return 0; default: - perror_with_name ("Internal error while converting character sets"); + perror_with_name (_("Internal error while " + "converting character sets")); } } @@ -786,9 +801,9 @@ find_charset_names (void) int fail = 1; struct gdb_environ *iconv_env; - /* Older iconvs, e.g. 2.2.2, don't omit the intro text if stdout is not - a tty. We need to recognize it and ignore it. This text is subject - to translation, so force LANGUAGE=C. */ + /* Older iconvs, e.g. 2.2.2, don't omit the intro text if stdout is + not a tty. We need to recognize it and ignore it. This text is + subject to translation, so force LANGUAGE=C. */ iconv_env = make_environ (); init_environ (iconv_env); set_in_environ (iconv_env, "LANGUAGE", "C"); @@ -837,8 +852,8 @@ find_charset_names (void) buf[len] = '\0'; /* libiconv will print multiple entries per line, separated - by spaces. Older iconvs will print multiple entries per line, - indented by two spaces, and separated by ", " + by spaces. Older iconvs will print multiple entries per + line, indented by two spaces, and separated by ", " (i.e. the human readable form). */ start = buf; while (1) @@ -907,6 +922,72 @@ default_auto_wide_charset (void) return GDB_DEFAULT_TARGET_WIDE_CHARSET; } + +#ifdef USE_INTERMEDIATE_ENCODING_FUNCTION +/* Macro used for UTF or UCS endianness suffix. */ +#if WORDS_BIGENDIAN +#define ENDIAN_SUFFIX "BE" +#else +#define ENDIAN_SUFFIX "LE" +#endif + +/* The code below serves to generate a compile time error if + gdb_wchar_t type is not of size 2 nor 4, despite the fact that + macro __STDC_ISO_10646__ is defined. + This is better than a gdb_assert call, because GDB cannot handle + strings correctly if this size is different. */ + +extern char your_gdb_wchar_t_is_bogus[(sizeof (gdb_wchar_t) == 2 + || sizeof (gdb_wchar_t) == 4) + ? 1 : -1]; + +/* intermediate_encoding returns the charset unsed internally by + GDB to convert between target and host encodings. As the test above + compiled, sizeof (gdb_wchar_t) is either 2 or 4 bytes. + UTF-16/32 is tested first, UCS-2/4 is tested as a second option, + otherwise an error is generated. */ + +const char * +intermediate_encoding (void) +{ + iconv_t desc; + static const char *stored_result = NULL; + char *result; + int i; + + if (stored_result) + return stored_result; + result = xstrprintf ("UTF-%d%s", (int) (sizeof (gdb_wchar_t) * 8), + ENDIAN_SUFFIX); + /* Check that the name is supported by iconv_open. */ + desc = iconv_open (result, host_charset ()); + if (desc != (iconv_t) -1) + { + iconv_close (desc); + stored_result = result; + return result; + } + /* Not valid, free the allocated memory. */ + xfree (result); + /* Second try, with UCS-2 type. */ + result = xstrprintf ("UCS-%d%s", (int) sizeof (gdb_wchar_t), + ENDIAN_SUFFIX); + /* Check that the name is supported by iconv_open. */ + desc = iconv_open (result, host_charset ()); + if (desc != (iconv_t) -1) + { + iconv_close (desc); + stored_result = result; + return result; + } + /* Not valid, free the allocated memory. */ + xfree (result); + /* No valid charset found, generate error here. */ + error (_("Unable to find a vaild charset for string conversions")); +} + +#endif /* USE_INTERMEDIATE_ENCODING_FUNCTION */ + void _initialize_charset (void) { @@ -925,15 +1006,16 @@ _initialize_charset (void) leak a little memory, if the user later changes the host charset, but that doesn't matter much. */ auto_host_charset_name = xstrdup (nl_langinfo (CODESET)); - /* Solaris will return `646' here -- but the Solaris iconv then - does not accept this. Darwin (and maybe FreeBSD) may return "" here, + /* Solaris will return `646' here -- but the Solaris iconv then does + not accept this. Darwin (and maybe FreeBSD) may return "" here, which GNU libiconv doesn't like (infinite loop). */ if (!strcmp (auto_host_charset_name, "646") || !*auto_host_charset_name) auto_host_charset_name = "ASCII"; auto_target_charset_name = auto_host_charset_name; #elif defined (USE_WIN32API) { - static char w32_host_default_charset[16]; /* "CP" + x<=5 digits + paranoia. */ + /* "CP" + x<=5 digits + paranoia. */ + static char w32_host_default_charset[16]; snprintf (w32_host_default_charset, sizeof w32_host_default_charset, "CP%d", GetACP()); @@ -988,8 +1070,8 @@ To see a list of the character sets GDB supports, type `set target-charset' _("\ Set the target wide character set."), _("\ Show the target wide character set."), _("\ -The `target wide character set' is the one used by the program being debugged.\n\ -In particular it is the encoding used by `wchar_t'.\n\ +The `target wide character set' is the one used by the program being debugged.\ +\nIn particular it is the encoding used by `wchar_t'.\n\ GDB translates characters and strings between the host and target\n\ character sets as needed.\n\ To see a list of the character sets GDB supports, type\n\ diff --git a/contrib/gdb-7/gdb/charset.h b/contrib/gdb-7/gdb/charset.h index bd93d01d7d..72f4dd70e3 100644 --- a/contrib/gdb-7/gdb/charset.h +++ b/contrib/gdb-7/gdb/charset.h @@ -1,5 +1,6 @@ /* Character set conversion support for GDB. - Copyright (C) 2001, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2001, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -60,8 +61,10 @@ enum transliterations caller is responsible for initializing the obstack, and for destroying the obstack should an error occur. TRANSLIT specifies how invalid conversions should be handled. */ + void convert_between_encodings (const char *from, const char *to, - const gdb_byte *bytes, unsigned int num_bytes, + const gdb_byte *bytes, + unsigned int num_bytes, int width, struct obstack *output, enum transliterations translit); @@ -91,7 +94,8 @@ struct wchar_iterator; This function either returns a new character set iterator, or calls error. The result can be freed using a cleanup; see make_cleanup_wchar_iterator. */ -struct wchar_iterator *make_wchar_iterator (const gdb_byte *input, size_t bytes, +struct wchar_iterator *make_wchar_iterator (const gdb_byte *input, + size_t bytes, const char *charset, size_t width); diff --git a/contrib/gdb-7/gdb/cli-out.c b/contrib/gdb-7/gdb/cli-out.c index de0559f0e9..9a8515d985 100644 --- a/contrib/gdb-7/gdb/cli-out.c +++ b/contrib/gdb-7/gdb/cli-out.c @@ -1,6 +1,6 @@ /* Output generating routines for GDB CLI. - Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions. @@ -26,6 +26,7 @@ #include "cli-out.h" #include "gdb_string.h" #include "gdb_assert.h" +#include "vec.h" typedef struct cli_ui_out_data cli_out_data; @@ -224,11 +225,13 @@ cli_field_fmt (struct ui_out *uiout, int fldno, va_list args) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream; if (data->suppress_output) return; - vfprintf_filtered (data->stream, format, args); + stream = VEC_last (ui_filep, data->streams); + vfprintf_filtered (stream, format, args); if (align != ui_noalign) field_separator (); @@ -238,20 +241,26 @@ static void cli_spaces (struct ui_out *uiout, int numspaces) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream; if (data->suppress_output) return; - print_spaces_filtered (numspaces, data->stream); + + stream = VEC_last (ui_filep, data->streams); + print_spaces_filtered (numspaces, stream); } static void cli_text (struct ui_out *uiout, const char *string) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream; if (data->suppress_output) return; - fputs_filtered (string, data->stream); + + stream = VEC_last (ui_filep, data->streams); + fputs_filtered (string, stream); } static void ATTRIBUTE_PRINTF (3, 0) @@ -262,8 +271,13 @@ cli_message (struct ui_out *uiout, int verbosity, if (data->suppress_output) return; + if (ui_out_get_verblvl (uiout) >= verbosity) - vfprintf_unfiltered (data->stream, format, args); + { + struct ui_file *stream = VEC_last (ui_filep, data->streams); + + vfprintf_unfiltered (stream, format, args); + } } static void @@ -280,25 +294,24 @@ static void cli_flush (struct ui_out *uiout) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream = VEC_last (ui_filep, data->streams); - gdb_flush (data->stream); + gdb_flush (stream); } +/* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams + and make it therefore active. OUTSTREAM as NULL will pop the last pushed + output stream; it is an internal error if it does not exist. */ + static int cli_redirect (struct ui_out *uiout, struct ui_file *outstream) { cli_out_data *data = ui_out_data (uiout); if (outstream != NULL) - { - data->original_stream = data->stream; - data->stream = outstream; - } - else if (data->original_stream != NULL) - { - data->stream = data->original_stream; - data->original_stream = NULL; - } + VEC_safe_push (ui_filep, data->streams, outstream); + else + VEC_pop (ui_filep, data->streams); return 0; } @@ -315,10 +328,11 @@ out_field_fmt (struct ui_out *uiout, int fldno, const char *format,...) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream = VEC_last (ui_filep, data->streams); va_list args; va_start (args, format); - vfprintf_filtered (data->stream, format, args); + vfprintf_filtered (stream, format, args); va_end (args); } @@ -329,8 +343,9 @@ static void field_separator (void) { cli_out_data *data = ui_out_data (uiout); + struct ui_file *stream = VEC_last (ui_filep, data->streams); - fputc_filtered (' ', data->stream); + fputc_filtered (' ', stream); } /* This is the CLI ui-out implementation functions vector */ @@ -364,8 +379,11 @@ struct ui_out_impl cli_ui_out_impl = void cli_out_data_ctor (cli_out_data *self, struct ui_file *stream) { - self->stream = stream; - self->original_stream = NULL; + gdb_assert (stream != NULL); + + self->streams = NULL; + VEC_safe_push (ui_filep, self->streams, stream); + self->suppress_output = 0; } @@ -385,8 +403,10 @@ struct ui_file * cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream) { cli_out_data *data = ui_out_data (uiout); - struct ui_file *old = data->stream; + struct ui_file *old; + + old = VEC_pop (ui_filep, data->streams); + VEC_quick_push (ui_filep, data->streams, stream); - data->stream = stream; return old; } diff --git a/contrib/gdb-7/gdb/cli-out.h b/contrib/gdb-7/gdb/cli-out.h index b4cdd82350..befa624eb3 100644 --- a/contrib/gdb-7/gdb/cli-out.h +++ b/contrib/gdb-7/gdb/cli-out.h @@ -1,5 +1,5 @@ /* Output generating routines for GDB CLI. - Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions. @@ -22,14 +22,19 @@ #define CLI_OUT_H #include "ui-out.h" +#include "vec.h" + +/* Used for cli_ui_out_data->streams. */ + +typedef struct ui_file *ui_filep; +DEF_VEC_P (ui_filep); /* These are exported so that they can be extended by other `ui_out' implementations, like TUI's. */ struct cli_ui_out_data { - struct ui_file *stream; - struct ui_file *original_stream; + VEC (ui_filep) *streams; int suppress_output; }; diff --git a/contrib/gdb-7/gdb/cli/cli-cmds.c b/contrib/gdb-7/gdb/cli/cli-cmds.c index e5df8f5207..7fd2f50398 100644 --- a/contrib/gdb-7/gdb/cli/cli-cmds.c +++ b/contrib/gdb-7/gdb/cli/cli-cmds.c @@ -1,7 +1,7 @@ /* GDB CLI commands. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -24,9 +24,9 @@ #include "readline/readline.h" #include "readline/tilde.h" #include "completer.h" -#include "target.h" /* For baud_rate, remote_debug and remote_timeout */ -#include "gdb_wait.h" /* For shell escape implementation */ -#include "gdb_regex.h" /* Used by apropos_command */ +#include "target.h" /* For baud_rate, remote_debug and remote_timeout. */ +#include "gdb_wait.h" /* For shell escape implementation. */ +#include "gdb_regex.h" /* Used by apropos_command. */ #include "gdb_string.h" #include "gdb_vfork.h" #include "linespec.h" @@ -34,7 +34,7 @@ #include "frame.h" #include "value.h" #include "language.h" -#include "filenames.h" /* for DOSish file names */ +#include "filenames.h" /* For DOSish file names. */ #include "objfiles.h" #include "source.h" #include "disasm.h" @@ -51,7 +51,7 @@ #include "python/python.h" #ifdef TUI -#include "tui/tui.h" /* For tui_active et.al. */ +#include "tui/tui.h" /* For tui_active et.al. */ #endif #include @@ -105,35 +105,35 @@ struct cmd_list_element *cmdlist; struct cmd_list_element *infolist; -/* Chain containing all defined enable subcommands. */ +/* Chain containing all defined enable subcommands. */ struct cmd_list_element *enablelist; -/* Chain containing all defined disable subcommands. */ +/* Chain containing all defined disable subcommands. */ struct cmd_list_element *disablelist; -/* Chain containing all defined toggle subcommands. */ +/* Chain containing all defined toggle subcommands. */ struct cmd_list_element *togglelist; -/* Chain containing all defined stop subcommands. */ +/* Chain containing all defined stop subcommands. */ struct cmd_list_element *stoplist; -/* Chain containing all defined delete subcommands. */ +/* Chain containing all defined delete subcommands. */ struct cmd_list_element *deletelist; -/* Chain containing all defined detach subcommands. */ +/* Chain containing all defined detach subcommands. */ struct cmd_list_element *detachlist; -/* Chain containing all defined kill subcommands. */ +/* Chain containing all defined kill subcommands. */ struct cmd_list_element *killlist; -/* Chain containing all defined "enable breakpoint" subcommands. */ +/* Chain containing all defined "enable breakpoint" subcommands. */ struct cmd_list_element *enablebreaklist; @@ -161,15 +161,15 @@ struct cmd_list_element *showhistlist; struct cmd_list_element *unsethistlist; -/* Chain containing all defined maintenance subcommands. */ +/* Chain containing all defined maintenance subcommands. */ struct cmd_list_element *maintenancelist; -/* Chain containing all defined "maintenance info" subcommands. */ +/* Chain containing all defined "maintenance info" subcommands. */ struct cmd_list_element *maintenanceinfolist; -/* Chain containing all defined "maintenance print" subcommands. */ +/* Chain containing all defined "maintenance print" subcommands. */ struct cmd_list_element *maintenanceprintlist; @@ -206,7 +206,7 @@ static const char *script_ext_enums[] = { static const char *script_ext_mode = script_ext_soft; /* Utility used everywhere when at least one argument is needed and - none is supplied. */ + none is supplied. */ void error_no_arg (char *why) @@ -215,12 +215,14 @@ error_no_arg (char *why) } /* The "info" command is defined as a prefix, with allow_unknown = 0. - Therefore, its own definition is called only for "info" with no args. */ + Therefore, its own definition is called only for "info" with no + args. */ static void info_command (char *arg, int from_tty) { - printf_unfiltered (_("\"info\" must be followed by the name of an info command.\n")); + printf_unfiltered (_("\"info\" must be followed by " + "the name of an info command.\n")); help_list (infolist, "info ", -1, gdb_stdout); } @@ -265,10 +267,10 @@ complete_command (char *arg, int from_tty) arg = ""; argpoint = strlen (arg); - /* complete_line assumes that its first argument is somewhere within, - and except for filenames at the beginning of, the word to be completed. - The following crude imitation of readline's word-breaking tries to - accomodate this. */ + /* complete_line assumes that its first argument is somewhere + within, and except for filenames at the beginning of, the word to + be completed. The following crude imitation of readline's + word-breaking tries to accomodate this. */ point = arg + argpoint; while (point > arg) { @@ -444,8 +446,8 @@ cd_command (char *dir, int from_tty) } } else - /* We are dealing with leading repetitions of "/..", for example - "/../..", which is the Mach super-root. */ + /* We are dealing with leading repetitions of "/..", for + example "/../..", which is the Mach super-root. */ p += 3; } else @@ -467,8 +469,8 @@ static void show_script_ext_mode (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Script filename extension recognition is \"%s\".\n"), + fprintf_filtered (file, + _("Script filename extension recognition is \"%s\".\n"), value); } @@ -574,10 +576,10 @@ source_script_with_search (const char *file, int from_tty, int search_path) if (!find_and_open_script (file, search_path, &stream, &full_path)) { - /* The script wasn't found, or was otherwise inaccessible. - If the source command was invoked interactively, throw an error. - Otherwise (e.g. if it was invoked by a script), silently ignore - the error. */ + /* The script wasn't found, or was otherwise inaccessible. + If the source command was invoked interactively, throw an + error. Otherwise (e.g. if it was invoked by a script), + silently ignore the error. */ if (from_tty) perror_with_name (file); else @@ -616,7 +618,8 @@ source_command (char *args, int from_tty) int search_path = 0; *old_source_verbose = source_verbose; - old_cleanups = make_cleanup (source_verbose_cleanup, old_source_verbose); + old_cleanups = make_cleanup (source_verbose_cleanup, + old_source_verbose); /* -v causes the source command to run in verbose mode. -s causes the file to be searched in the source search path, @@ -628,7 +631,8 @@ source_command (char *args, int from_tty) { while (args[0] != '\0') { - /* Make sure leading white space does not break the comparisons. */ + /* Make sure leading white space does not break the + comparisons. */ while (isspace(args[0])) args++; @@ -717,8 +721,8 @@ shell_escape (char *arg, int from_tty) gdb_flush (gdb_stderr); } #ifdef GLOBAL_CURDIR - /* Make sure to return to the directory GDB thinks it is, in case the - shell command we just ran changed it. */ + /* Make sure to return to the directory GDB thinks it is, in case + the shell command we just ran changed it. */ chdir (current_directory); #endif #else /* Can fork. */ @@ -726,16 +730,13 @@ shell_escape (char *arg, int from_tty) if ((pid = vfork ()) == 0) { - char *p, *user_shell; + const char *p, *user_shell; if ((user_shell = (char *) getenv ("SHELL")) == NULL) user_shell = "/bin/sh"; - /* Get the name of the shell for arg0 */ - if ((p = strrchr (user_shell, '/')) == NULL) - p = user_shell; - else - p++; /* Get past '/' */ + /* Get the name of the shell for arg0. */ + p = lbasename (user_shell); if (!arg) execl (user_shell, p, (char *) 0); @@ -773,7 +774,7 @@ edit_command (char *arg, int from_tty) sal = get_current_source_symtab_and_line (); } - /* bare "edit" edits file with present line. */ + /* Bare "edit" edits file with present line. */ if (arg == 0) { @@ -786,7 +787,7 @@ edit_command (char *arg, int from_tty) /* Now should only be one argument -- decode it in SAL. */ arg1 = arg; - sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, 0, 0, 0, 0); if (! sals.nelts) { @@ -806,10 +807,10 @@ edit_command (char *arg, int from_tty) if (*arg1) error (_("Junk at end of line specification.")); - /* If line was specified by address, - first print exactly which line, and which file. - In this case, sal.symtab == 0 means address is outside - of all known source files, not that user failed to give a filename. */ + /* If line was specified by address, first print exactly which + line, and which file. In this case, sal.symtab == 0 means + address is outside of all known source files, not that user + failed to give a filename. */ if (*arg == '*') { struct gdbarch *gdbarch; @@ -832,8 +833,8 @@ edit_command (char *arg, int from_tty) sal.symtab->filename, sal.line); } - /* If what was given does not imply a symtab, it must be an undebuggable - symbol which means no source code. */ + /* If what was given does not imply a symtab, it must be an + undebuggable symbol which means no source code. */ if (sal.symtab == 0) error (_("No line number known for %s."), arg); @@ -875,7 +876,7 @@ list_command (char *arg, int from_tty) int linenum_beg = 0; char *p; - /* Pull in the current default source line if necessary */ + /* Pull in the current default source line if necessary. */ if (arg == 0 || arg[0] == '+' || arg[0] == '-') { set_default_source_symtab_and_line (); @@ -891,11 +892,13 @@ list_command (char *arg, int from_tty) return; } - /* "l -" lists previous ten lines, the ones before the ten just listed. */ + /* "l -" lists previous ten lines, the ones before the ten just + listed. */ if (strcmp (arg, "-") == 0) { print_source_lines (cursal.symtab, - max (get_first_line_listed () - get_lines_to_list (), 1), + max (get_first_line_listed () + - get_lines_to_list (), 1), get_first_line_listed (), 0); return; } @@ -914,7 +917,7 @@ list_command (char *arg, int from_tty) dummy_beg = 1; else { - sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, 0, 0, 0, 0); if (!sals.nelts) return; /* C++ */ @@ -947,9 +950,9 @@ list_command (char *arg, int from_tty) else { if (dummy_beg) - sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + sals_end = decode_line_1 (&arg1, 0, 0, 0, 0); else - sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0); + sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0); if (sals_end.nelts == 0) return; if (sals_end.nelts > 1) @@ -972,10 +975,11 @@ list_command (char *arg, int from_tty) if (dummy_beg && dummy_end) error (_("Two empty args do not say what lines to list.")); - /* if line was specified by address, + /* If line was specified by address, first print exactly which line, and which file. - In this case, sal.symtab == 0 means address is outside - of all known source files, not that user failed to give a filename. */ + + In this case, sal.symtab == 0 means address is outside of all + known source files, not that user failed to give a filename. */ if (*arg == '*') { struct gdbarch *gdbarch; @@ -998,9 +1002,9 @@ list_command (char *arg, int from_tty) sal.symtab->filename, sal.line); } - /* If line was not specified by just a line number, - and it does not imply a symtab, it must be an undebuggable symbol - which means no source code. */ + /* If line was not specified by just a line number, and it does not + imply a symtab, it must be an undebuggable symbol which means no + source code. */ if (!linenum_beg && sal.symtab == 0) error (_("No line number known for %s."), arg); @@ -1241,38 +1245,39 @@ show_user (char *args, int from_tty) } /* Search through names of commands and documentations for a certain - regular expression. -*/ + regular expression. */ + void apropos_command (char *searchstr, int from_tty) { - extern struct cmd_list_element *cmdlist; /*This is the main command list*/ regex_t pattern; - char *pattern_fastmap; - char errorbuffer[512]; + int code; - pattern_fastmap = xcalloc (256, sizeof (char)); if (searchstr == NULL) - error (_("REGEXP string is empty")); + error (_("REGEXP string is empty")); - if (regcomp(&pattern,searchstr,REG_ICASE) == 0) + code = regcomp (&pattern, searchstr, REG_ICASE); + if (code == 0) { - pattern.fastmap=pattern_fastmap; - re_compile_fastmap(&pattern); - apropos_cmd (gdb_stdout,cmdlist,&pattern,""); + struct cleanup *cleanups; + + cleanups = make_regfree_cleanup (&pattern); + apropos_cmd (gdb_stdout, cmdlist, &pattern, ""); + do_cleanups (cleanups); } else { - regerror(regcomp(&pattern,searchstr,REG_ICASE),NULL,errorbuffer,512); - error (_("Error in regular expression:%s"),errorbuffer); + char *err = get_regcomp_error (code, &pattern); + + make_cleanup (xfree, err); + error (_("Error in regular expression: %s"), err); } - xfree (pattern_fastmap); } /* Print a list of files and line numbers which a user may choose from - in order to list a function which was specified ambiguously (as with - `list classname::overloadedfuncname', for example). The vector in - SALS provides the filenames and line numbers. */ + in order to list a function which was specified ambiguously (as + with `list classname::overloadedfuncname', for example). The + vector in SALS provides the filenames and line numbers. */ static void ambiguous_line_spec (struct symtabs_and_lines *sals) @@ -1287,7 +1292,8 @@ ambiguous_line_spec (struct symtabs_and_lines *sals) static void set_debug (char *arg, int from_tty) { - printf_unfiltered (_("\"set debug\" must be followed by the name of a debug subcommand.\n")); + printf_unfiltered (_("\"set debug\" must be followed by " + "the name of a debug subcommand.\n")); help_list (setdebuglist, "set debug ", -1, gdb_stdout); } @@ -1332,8 +1338,9 @@ show_info_verbose (struct ui_file *file, int from_tty, const char *value) { if (info_verbose) - fprintf_filtered (file, _("\ -Verbose printing of informational messages is %s.\n"), value); + fprintf_filtered (file, + _("Verbose printing of informational messages is %s.\n"), + value); else fprintf_filtered (file, _("Verbosity is %s.\n"), value); } @@ -1366,8 +1373,8 @@ static void show_remote_timeout (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Timeout limit to wait for target to respond is %s.\n"), + fprintf_filtered (file, + _("Timeout limit to wait for target to respond is %s.\n"), value); } @@ -1375,8 +1382,8 @@ static void show_max_user_call_depth (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The max call depth for user-defined commands is %s.\n"), + fprintf_filtered (file, + _("The max call depth for user-defined commands is %s.\n"), value); } @@ -1397,7 +1404,8 @@ These commands are subject to frequent change, and may not be as\n\ well documented as user commands."), &cmdlist); add_cmd ("obscure", class_obscure, NULL, _("Obscure features."), &cmdlist); - add_cmd ("aliases", class_alias, NULL, _("Aliases of other commands."), &cmdlist); + add_cmd ("aliases", class_alias, NULL, + _("Aliases of other commands."), &cmdlist); add_cmd ("user-defined", class_user, NULL, _("\ User-defined commands.\n\ The commands in this class are those defined by the user.\n\ @@ -1421,7 +1429,7 @@ The commands below can be used to select other frames by number or address."), &cmdlist); add_cmd ("running", class_run, NULL, _("Running the program."), &cmdlist); - /* Define general commands. */ + /* Define general commands. */ add_com ("pwd", class_files, pwd_command, _("\ Print working directory. This is used for your program as well.")); @@ -1522,13 +1530,13 @@ Generic command for showing things about the debugger."), /* Another way to get at the same thing. */ add_info ("set", show_command, _("Show all GDB settings.")); - add_cmd ("commands", no_class, show_commands, _("\ + add_cmd ("commands", no_set_class, show_commands, _("\ Show the history of commands you typed.\n\ You can supply a command number to start with, or a `+' to start after\n\ the previous command number shown."), &showlist); - add_cmd ("version", no_class, show_version, + add_cmd ("version", no_set_class, show_version, _("Show what version of GDB this is."), &showlist); add_com ("while", class_support, while_command, _("\ @@ -1544,8 +1552,8 @@ followed by a new line. The nested commands must be entered one per line,\n\ and should be terminated by the word 'else' or `end'. If an else clause\n\ is used, the same rules apply to its nested commands as to the first ones.")); - /* If target is open when baud changes, it doesn't take effect until the - next open (I think, not sure). */ + /* If target is open when baud changes, it doesn't take effect until + the next open (I think, not sure). */ add_setshow_zinteger_cmd ("remotebaud", no_class, &baud_rate, _("\ Set baud rate for remote serial I/O."), _("\ Show baud rate for remote serial I/O."), _("\ @@ -1610,7 +1618,8 @@ Lines can be specified in these ways:\n\ FUNCTION, to list around beginning of that function,\n\ FILE:FUNCTION, to distinguish among like-named static functions.\n\ *ADDRESS, to list around the line containing that address.\n\ -With two args if one is empty it stands for ten lines away from the other arg.")); +With two args if one is empty it stands for ten lines away from \ +the other arg.")); if (!xdb_commands) add_com_alias ("l", "list", class_files, 1); @@ -1637,7 +1646,7 @@ Two arguments (separated by a comma) are taken as a range of memory to dump,\n\ this. Instead it adds support for the form ``(gdb) ! ls'' (i.e. the space is required). If the ``!'' command below is added the complains about no ``!'' command would be replaced by - complains about how the ``!'' command is broken :-) */ + complains about how the ``!'' command is broken :-) */ if (xdb_commands) add_com_alias ("!", "shell", class_support, 0); diff --git a/contrib/gdb-7/gdb/cli/cli-cmds.h b/contrib/gdb-7/gdb/cli/cli-cmds.h index 596870e0a3..e79dcf05d6 100644 --- a/contrib/gdb-7/gdb/cli/cli-cmds.h +++ b/contrib/gdb-7/gdb/cli/cli-cmds.h @@ -1,5 +1,6 @@ /* Header file for GDB CLI command implementation library. - Copyright (c) 2000,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + Copyright (c) 2000,2006,2007,2008,2009,2010,2011 + Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,19 +26,19 @@ extern struct cmd_list_element *cmdlist; extern struct cmd_list_element *infolist; -/* Chain containing all defined enable subcommands. */ +/* Chain containing all defined enable subcommands. */ extern struct cmd_list_element *enablelist; -/* Chain containing all defined disable subcommands. */ +/* Chain containing all defined disable subcommands. */ extern struct cmd_list_element *disablelist; -/* Chain containing all defined delete subcommands. */ +/* Chain containing all defined delete subcommands. */ extern struct cmd_list_element *deletelist; -/* Chain containing all defined detach subcommands. */ +/* Chain containing all defined detach subcommands. */ extern struct cmd_list_element *detachlist; @@ -45,15 +46,15 @@ extern struct cmd_list_element *detachlist; extern struct cmd_list_element *killlist; -/* Chain containing all defined toggle subcommands. */ +/* Chain containing all defined toggle subcommands. */ extern struct cmd_list_element *togglelist; -/* Chain containing all defined stop subcommands. */ +/* Chain containing all defined stop subcommands. */ extern struct cmd_list_element *stoplist; -/* Chain containing all defined "enable breakpoint" subcommands. */ +/* Chain containing all defined "enable breakpoint" subcommands. */ extern struct cmd_list_element *enablebreaklist; @@ -81,15 +82,15 @@ extern struct cmd_list_element *showhistlist; extern struct cmd_list_element *unsethistlist; -/* Chain containing all defined maintenance subcommands. */ +/* Chain containing all defined maintenance subcommands. */ extern struct cmd_list_element *maintenancelist; -/* Chain containing all defined "maintenance info" subcommands. */ +/* Chain containing all defined "maintenance info" subcommands. */ extern struct cmd_list_element *maintenanceinfolist; -/* Chain containing all defined "maintenance print" subcommands. */ +/* Chain containing all defined "maintenance print" subcommands. */ extern struct cmd_list_element *maintenanceprintlist; diff --git a/contrib/gdb-7/gdb/cli/cli-decode.c b/contrib/gdb-7/gdb/cli/cli-decode.c index 374bd19b83..093fec0355 100644 --- a/contrib/gdb-7/gdb/cli/cli-decode.c +++ b/contrib/gdb-7/gdb/cli/cli-decode.c @@ -1,7 +1,7 @@ /* Handle lists of commands, their decoding and documentation, for GDB. Copyright (c) 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002, 2004, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,12 +28,12 @@ #include "cli/cli-decode.h" #ifdef TUI -#include "tui/tui.h" /* For tui_active et.al. */ +#include "tui/tui.h" /* For tui_active et al. */ #endif #include "gdb_assert.h" -/* Prototypes for local functions */ +/* Prototypes for local functions. */ static void undef_cmd_error (char *, char *); @@ -139,10 +139,10 @@ set_cmd_completer (struct cmd_list_element *cmd, It should start with ? for a command that is an abbreviation or with * for a command that most users don't need to know about. - Add this command to command list *LIST. + Add this command to command list *LIST. Returns a pointer to the added command (not necessarily the head - of *LIST). */ + of *LIST). */ struct cmd_list_element * add_cmd (char *name, enum command_class class, void (*fun) (char *, int), @@ -210,12 +210,12 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int), } /* Deprecates a command CMD. - REPLACEMENT is the name of the command which should be used in place - of this command, or NULL if no such command exists. + REPLACEMENT is the name of the command which should be used in + place of this command, or NULL if no such command exists. This function does not check to see if command REPLACEMENT exists - since gdb may not have gotten around to adding REPLACEMENT when this - function is called. + since gdb may not have gotten around to adding REPLACEMENT when + this function is called. Returns a pointer to the deprecated command. */ @@ -236,7 +236,8 @@ struct cmd_list_element * add_alias_cmd (char *name, char *oldname, enum command_class class, int abbrev_flag, struct cmd_list_element **list) { - /* Must do this since lookup_cmd tries to side-effect its first arg */ + /* Must do this since lookup_cmd tries to side-effect its first + arg. */ char *copied_name; struct cmd_list_element *old; struct cmd_list_element *c; @@ -272,13 +273,14 @@ add_alias_cmd (char *name, char *oldname, enum command_class class, return c; } -/* Like add_cmd but adds an element for a command prefix: - a name that should be followed by a subcommand to be looked up - in another command list. PREFIXLIST should be the address - of the variable containing that list. */ +/* Like add_cmd but adds an element for a command prefix: a name that + should be followed by a subcommand to be looked up in another + command list. PREFIXLIST should be the address of the variable + containing that list. */ struct cmd_list_element * -add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int), +add_prefix_cmd (char *name, enum command_class class, + void (*fun) (char *, int), char *doc, struct cmd_list_element **prefixlist, char *prefixname, int allow_unknown, struct cmd_list_element **list) @@ -291,7 +293,7 @@ add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int), return c; } -/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ +/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ struct cmd_list_element * add_abbrev_prefix_cmd (char *name, enum command_class class, @@ -719,7 +721,7 @@ delete_cmd (char *name, struct cmd_list_element **list, return aliases; } -/* Shorthands to the commands above. */ +/* Shorthands to the commands above. */ /* Add an element to the list of info subcommands. */ @@ -760,19 +762,20 @@ add_com_alias (char *name, char *oldname, enum command_class class, name, or their documentation. */ void -apropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist, +apropos_cmd (struct ui_file *stream, + struct cmd_list_element *commandlist, struct re_pattern_buffer *regex, char *prefix) { struct cmd_list_element *c; int returnvalue; - /* Walk through the commands */ + /* Walk through the commands. */ for (c=commandlist;c;c=c->next) { - returnvalue = -1; /*Needed to avoid double printing*/ + returnvalue = -1; /* Needed to avoid double printing. */ if (c->name != NULL) { - /* Try to match against the name*/ + /* Try to match against the name. */ returnvalue = re_search (regex, c->name, strlen(c->name), 0, strlen (c->name), NULL); if (returnvalue >= 0) @@ -783,37 +786,35 @@ apropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist, } if (c->doc != NULL && returnvalue < 0) { - /* Try to match against documentation */ + /* Try to match against documentation. */ if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0) { print_help_for_command (c, prefix, 0 /* don't recurse */, stream); } } - /* Check if this command has subcommands and is not an abbreviation. - We skip listing subcommands of abbreviations in order to avoid - duplicates in the output. - */ + /* Check if this command has subcommands and is not an + abbreviation. We skip listing subcommands of abbreviations + in order to avoid duplicates in the output. */ if (c->prefixlist != NULL && !c->abbrev_flag) { /* Recursively call ourselves on the subcommand list, - passing the right prefix in. - */ + passing the right prefix in. */ apropos_cmd (stream,*c->prefixlist,regex,c->prefixname); } } } /* This command really has to deal with two things: - * 1) I want documentation on *this string* (usually called by - * "help commandname"). - * 2) I want documentation on *this list* (usually called by - * giving a command that requires subcommands. Also called by saying - * just "help".) - * - * I am going to split this into two seperate comamnds, help_cmd and - * help_list. - */ + 1) I want documentation on *this string* (usually called by + "help commandname"). + + 2) I want documentation on *this list* (usually called by giving a + command that requires subcommands. Also called by saying just + "help".) + + I am going to split this into two seperate comamnds, help_cmd and + help_list. */ void help_cmd (char *command, struct ui_file *stream) @@ -857,11 +858,11 @@ help_cmd (char *command, struct ui_file *stream) return; fprintf_filtered (stream, "\n"); - /* If this is a prefix command, print it's subcommands */ + /* If this is a prefix command, print it's subcommands. */ if (c->prefixlist) help_list (*c->prefixlist, c->prefixname, all_commands, stream); - /* If this is a class name, print all of the commands in the class */ + /* If this is a class name, print all of the commands in the class. */ if (c->func == NULL) help_list (cmdlist, "", c->class, stream); @@ -898,7 +899,8 @@ help_list (struct cmd_list_element *list, char *cmdtype, int len; char *cmdtype1, *cmdtype2; - /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */ + /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub". + */ len = strlen (cmdtype); cmdtype1 = (char *) alloca (len + 1); cmdtype1[0] = 0; @@ -941,7 +943,7 @@ Type \"help all\" for the list of all commands."); wrap_here (""); fputs_filtered ("documentation.\n", stream); fputs_filtered ("Type \"apropos word\" to search " - "for commands related to \"word\".\n", stream); + "for commands related to \"word\".\n", stream); fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n", stream); } @@ -957,7 +959,8 @@ help_all (struct ui_file *stream) { if (c->abbrev_flag) continue; - /* If this is a class name, print all of the commands in the class */ + /* If this is a class name, print all of the commands in the + class. */ if (c->func == NULL) { @@ -1020,7 +1023,7 @@ print_doc_line (struct ui_file *stream, char *str) /* Print one-line help for command C. If RECURSE is non-zero, also print one-line descriptions - of all prefixed subcommands. */ + of all prefixed subcommands. */ static void print_help_for_command (struct cmd_list_element *c, char *prefix, int recurse, struct ui_file *stream) @@ -1034,7 +1037,7 @@ print_help_for_command (struct cmd_list_element *c, char *prefix, int recurse, && c->abbrev_flag == 0) /* Subcommands of a prefix command typically have 'all_commands' as class. If we pass CLASS to recursive invocation, - most often we won't see anything. */ + most often we won't see anything. */ help_cmd_list (*c->prefixlist, all_commands, c->prefixname, 1, stream); } @@ -1072,14 +1075,15 @@ help_cmd_list (struct cmd_list_element *list, enum command_class class, else if (c->abbrev_flag == 0 && recurse && class == class_user && c->prefixlist != NULL) /* User-defined commands may be subcommands. */ - help_cmd_list (*c->prefixlist, class, c->prefixname, recurse, stream); + help_cmd_list (*c->prefixlist, class, c->prefixname, + recurse, stream); } } /* Search the input clist for 'command'. Return the command if found (or NULL if not), and return the number of commands - found in nfound */ + found in nfound. */ static struct cmd_list_element * find_cmd (char *command, int len, struct cmd_list_element *clist, @@ -1112,13 +1116,17 @@ find_command_name_length (const char *text) /* Treating underscores as part of command words is important so that "set args_foo()" doesn't get interpreted as "set args _foo()". */ - /* Some characters are only used for TUI specific commands. However, they - are always allowed for the sake of consistency. - The XDB compatibility characters are only allowed when using the right - mode because they clash with other GDB commands - specifically '/' is - used as a suffix for print, examine and display. - Note that this is larger than the character set allowed when creating - user-defined commands. */ + /* Some characters are only used for TUI specific commands. + However, they are always allowed for the sake of consistency. + + The XDB compatibility characters are only allowed when using the + right mode because they clash with other GDB commands - + specifically '/' is used as a suffix for print, examine and + display. + + Note that this is larger than the character set allowed when + creating user-defined commands. */ + while (isalnum (*p) || *p == '-' || *p == '_' /* Characters used by TUI specific commands. */ || *p == '+' || *p == '<' || *p == '>' || *p == '$' @@ -1185,7 +1193,7 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist, return 0; /* *text and p now bracket the first command word to lookup (and - it's length is len). We copy this into a local temporary */ + it's length is len). We copy this into a local temporary. */ command = (char *) alloca (len + 1); @@ -1197,10 +1205,8 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist, nfound = 0; found = find_cmd (command, len, clist, ignore_help_classes, &nfound); - /* - ** We didn't find the command in the entered case, so lower case it - ** and search again. - */ + /* We didn't find the command in the entered case, so lower case it + and search again. */ if (!found || nfound == 0) { for (tmp = 0; tmp < len; tmp++) @@ -1222,21 +1228,21 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist, /* Will be modified in calling routine if we know what the prefix command is. */ *result_list = 0; - return (struct cmd_list_element *) -1; /* Ambiguous. */ + return CMD_LIST_AMBIGUOUS; /* Ambiguous. */ } - /* We've matched something on this list. Move text pointer forward. */ + /* We've matched something on this list. Move text pointer forward. */ *text += len; if (found->cmd_pointer) { - /* We drop the alias (abbreviation) in favor of the command it is - pointing to. If the alias is deprecated, though, we need to + /* We drop the alias (abbreviation) in favor of the command it + is pointing to. If the alias is deprecated, though, we need to warn the user about it before we drop it. Note that while we are warning about the alias, we may also warn about the command itself and we will adjust the appropriate DEPRECATED_WARN_USER - flags */ + flags. */ if (found->flags & DEPRECATED_WARN_USER) deprecated_cmd_warning (&line); @@ -1255,17 +1261,17 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist, *result_list = clist; return found; } - else if (c == (struct cmd_list_element *) -1) + else if (c == CMD_LIST_AMBIGUOUS) { - /* We've gotten this far properly, but the next step - is ambiguous. We need to set the result list to the best + /* We've gotten this far properly, but the next step is + ambiguous. We need to set the result list to the best we've found (if an inferior hasn't already set it). */ if (result_list != NULL) if (!*result_list) - /* This used to say *result_list = *found->prefixlist + /* This used to say *result_list = *found->prefixlist. If that was correct, need to modify the documentation - at the top of this function to clarify what is supposed - to be going on. */ + at the top of this function to clarify what is + supposed to be going on. */ *result_list = found; return c; } @@ -1340,7 +1346,7 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, else return 0; } - else if (c == (struct cmd_list_element *) -1) + else if (c == CMD_LIST_AMBIGUOUS) { /* Ambigous. Local values should be off prefixlist or called values. */ @@ -1373,7 +1379,8 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, for (c = local_list; c; c = c->next) if (!strncmp (*line, c->name, amb_len)) { - if (strlen (ambbuf) + strlen (c->name) + 6 < (int) sizeof ambbuf) + if (strlen (ambbuf) + strlen (c->name) + 6 + < (int) sizeof ambbuf) { if (strlen (ambbuf)) strcat (ambbuf, ", "); @@ -1406,10 +1413,10 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, return 0; } -/* We are here presumably because an alias or command in *TEXT is - deprecated and a warning message should be generated. This function - decodes *TEXT and potentially generates a warning message as outlined - below. +/* We are here presumably because an alias or command in *TEXT is + deprecated and a warning message should be generated. This + function decodes *TEXT and potentially generates a warning message + as outlined below. Example for 'set endian big' which has a fictitious alias 'seb'. @@ -1419,8 +1426,8 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, If alias was used, and only the alias is deprecated: "warning: 'seb' an alias for the command 'set endian big' is deprecated." - If alias was used and command is deprecated (regardless of whether the - alias itself is deprecated: + If alias was used and command is deprecated (regardless of whether + the alias itself is deprecated: "warning: 'set endian big' (seb) is deprecated." @@ -1436,12 +1443,12 @@ deprecated_cmd_warning (char **text) struct cmd_list_element *cmd = NULL; if (!lookup_cmd_composition (*text, &alias, &prefix_cmd, &cmd)) - /* return if text doesn't evaluate to a command */ + /* Return if text doesn't evaluate to a command. */ return; if (!((alias ? (alias->flags & DEPRECATED_WARN_USER) : 0) || (cmd->flags & DEPRECATED_WARN_USER) ) ) - /* return if nothing is deprecated */ + /* Return if nothing is deprecated. */ return; printf_filtered ("Warning:"); @@ -1462,8 +1469,8 @@ deprecated_cmd_warning (char **text) printf_filtered ("' is deprecated.\n"); - /* If it is only the alias that is deprecated, we want to indicate the - new alias, otherwise we'll indicate the new command. */ + /* If it is only the alias that is deprecated, we want to indicate + the new alias, otherwise we'll indicate the new command. */ if (alias && !(cmd->flags & CMD_DEPRECATED)) { @@ -1480,7 +1487,7 @@ deprecated_cmd_warning (char **text) printf_filtered ("No alternative known.\n\n"); } - /* We've warned you, now we'll keep quiet */ + /* We've warned you, now we'll keep quiet. */ if (alias) alias->flags &= ~DEPRECATED_WARN_USER; @@ -1488,8 +1495,7 @@ deprecated_cmd_warning (char **text) } - -/* Look up the contents of LINE as a command in the command list 'cmdlist'. +/* Look up the contents of LINE as a command in the command list 'cmdlist'. Return 1 on success, 0 on failure. If LINE refers to an alias, *alias will point to that alias. @@ -1523,7 +1529,7 @@ lookup_cmd_composition (char *text, while (1) { /* Go through as many command lists as we need to - to find the command TEXT refers to. */ + to find the command TEXT refers to. */ prev_cmd = *cmd; @@ -1549,8 +1555,8 @@ lookup_cmd_composition (char *text, nfound = 0; *cmd = find_cmd (command, len, cur_list, 1, &nfound); - /* We didn't find the command in the entered case, so lower case it - and search again. + /* We didn't find the command in the entered case, so lower case + it and search again. */ if (!*cmd || nfound == 0) { @@ -1563,7 +1569,7 @@ lookup_cmd_composition (char *text, *cmd = find_cmd (command, len, cur_list, 1, &nfound); } - if (*cmd == (struct cmd_list_element *) -1) + if (*cmd == CMD_LIST_AMBIGUOUS) { return 0; /* ambiguous */ } @@ -1574,8 +1580,8 @@ lookup_cmd_composition (char *text, { if ((*cmd)->cmd_pointer) { - /* cmd was actually an alias, we note that an alias was used - (by assigning *alais) and we set *cmd. */ + /* cmd was actually an alias, we note that an alias was + used (by assigning *alais) and we set *cmd. */ *alias = *cmd; *cmd = (*cmd)->cmd_pointer; } @@ -1593,11 +1599,11 @@ lookup_cmd_composition (char *text, /* Helper function for SYMBOL_COMPLETION_FUNCTION. */ /* Return a vector of char pointers which point to the different - possible completions in LIST of TEXT. + possible completions in LIST of TEXT. WORD points in the same buffer as TEXT, and completions should be - returned relative to this position. For example, suppose TEXT is "foo" - and we want to complete to "foobar". If WORD is "oo", return + returned relative to this position. For example, suppose TEXT is + "foo" and we want to complete to "foobar". If WORD is "oo", return "oobar"; if WORD is "baz/foo", return "baz/foobar". */ char ** @@ -1686,7 +1692,7 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word) /* Helper function for SYMBOL_COMPLETION_FUNCTION. */ /* Return a vector of char pointers which point to the different - possible completions in CMD of TEXT. + possible completions in CMD of TEXT. WORD points in the same buffer as TEXT, and completions should be returned relative to this position. For example, suppose TEXT is "foo" @@ -1747,7 +1753,7 @@ complete_on_enum (const char *enumlist[], else { matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1) - * sizeof (char *))); + * sizeof (char *))); matchlist[matches] = (char *) 0; } @@ -1755,7 +1761,7 @@ complete_on_enum (const char *enumlist[], } -/* check function pointer */ +/* Check function pointer. */ int cmd_func_p (struct cmd_list_element *cmd) { @@ -1763,7 +1769,7 @@ cmd_func_p (struct cmd_list_element *cmd) } -/* call the command function */ +/* Call the command function. */ void cmd_func (struct cmd_list_element *cmd, char *args, int from_tty) { diff --git a/contrib/gdb-7/gdb/cli/cli-decode.h b/contrib/gdb-7/gdb/cli/cli-decode.h index 2764d417eb..e9749681cb 100644 --- a/contrib/gdb-7/gdb/cli/cli-decode.h +++ b/contrib/gdb-7/gdb/cli/cli-decode.h @@ -1,6 +1,6 @@ /* Header file for GDB command decoding library. - Copyright (c) 2000, 2003, 2007, 2008, 2009, 2010 + Copyright (c) 2000, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -41,9 +41,9 @@ cmd_types; /* This structure records one command'd definition. */ -/* This flag is used by the code executing commands to warn the user - the first time a deprecated command is used, see the 'flags' field in - the following struct. +/* This flag is used by the code executing commands to warn the user + the first time a deprecated command is used, see the 'flags' field + in the following struct. */ #define CMD_DEPRECATED 0x1 #define DEPRECATED_WARN_USER 0x2 @@ -94,7 +94,7 @@ struct cmd_list_element /* flags : a bitfield bit 0: (LSB) CMD_DEPRECATED, when 1 indicated that this command - is deprecated. It may be removed from gdb's command set in the + is deprecated. It may be removed from gdb's command set in the future. bit 1: DEPRECATED_WARN_USER, the user needs to be warned that @@ -109,8 +109,8 @@ struct cmd_list_element memory for replacement is malloc'ed. When a command is undeprecated or re-deprecated at runtime we don't want to risk calling free on statically allocated memory, so we check this - flag. - */ + flag. */ + int flags; /* If this command is deprecated, this is the replacement name. */ @@ -157,14 +157,16 @@ struct cmd_list_element skipped). It stops where we are supposed to stop completing (rl_point) and is '\0' terminated. - Return value is a malloc'd vector of pointers to possible completions - terminated with NULL. If there are no completions, returning a pointer - to a NULL would work but returning NULL itself is also valid. - WORD points in the same buffer as TEXT, and completions should be - returned relative to this position. For example, suppose TEXT is "foo" - and we want to complete to "foobar". If WORD is "oo", return - "oobar"; if WORD is "baz/foo", return "baz/foobar". */ - char **(*completer) (struct cmd_list_element *cmd, char *text, char *word); + Return value is a malloc'd vector of pointers to possible + completions terminated with NULL. If there are no completions, + returning a pointer to a NULL would work but returning NULL + itself is also valid. WORD points in the same buffer as TEXT, + and completions should be returned relative to this position. + For example, suppose TEXT is "foo" and we want to complete to + "foobar". If WORD is "oo", return "oobar"; if WORD is + "baz/foo", return "baz/foobar". */ + char **(*completer) (struct cmd_list_element *cmd, + char *text, char *word); /* Destruction routine for this command. If non-NULL, this is called when this command instance is destroyed. This may be @@ -175,14 +177,15 @@ struct cmd_list_element or "show"). */ cmd_types type; - /* Pointer to variable affected by "set" and "show". Doesn't matter - if type is not_set. */ + /* Pointer to variable affected by "set" and "show". Doesn't + matter if type is not_set. */ void *var; /* What kind of variable is *VAR? */ var_types var_type; - /* Pointer to NULL terminated list of enumerated values (like argv). */ + /* Pointer to NULL terminated list of enumerated values (like + argv). */ const char **enums; /* Pointer to command strings of user-defined commands */ @@ -207,6 +210,9 @@ struct cmd_list_element struct cmd_list_element *alias_chain; }; +/* Flag for an ambiguous cmd_list result. */ +#define CMD_LIST_AMBIGUOUS ((struct cmd_list_element *) -1) + /* API to the manipulation of command lists. */ extern struct cmd_list_element *add_cmd (char *, enum command_class, @@ -295,7 +301,7 @@ extern char **complete_on_enum (const char *enumlist[], char *, char *); extern void help_cmd_list (struct cmd_list_element *, enum command_class, char *, int, struct ui_file *); -/* Functions that implement commands about CLI commands. */ +/* Functions that implement commands about CLI commands. */ extern void help_cmd (char *, struct ui_file *); diff --git a/contrib/gdb-7/gdb/cli/cli-dump.c b/contrib/gdb-7/gdb/cli/cli-dump.c index 34d805cca5..ac6270e645 100644 --- a/contrib/gdb-7/gdb/cli/cli-dump.c +++ b/contrib/gdb-7/gdb/cli/cli-dump.c @@ -1,6 +1,6 @@ /* Dump-to-file commands, for GDB, the GNU debugger. - Copyright (c) 2002, 2005, 2007, 2008, 2009, 2010 + Copyright (c) 2002, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Red Hat. @@ -32,20 +32,11 @@ #include "target.h" #include "readline/readline.h" #include "gdbcore.h" +#include "cli/cli-utils.h" #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) -char * -skip_spaces (char *chp) -{ - if (chp == NULL) - return NULL; - while (isspace (*chp)) - chp++; - return chp; -} - char * scan_expression_with_cleanup (char **cmd, const char *def) { @@ -149,8 +140,8 @@ bfd_openw_with_cleanup (const char *filename, const char *target, if (!bfd_set_format (obfd, bfd_object)) error (_("bfd_openw_with_cleanup: %s."), bfd_errmsg (bfd_get_error ())); } - else if (*mode == 'a') /* Append to existing file */ - { /* FIXME -- doesn't work... */ + else if (*mode == 'a') /* Append to existing file. */ + { /* FIXME -- doesn't work... */ error (_("bfd_openw does not work with append.")); } else @@ -211,7 +202,9 @@ dump_bfd_file (const char *filename, const char *mode, | SEC_ALLOC | SEC_LOAD)); osection->entsize = 0; - bfd_set_section_contents (obfd, osection, buf, 0, len); + if (!bfd_set_section_contents (obfd, osection, buf, 0, len)) + warning (_("writing dump file '%s' (%s)"), filename, + bfd_errmsg (bfd_get_error ())); } static void @@ -430,7 +423,7 @@ add_dump_command (char *name, void (*func) (char *args, char *mode), c->doc = concat ("Append ", c->doc + 6, (char *)NULL); } -/* Opaque data for restore_section_callback. */ +/* Opaque data for restore_section_callback. */ struct callback_data { CORE_ADDR load_offset; CORE_ADDR load_start; @@ -455,7 +448,7 @@ restore_section_callback (bfd *ibfd, asection *isec, void *args) gdb_byte *buf; int ret; - /* Ignore non-loadable sections, eg. from elf files. */ + /* Ignore non-loadable sections, eg. from elf files. */ if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD)) return; @@ -463,7 +456,7 @@ restore_section_callback (bfd *ibfd, asection *isec, void *args) if (sec_end <= data->load_start || (data->load_end > 0 && sec_start >= data->load_end)) { - /* No, no useable data in this section. */ + /* No, no useable data in this section. */ printf_filtered (_("skipping section %s...\n"), bfd_section_name (ibfd, isec)); return; @@ -474,7 +467,7 @@ restore_section_callback (bfd *ibfd, asection *isec, void *args) transfer should start and end. */ if (sec_start < data->load_start) sec_offset = data->load_start - sec_start; - /* Size of a partial transfer: */ + /* Size of a partial transfer. */ sec_load_count -= sec_offset; if (data->load_end > 0 && sec_end > data->load_end) sec_load_count -= sec_end - data->load_end; @@ -520,7 +513,11 @@ restore_binary_file (char *filename, struct callback_data *data) /* Get the file size for reading. */ if (fseek (file, 0, SEEK_END) == 0) - len = ftell (file); + { + len = ftell (file); + if (len < 0) + perror_with_name (filename); + } else perror_with_name (filename); @@ -528,10 +525,10 @@ restore_binary_file (char *filename, struct callback_data *data) error (_("Start address is greater than length of binary file %s."), filename); - /* Chop off "len" if it exceeds the requested load_end addr. */ + /* Chop off "len" if it exceeds the requested load_end addr. */ if (data->load_end != 0 && data->load_end < len) len = data->load_end; - /* Chop off "len" if the requested load_start addr skips some bytes. */ + /* Chop off "len" if the requested load_start addr skips some bytes. */ if (data->load_start > 0) len -= data->load_start; @@ -551,7 +548,7 @@ restore_binary_file (char *filename, struct callback_data *data) if (fread (buf, 1, len, file) != len) perror_with_name (filename); - /* Now write the buffer into target memory. */ + /* Now write the buffer into target memory. */ len = target_write_memory (data->load_start + data->load_offset, buf, len); if (len != 0) warning (_("restore: memory write failed (%s)."), safe_strerror (len)); @@ -573,7 +570,7 @@ restore_command (char *args, int from_tty) data.load_start = 0; data.load_end = 0; - /* Parse the input arguments. First is filename (required). */ + /* Parse the input arguments. First is filename (required). */ filename = scan_filename_with_cleanup (&args, NULL); if (args != NULL && *args != '\0') { @@ -586,18 +583,18 @@ restore_command (char *args, int from_tty) args += strlen (binary_string); args = skip_spaces (args); } - /* Parse offset (optional). */ + /* Parse offset (optional). */ if (args != NULL && *args != '\0') data.load_offset = parse_and_eval_address (scan_expression_with_cleanup (&args, NULL)); if (args != NULL && *args != '\0') { - /* Parse start address (optional). */ + /* Parse start address (optional). */ data.load_start = parse_and_eval_long (scan_expression_with_cleanup (&args, NULL)); if (args != NULL && *args != '\0') { - /* Parse end address (optional). */ + /* Parse end address (optional). */ data.load_end = parse_and_eval_long (args); if (data.load_end <= data.load_start) error (_("Start must be less than end.")); @@ -617,10 +614,10 @@ restore_command (char *args, int from_tty) } else { - /* Open the file for loading. */ + /* Open the file for loading. */ ibfd = bfd_openr_with_cleanup (filename, NULL); - /* Process the sections. */ + /* Process the sections. */ bfd_map_over_sections (ibfd, restore_section_callback, &data); } return; @@ -668,13 +665,13 @@ _initialize_cli_dump (void) { struct cmd_list_element *c; - add_prefix_cmd ("dump", class_vars, dump_command, _("\ -Dump target code/data to a local file."), + add_prefix_cmd ("dump", class_vars, dump_command, + _("Dump target code/data to a local file."), &dump_cmdlist, "dump ", 0/*allow-unknown*/, &cmdlist); - add_prefix_cmd ("append", class_vars, append_command, _("\ -Append target code/data to a local file."), + add_prefix_cmd ("append", class_vars, append_command, + _("Append target code/data to a local file."), &append_cmdlist, "append ", 0/*allow-unknown*/, &cmdlist); @@ -689,32 +686,32 @@ Write the value of an expression to a raw binary file.\n\ Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\ the specified FILE in raw target ordered bytes."); - add_prefix_cmd ("srec", all_commands, srec_dump_command, _("\ -Write target code/data to an srec file."), + add_prefix_cmd ("srec", all_commands, srec_dump_command, + _("Write target code/data to an srec file."), &srec_cmdlist, "dump srec ", 0 /*allow-unknown*/, &dump_cmdlist); - add_prefix_cmd ("ihex", all_commands, ihex_dump_command, _("\ -Write target code/data to an intel hex file."), + add_prefix_cmd ("ihex", all_commands, ihex_dump_command, + _("Write target code/data to an intel hex file."), &ihex_cmdlist, "dump ihex ", 0 /*allow-unknown*/, &dump_cmdlist); - add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, _("\ -Write target code/data to a tekhex file."), + add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, + _("Write target code/data to a tekhex file."), &tekhex_cmdlist, "dump tekhex ", 0 /*allow-unknown*/, &dump_cmdlist); - add_prefix_cmd ("binary", all_commands, binary_dump_command, _("\ -Write target code/data to a raw binary file."), + add_prefix_cmd ("binary", all_commands, binary_dump_command, + _("Write target code/data to a raw binary file."), &binary_dump_cmdlist, "dump binary ", 0 /*allow-unknown*/, &dump_cmdlist); - add_prefix_cmd ("binary", all_commands, binary_append_command, _("\ -Append target code/data to a raw binary file."), + add_prefix_cmd ("binary", all_commands, binary_append_command, + _("Append target code/data to a raw binary file."), &binary_append_cmdlist, "append binary ", 0 /*allow-unknown*/, &append_cmdlist); @@ -786,5 +783,5 @@ OFFSET will be added to the base address of the file (default zero).\n\ If START and END are given, only the file contents within that range\n\ (file relative) will be restored to target memory.")); c->completer = filename_completer; - /* FIXME: completers for other commands. */ + /* FIXME: completers for other commands. */ } diff --git a/contrib/gdb-7/gdb/cli/cli-dump.h b/contrib/gdb-7/gdb/cli/cli-dump.h index a11e00ca3b..384aa488c3 100644 --- a/contrib/gdb-7/gdb/cli/cli-dump.h +++ b/contrib/gdb-7/gdb/cli/cli-dump.h @@ -1,6 +1,6 @@ /* Dump-to-file commands, for GDB, the GNU debugger. - Copyright (c) 2001, 2005, 2007, 2008, 2009, 2010 + Copyright (c) 2001, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -32,6 +32,4 @@ extern char *scan_expression_with_cleanup (char **cmd, const char *defname); extern FILE *fopen_with_cleanup (const char *filename, const char *mode); -extern char *skip_spaces (char *inp); - #endif diff --git a/contrib/gdb-7/gdb/cli/cli-interp.c b/contrib/gdb-7/gdb/cli/cli-interp.c index fd75c7a181..7a517e9e48 100644 --- a/contrib/gdb-7/gdb/cli/cli-interp.c +++ b/contrib/gdb-7/gdb/cli/cli-interp.c @@ -1,6 +1,6 @@ /* CLI Definitions for GDB, the GNU debugger. - Copyright (c) 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (c) 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -30,11 +30,13 @@ struct ui_out *cli_uiout; -/* These are the ui_out and the interpreter for the console interpreter. */ +/* These are the ui_out and the interpreter for the console + interpreter. */ /* Longjmp-safe wrapper for "execute_command". */ static struct gdb_exception safe_execute_command (struct ui_out *uiout, - char *command, int from_tty); + char *command, + int from_tty); struct captured_execute_command_args { char *command; @@ -56,8 +58,9 @@ cli_interpreter_resume (void *data) /*sync_execution = 1; */ - /* gdb_setup_readline will change gdb_stdout. If the CLI was previously - writing to gdb_stdout, then set it to the new gdb_stdout afterwards. */ + /* gdb_setup_readline will change gdb_stdout. If the CLI was + previously writing to gdb_stdout, then set it to the new + gdb_stdout afterwards. */ stream = cli_out_set_stream (cli_uiout, gdb_stdout); if (stream != gdb_stdout) @@ -101,12 +104,13 @@ cli_interpreter_exec (void *data, const char *command_str) safe_execute_command. */ char *str = strcpy (alloca (strlen (command_str) + 1), command_str); - /* gdb_stdout could change between the time cli_uiout was initialized - and now. Since we're probably using a different interpreter which has - a new ui_file for gdb_stdout, use that one instead of the default. + /* gdb_stdout could change between the time cli_uiout was + initialized and now. Since we're probably using a different + interpreter which has a new ui_file for gdb_stdout, use that one + instead of the default. - It is important that it gets reset everytime, since the user could - set gdb to use a different interpreter. */ + It is important that it gets reset everytime, since the user + could set gdb to use a different interpreter. */ old_stream = cli_out_set_stream (cli_uiout, gdb_stdout); result = safe_execute_command (cli_uiout, str, 1); cli_out_set_stream (cli_uiout, old_stream); diff --git a/contrib/gdb-7/gdb/cli/cli-logging.c b/contrib/gdb-7/gdb/cli/cli-logging.c index 497a7a3f6e..d0e25ea555 100644 --- a/contrib/gdb-7/gdb/cli/cli-logging.c +++ b/contrib/gdb-7/gdb/cli/cli-logging.c @@ -1,6 +1,6 @@ /* Command-line output logging for GDB, the GNU debugger. - Copyright (c) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (c) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +21,7 @@ #include "defs.h" #include "gdbcmd.h" #include "ui-out.h" +#include "gdb_assert.h" #include "gdb_string.h" @@ -32,6 +33,7 @@ struct saved_output_files struct ui_file *err; struct ui_file *log; struct ui_file *targ; + struct ui_file *targerr; }; static struct saved_output_files saved_output; static char *saved_filename; @@ -45,17 +47,95 @@ show_logging_filename (struct ui_file *file, int from_tty, value); } -int logging_overwrite; +static int logging_overwrite; + +static void +set_logging_overwrite (char *args, int from_tty, struct cmd_list_element *c) +{ + if (saved_filename) + warning (_("Currently logging to %s. Turn the logging off and on to " + "make the new setting effective."), saved_filename); +} + static void show_logging_overwrite (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Whether logging overwrites or appends to the log file is %s.\n"), + fprintf_filtered (file, + _("Whether logging overwrites or " + "appends to the log file is %s.\n"), value); } -int logging_redirect; +/* Value as configured by the user. */ +static int logging_redirect; + +/* The on-disk file in use if logging is currently active together + with redirection turned off (and therefore using tee_file_new). + For active logging with redirection the on-disk file is directly in + GDB_STDOUT and this variable is NULL. */ +static struct ui_file *logging_no_redirect_file; + +static void +set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c) +{ + struct cleanup *cleanups = NULL; + struct ui_file *output, *new_logging_no_redirect_file; + + if (saved_filename == NULL + || (logging_redirect != 0 && logging_no_redirect_file == NULL) + || (logging_redirect == 0 && logging_no_redirect_file != NULL)) + return; + + if (logging_redirect != 0) + { + gdb_assert (logging_no_redirect_file != NULL); + + /* ui_out_redirect still has not been called for next + gdb_stdout. */ + cleanups = make_cleanup_ui_file_delete (gdb_stdout); + + output = logging_no_redirect_file; + new_logging_no_redirect_file = NULL; + + if (from_tty) + fprintf_unfiltered (saved_output.out, "Redirecting output to %s.\n", + logging_filename); + } + else + { + gdb_assert (logging_no_redirect_file == NULL); + output = tee_file_new (saved_output.out, 0, gdb_stdout, 0); + if (output == NULL) + perror_with_name (_("set logging")); + new_logging_no_redirect_file = gdb_stdout; + + if (from_tty) + fprintf_unfiltered (saved_output.out, "Copying output to %s.\n", + logging_filename); + } + + gdb_stdout = output; + gdb_stderr = output; + gdb_stdlog = output; + gdb_stdtarg = output; + gdb_stdtargerr = output; + logging_no_redirect_file = new_logging_no_redirect_file; + + /* There is a former output pushed on the ui_out_redirect stack. We + want to replace it by OUTPUT so we must pop the former value + first. We should either do both the pop and push or to do + neither of it. At least do not try to push OUTPUT if the pop + already failed. */ + + if (ui_out_redirect (uiout, NULL) < 0 + || ui_out_redirect (uiout, output) < 0) + warning (_("Current output protocol does not support redirection")); + + if (logging_redirect != 0) + do_cleanups (cleanups); +} + static void show_logging_redirect (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -70,14 +150,21 @@ pop_output_files (void) /* Only delete one of the files -- they are all set to the same value. */ ui_file_delete (gdb_stdout); + if (logging_no_redirect_file) + { + ui_file_delete (logging_no_redirect_file); + logging_no_redirect_file = NULL; + } gdb_stdout = saved_output.out; gdb_stderr = saved_output.err; gdb_stdlog = saved_output.log; gdb_stdtarg = saved_output.targ; + gdb_stdtargerr = saved_output.targ; saved_output.out = NULL; saved_output.err = NULL; saved_output.log = NULL; saved_output.targ = NULL; + saved_output.targerr = NULL; ui_out_redirect (uiout, NULL); } @@ -104,18 +191,25 @@ handle_redirections (int from_tty) /* Redirects everything to gdb_stdout while this is running. */ if (!logging_redirect) { - output = tee_file_new (gdb_stdout, 0, output, 1); + struct ui_file *no_redirect_file = output; + + output = tee_file_new (gdb_stdout, 0, no_redirect_file, 0); if (output == NULL) perror_with_name (_("set logging")); - discard_cleanups (cleanups); - cleanups = make_cleanup_ui_file_delete (output); + make_cleanup_ui_file_delete (output); if (from_tty) fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n", logging_filename); + logging_no_redirect_file = no_redirect_file; + } + else + { + gdb_assert (logging_no_redirect_file == NULL); + + if (from_tty) + fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n", + logging_filename); } - else if (from_tty) - fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n", - logging_filename); discard_cleanups (cleanups); @@ -124,13 +218,15 @@ handle_redirections (int from_tty) saved_output.err = gdb_stderr; saved_output.log = gdb_stdlog; saved_output.targ = gdb_stdtarg; + saved_output.targerr = gdb_stdtargerr; gdb_stdout = output; gdb_stderr = output; gdb_stdlog = output; gdb_stdtarg = output; + gdb_stdtargerr = output; - if (ui_out_redirect (uiout, gdb_stdout) < 0) + if (ui_out_redirect (uiout, output) < 0) warning (_("Current output protocol does not support redirection")); } @@ -163,13 +259,12 @@ set_logging_off (char *args, int from_tty) static void set_logging_command (char *args, int from_tty) { - printf_unfiltered (_("\ -\"set logging\" lets you log output to a file.\n\ -Usage: set logging on [FILENAME]\n\ - set logging off\n\ - set logging file FILENAME\n\ - set logging overwrite [on|off]\n\ - set logging redirect [on|off]\n")); + printf_unfiltered (_("\"set logging\" lets you log output to a file.\n" + "Usage: set logging on [FILENAME]\n" + " set logging off\n" + " set logging file FILENAME\n" + " set logging overwrite [on|off]\n" + " set logging redirect [on|off]\n")); } static void @@ -187,10 +282,20 @@ show_logging_command (char *args, int from_tty) else printf_unfiltered (_("Logs will be appended to the log file.\n")); - if (logging_redirect) - printf_unfiltered (_("Output will be sent only to the log file.\n")); + if (saved_filename) + { + if (logging_redirect) + printf_unfiltered (_("Output is being sent only to the log file.\n")); + else + printf_unfiltered (_("Output is being logged and displayed.\n")); + } else - printf_unfiltered (_("Output will be logged and displayed.\n")); + { + if (logging_redirect) + printf_unfiltered (_("Output will be sent only to the log file.\n")); + else + printf_unfiltered (_("Output will be logged and displayed.\n")); + } } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -211,7 +316,7 @@ _initialize_cli_logging (void) Set whether logging overwrites or appends to the log file."), _("\ Show whether logging overwrites or appends to the log file."), _("\ If set, logging overrides the log file."), - NULL, + set_logging_overwrite, show_logging_overwrite, &set_logging_cmdlist, &show_logging_cmdlist); add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\ @@ -219,7 +324,7 @@ Set the logging output mode."), _("\ Show the logging output mode."), _("\ If redirect is off, output will go to both the screen and the log file.\n\ If redirect is on, output will go only to the log file."), - NULL, + set_logging_redirect, show_logging_redirect, &set_logging_cmdlist, &show_logging_cmdlist); add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\ diff --git a/contrib/gdb-7/gdb/cli/cli-script.c b/contrib/gdb-7/gdb/cli/cli-script.c index 9056773e28..5903015be3 100644 --- a/contrib/gdb-7/gdb/cli/cli-script.c +++ b/contrib/gdb-7/gdb/cli/cli-script.c @@ -2,7 +2,7 @@ Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -36,7 +36,7 @@ #include "python/python.h" -/* Prototypes for local functions */ +/* Prototypes for local functions. */ static enum command_control_type recurse_read_control_structure (char * (*read_next_line_func) (void), @@ -65,7 +65,8 @@ struct user_args { struct user_args *next; /* It is necessary to store a malloced copy of the command line to - ensure that the arguments are not overwritten before they are used. */ + ensure that the arguments are not overwritten before they are + used. */ char *command; struct { @@ -164,7 +165,8 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* loop_break to break out of a while loop, print it and continue. */ + /* loop_break to break out of a while loop, print it and + continue. */ if (list->control_type == break_control) { ui_out_field_string (uiout, NULL, "loop_break"); @@ -173,13 +175,14 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* A while command. Recursively print its subcommands and continue. */ + /* A while command. Recursively print its subcommands and + continue. */ if (list->control_type == while_control || list->control_type == while_stepping_control) { - /* For while-stepping, the line includes the 'while-stepping' token. - See comment in process_next_line for explanation. Here, - take care not print 'while-stepping' twice. */ + /* For while-stepping, the line includes the 'while-stepping' + token. See comment in process_next_line for explanation. + Here, take care not print 'while-stepping' twice. */ if (list->control_type == while_control) ui_out_field_fmt (uiout, NULL, "while %s", list->line); else @@ -194,12 +197,13 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* An if command. Recursively print both arms before continueing. */ + /* An if command. Recursively print both arms before + continueing. */ if (list->control_type == if_control) { ui_out_field_fmt (uiout, NULL, "if %s", list->line); ui_out_text (uiout, "\n"); - /* The true arm. */ + /* The true arm. */ print_command_lines (uiout, list->body_list[0], depth + 1); /* Show the false arm if it exists. */ @@ -220,7 +224,8 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* A commands command. Print the breakpoint commands and continue. */ + /* A commands command. Print the breakpoint commands and + continue. */ if (list->control_type == commands_control) { if (*(list->line)) @@ -251,7 +256,7 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* ignore illegal command type and try next */ + /* Ignore illegal command type and try next. */ list = list->next; } /* while (list) */ } @@ -263,7 +268,7 @@ clear_hook_in_cleanup (void *data) { struct cmd_list_element *c = data; - c->hook_in = 0; /* Allow hook to work again once it is complete */ + c->hook_in = 0; /* Allow hook to work again once it is complete. */ } void @@ -272,7 +277,7 @@ execute_cmd_pre_hook (struct cmd_list_element *c) if ((c->hook_pre) && (!c->hook_in)) { struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); - c->hook_in = 1; /* Prevent recursive hooking */ + c->hook_in = 1; /* Prevent recursive hooking. */ execute_user_command (c->hook_pre, (char *) 0); do_cleanups (cleanups); } @@ -285,7 +290,7 @@ execute_cmd_post_hook (struct cmd_list_element *c) { struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); - c->hook_in = 1; /* Prevent recursive hooking */ + c->hook_in = 1; /* Prevent recursive hooking. */ execute_user_command (c->hook_post, (char *) 0); do_cleanups (cleanups); } @@ -348,8 +353,8 @@ execute_user_command (struct cmd_list_element *c, char *args) do_cleanups (old_chain); } -/* This function is called every time GDB prints a prompt. - It ensures that errors and the like to not confuse the command tracing. */ +/* This function is called every time GDB prints a prompt. It ensures + that errors and the like do not confuse the command tracing. */ void reset_command_nest_depth (void) @@ -522,8 +527,8 @@ execute_control_command (struct command_line *cmd) val_mark = value_mark (); val = evaluate_expression (expr); - /* Choose which arm to take commands from based on the value of the - conditional expression. */ + /* Choose which arm to take commands from based on the value + of the conditional expression. */ if (value_true (val)) current = *cmd->body_list; else if (cmd->body_count == 2) @@ -549,8 +554,8 @@ execute_control_command (struct command_line *cmd) } case commands_control: { - /* Breakpoint commands list, record the commands in the breakpoint's - command list and return. */ + /* Breakpoint commands list, record the commands in the + breakpoint's command list and return. */ new_line = insert_args (cmd->line); if (!new_line) break; @@ -576,7 +581,7 @@ execute_control_command (struct command_line *cmd) } /* Like execute_control_command, but first set - suppress_next_print_command_trace. */ + suppress_next_print_command_trace. */ enum command_control_type execute_control_command_untraced (struct command_line *cmd) @@ -721,8 +726,8 @@ setup_user_args (char *p) return old_chain; } -/* Given character string P, return a point to the first argument ($arg), - or NULL if P contains no arguments. */ +/* Given character string P, return a point to the first argument + ($arg), or NULL if P contains no arguments. */ static char * locate_arg (char *p) @@ -738,7 +743,8 @@ locate_arg (char *p) } /* Insert the user defined arguments stored in user_arg into the $arg - arguments found in line, with the updated copy being placed into nline. */ + arguments found in line, with the updated copy being placed into + nline. */ static char * insert_args (char *line) @@ -751,7 +757,8 @@ insert_args (char *line) if (user_args == NULL) return xstrdup (line); - /* First we need to know how much memory to allocate for the new line. */ + /* First we need to know how much memory to allocate for the new + line. */ save_line = line; len = 0; while ((p = locate_arg (line))) @@ -883,11 +890,12 @@ read_next_line (void) return command_line_input (prompt_ptr, instream == stdin, "commands"); } -/* Process one input line. If the command is an "end", - return such an indication to the caller. If PARSE_COMMANDS is true, - strip leading whitespace (trailing whitespace is always stripped) - in the line, attempt to recognize GDB control commands, and also - return an indication if the command is an "else" or a nop. +/* Process one input line. If the command is an "end", return such an + indication to the caller. If PARSE_COMMANDS is true, strip leading + whitespace (trailing whitespace is always stripped) in the line, + attempt to recognize GDB control commands, and also return an + indication if the command is an "else" or a nop. + Otherwise, only "end" is recognized. */ static enum misc_command_type @@ -912,21 +920,21 @@ process_next_line (char *p, struct command_line **command, int parse_commands, while (p_start < p_end && (*p_start == ' ' || *p_start == '\t')) p_start++; - /* 'end' is always recognized, regardless of parse_commands value. + /* 'end' is always recognized, regardless of parse_commands value. We also permit whitespace before end and after. */ if (p_end - p_start == 3 && !strncmp (p_start, "end", 3)) return end_command; if (parse_commands) { - /* If commands are parsed, we skip initial spaces. Otherwise, + /* If commands are parsed, we skip initial spaces. Otherwise, which is the case for Python commands and documentation (see the 'document' command), spaces are preserved. */ p = p_start; /* Blanks and comments don't really do anything, but we need to - distinguish them from else, end and other commands which can be - executed. */ + distinguish them from else, end and other commands which can + be executed. */ if (p_end == p || p[0] == '#') return nop_command; @@ -934,8 +942,8 @@ process_next_line (char *p, struct command_line **command, int parse_commands, if (p_end - p == 4 && !strncmp (p, "else", 4)) return else_command; - /* Check for while, if, break, continue, etc and build a new command - line structure for them. */ + /* Check for while, if, break, continue, etc and build a new + command line structure for them. */ if ((p_end - p >= 14 && !strncmp (p, "while-stepping", 14)) || (p_end - p >= 8 && !strncmp (p, "stepping", 8)) || (p_end - p >= 2 && !strncmp (p, "ws", 2))) @@ -945,11 +953,12 @@ process_next_line (char *p, struct command_line **command, int parse_commands, include 'while-stepping'. For 'ws' alias, the command will have 'ws', not expanded - to 'while-stepping'. This is intentional -- we don't + to 'while-stepping'. This is intentional -- we don't really want frontend to send a command list with 'ws', - and next break-info returning command line with 'while-stepping'. - This should work, but might cause the breakpoint to be marked as - changed while it's actually not. */ + and next break-info returning command line with + 'while-stepping'. This should work, but might cause the + breakpoint to be marked as changed while it's actually + not. */ *command = build_command_line (while_stepping_control, p); } else if (p_end - p > 5 && !strncmp (p, "while", 5)) @@ -1040,11 +1049,9 @@ process_next_line (char *p, struct command_line **command, int parse_commands, return ok_command; } -/* Recursively read in the control structures and create a command_line - structure from them. Use read_next_line_func to obtain lines of - the command. - -*/ +/* Recursively read in the control structures and create a + command_line structure from them. Use read_next_line_func to + obtain lines of the command. */ static enum command_control_type recurse_read_control_structure (char * (*read_next_line_func) (void), @@ -1178,8 +1185,9 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands, { if (deprecated_readline_begin_hook) { - /* Note - intentional to merge messages with no newline */ - (*deprecated_readline_begin_hook) ("%s %s\n", prompt_arg, END_MESSAGE); + /* Note - intentional to merge messages with no newline. */ + (*deprecated_readline_begin_hook) ("%s %s\n", prompt_arg, + END_MESSAGE); } else { @@ -1472,7 +1480,8 @@ define_command (char *comname, int from_tty) hookc = 0; if (!hookc) { - warning (_("Your new `%s' command does not hook any existing command."), + warning (_("Your new `%s' command does not " + "hook any existing command."), comfull); if (!query (_("Proceed? "))) error (_("Not confirmed.")); @@ -1482,7 +1491,7 @@ define_command (char *comname, int from_tty) comname = xstrdup (comname); /* If the rest of the commands will be case insensitive, this one - should behave in the same manner. */ + should behave in the same manner. */ for (tem = comname; *tem; tem++) if (isupper (*tem)) *tem = tolower (*tem); @@ -1506,14 +1515,15 @@ define_command (char *comname, int from_tty) { case CMD_PRE_HOOK: hookc->hook_pre = newc; /* Target gets hooked. */ - newc->hookee_pre = hookc; /* We are marked as hooking target cmd. */ + newc->hookee_pre = hookc; /* We are marked as hooking target cmd. */ break; case CMD_POST_HOOK: hookc->hook_post = newc; /* Target gets hooked. */ - newc->hookee_post = hookc; /* We are marked as hooking target cmd. */ + newc->hookee_post = hookc; /* We are marked as hooking + target cmd. */ break; default: - /* Should never come here as hookc would be 0. */ + /* Should never come here as hookc would be 0. */ internal_error (__FILE__, __LINE__, _("bad switch")); } } @@ -1592,7 +1602,7 @@ wrapped_read_command_file (struct ui_out *uiout, void *data) read_command_file (args->stream); } -/* Used to implement source_command */ +/* Used to implement source_command. */ void script_from_file (FILE *stream, const char *file) @@ -1610,8 +1620,8 @@ script_from_file (FILE *stream, const char *file) make_cleanup (source_cleanup_lines, &old_lines); source_line_number = 0; source_file_name = file; - /* This will get set every time we read a line. So it won't stay "" for - long. */ + /* This will get set every time we read a line. So it won't stay "" + for long. */ error_pre_print = ""; { diff --git a/contrib/gdb-7/gdb/cli/cli-script.h b/contrib/gdb-7/gdb/cli/cli-script.h index 6cdcfd299c..9567f6e9a0 100644 --- a/contrib/gdb-7/gdb/cli/cli-script.h +++ b/contrib/gdb-7/gdb/cli/cli-script.h @@ -1,5 +1,5 @@ /* Header file for GDB CLI command implementation library. - Copyright (c) 2000, 2002, 2007, 2008, 2009, 2010 + Copyright (c) 2000, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify diff --git a/contrib/gdb-7/gdb/cli/cli-setshow.c b/contrib/gdb-7/gdb/cli/cli-setshow.c index 37f7918ef6..6acdd9156c 100644 --- a/contrib/gdb-7/gdb/cli/cli-setshow.c +++ b/contrib/gdb-7/gdb/cli/cli-setshow.c @@ -1,6 +1,6 @@ /* Handle set and show GDB commands. - Copyright (c) 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (c) 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ #include "cli/cli-cmds.h" #include "cli/cli-setshow.h" -/* Prototypes for local functions */ +/* Prototypes for local functions. */ static int parse_binary_operation (char *); @@ -58,7 +58,7 @@ parse_auto_binary_operation (const char *arg) return AUTO_BOOLEAN_AUTO; } error (_("\"on\", \"off\" or \"auto\" expected.")); - return AUTO_BOOLEAN_AUTO; /* pacify GCC */ + return AUTO_BOOLEAN_AUTO; /* Pacify GCC. */ } static int @@ -117,10 +117,10 @@ deprecated_show_value_hack (struct ui_file *ignore_file, } } -/* Do a "set" or "show" command. ARG is NULL if no argument, or the text - of the argument, and FROM_TTY is nonzero if this command is being entered - directly by the user (i.e. these are just like any other - command). C is the command list element for the command. */ +/* Do a "set" or "show" command. ARG is NULL if no argument, or the + text of the argument, and FROM_TTY is nonzero if this command is + being entered directly by the user (i.e. these are just like any + other command). C is the command list element for the command. */ void do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) @@ -249,7 +249,8 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) const char *match = NULL; char *p; - /* if no argument was supplied, print an informative error message */ + /* If no argument was supplied, print an informative error + message. */ if (arg == NULL) { char *msg; @@ -268,7 +269,8 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) strcat (msg, ", "); strcat (msg, c->enums[i]); } - error (_("Requires an argument. Valid arguments are %s."), msg); + error (_("Requires an argument. Valid arguments are %s."), + msg); } p = strchr (arg, ' '); @@ -286,7 +288,7 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) { match = c->enums[i]; nmatches = 1; - break; /* exact match. */ + break; /* Exact match. */ } else { @@ -350,7 +352,8 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) break; default: internal_error (__FILE__, __LINE__, - _("do_setshow_command: invalid var_auto_boolean")); + _("do_setshow_command: " + "invalid var_auto_boolean")); break; } break; @@ -431,18 +434,21 @@ cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix) } else { - struct cleanup *option_chain - = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); - - ui_out_text (uiout, prefix); - ui_out_field_string (uiout, "name", list->name); - ui_out_text (uiout, ": "); - if (list->type == show_cmd) - do_setshow_command ((char *) NULL, from_tty, list); - else - cmd_func (list, NULL, from_tty); - /* Close the tuple. */ - do_cleanups (option_chain); + if (list->class != no_set_class) + { + struct cleanup *option_chain + = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); + + ui_out_text (uiout, prefix); + ui_out_field_string (uiout, "name", list->name); + ui_out_text (uiout, ": "); + if (list->type == show_cmd) + do_setshow_command ((char *) NULL, from_tty, list); + else + cmd_func (list, NULL, from_tty); + /* Close the tuple. */ + do_cleanups (option_chain); + } } } /* Close the tuple. */ diff --git a/contrib/gdb-7/gdb/cli/cli-setshow.h b/contrib/gdb-7/gdb/cli/cli-setshow.h index b168ff8ba1..3cace8bd9b 100644 --- a/contrib/gdb-7/gdb/cli/cli-setshow.h +++ b/contrib/gdb-7/gdb/cli/cli-setshow.h @@ -1,5 +1,5 @@ /* Header file for GDB CLI set and show commands implementation. - Copyright (c) 2000, 2001, 2007, 2008, 2009, 2010 + Copyright (c) 2000, 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -22,10 +22,10 @@ struct cmd_list_element; /* Exported to cli/cli-cmds.c and gdb/top.c */ -/* Do a "set" or "show" command. ARG is NULL if no argument, or the text - of the argument, and FROM_TTY is nonzero if this command is being entered - directly by the user (i.e. these are just like any other - command). C is the command list element for the command. */ +/* Do a "set" or "show" command. ARG is NULL if no argument, or the + text of the argument, and FROM_TTY is nonzero if this command is + being entered directly by the user (i.e. these are just like any + other command). C is the command list element for the command. */ extern void do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c); diff --git a/contrib/gdb-7/gdb/cli/cli-utils.c b/contrib/gdb-7/gdb/cli/cli-utils.c new file mode 100644 index 0000000000..62a2f12c49 --- /dev/null +++ b/contrib/gdb-7/gdb/cli/cli-utils.c @@ -0,0 +1,247 @@ +/* CLI utilities. + + Copyright (c) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "cli/cli-utils.h" +#include "gdb_string.h" +#include "value.h" +#include "gdb_assert.h" + +#include + +/* *PP is a string denoting a number. Get the number of the. Advance + *PP after the string and any trailing whitespace. + + Currently the string can either be a number, or "$" followed by the + name of a convenience variable, or ("$" or "$$") followed by digits. + + TRAILER is a character which can be found after the number; most + commonly this is `-'. If you don't want a trailer, use \0. */ + +static int +get_number_trailer (char **pp, int trailer) +{ + int retval = 0; /* default */ + char *p = *pp; + + if (*p == '$') + { + struct value *val = value_from_history_ref (p, &p); + + if (val) /* Value history reference */ + { + if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT) + retval = value_as_long (val); + else + { + printf_filtered (_("History value must have integer type.")); + retval = 0; + } + } + else /* Convenience variable */ + { + /* Internal variable. Make a copy of the name, so we can + null-terminate it to pass to lookup_internalvar(). */ + char *varname; + char *start = ++p; + LONGEST val; + + while (isalnum (*p) || *p == '_') + p++; + varname = (char *) alloca (p - start + 1); + strncpy (varname, start, p - start); + varname[p - start] = '\0'; + if (get_internalvar_integer (lookup_internalvar (varname), &val)) + retval = (int) val; + else + { + printf_filtered (_("Convenience variable must " + "have integer value.\n")); + retval = 0; + } + } + } + else + { + if (*p == '-') + ++p; + while (*p >= '0' && *p <= '9') + ++p; + if (p == *pp) + /* There is no number here. (e.g. "cond a == b"). */ + { + /* Skip non-numeric token. */ + while (*p && !isspace((int) *p)) + ++p; + /* Return zero, which caller must interpret as error. */ + retval = 0; + } + else + retval = atoi (*pp); + } + if (!(isspace (*p) || *p == '\0' || *p == trailer)) + { + /* Trailing junk: return 0 and let caller print error msg. */ + while (!(isspace (*p) || *p == '\0' || *p == trailer)) + ++p; + retval = 0; + } + p = skip_spaces (p); + *pp = p; + return retval; +} + +/* See documentation in cli-utils.h. */ + +int +get_number (char **pp) +{ + return get_number_trailer (pp, '\0'); +} + +/* See documentation in cli-utils.h. */ + +void +init_number_or_range (struct get_number_or_range_state *state, + char *string) +{ + memset (state, 0, sizeof (*state)); + state->string = string; +} + +/* See documentation in cli-utils.h. */ + +int +get_number_or_range (struct get_number_or_range_state *state) +{ + if (*state->string != '-') + { + /* Default case: state->string is pointing either to a solo + number, or to the first number of a range. */ + state->last_retval = get_number_trailer (&state->string, '-'); + if (*state->string == '-') + { + char **temp; + + /* This is the start of a range ( - ). + Skip the '-', parse and remember the second number, + and also remember the end of the final token. */ + + temp = &state->end_ptr; + state->end_ptr = skip_spaces (state->string + 1); + state->end_value = get_number (temp); + if (state->end_value < state->last_retval) + { + error (_("inverted range")); + } + else if (state->end_value == state->last_retval) + { + /* Degenerate range (number1 == number2). Advance the + token pointer so that the range will be treated as a + single number. */ + state->string = state->end_ptr; + } + else + state->in_range = 1; + } + } + else if (! state->in_range) + error (_("negative value")); + else + { + /* state->string points to the '-' that betokens a range. All + number-parsing has already been done. Return the next + integer value (one greater than the saved previous value). + Do not advance the token pointer until the end of range + is reached. */ + + if (++state->last_retval == state->end_value) + { + /* End of range reached; advance token pointer. */ + state->string = state->end_ptr; + state->in_range = 0; + } + } + state->finished = *state->string == '\0'; + return state->last_retval; +} + +/* Accept a number and a string-form list of numbers such as is + accepted by get_number_or_range. Return TRUE if the number is + in the list. + + By definition, an empty list includes all numbers. This is to + be interpreted as typing a command such as "delete break" with + no arguments. */ + +int +number_is_in_list (char *list, int number) +{ + struct get_number_or_range_state state; + + if (list == NULL || *list == '\0') + return 1; + + init_number_or_range (&state, list); + while (!state.finished) + { + int gotnum = get_number_or_range (&state); + + if (gotnum == 0) + error (_("Args must be numbers or '$' variables.")); + if (gotnum == number) + return 1; + } + return 0; +} + +/* See documentation in cli-utils.h. */ + +char * +skip_spaces (char *chp) +{ + if (chp == NULL) + return NULL; + while (*chp && isspace (*chp)) + chp++; + return chp; +} + +/* See documentation in cli-utils.h. */ + +char * +skip_to_space (char *chp) +{ + if (chp == NULL) + return NULL; + while (*chp && !isspace (*chp)) + chp++; + return chp; +} + +/* See documentation in cli-utils.h. */ + +char * +remove_trailing_whitespace (const char *start, char *s) +{ + while (s > start && isspace (*(s - 1))) + --s; + + return s; +} diff --git a/contrib/gdb-7/gdb/cli/cli-utils.h b/contrib/gdb-7/gdb/cli/cli-utils.h new file mode 100644 index 0000000000..8a6e5b35dd --- /dev/null +++ b/contrib/gdb-7/gdb/cli/cli-utils.h @@ -0,0 +1,106 @@ +/* CLI utilities. + + Copyright (c) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef CLI_UTILS_H +#define CLI_UTILS_H + +/* *PP is a string denoting a number. Get the number of the. Advance + *PP after the string and any trailing whitespace. + + Currently the string can either be a number, or "$" followed by the + name of a convenience variable, or ("$" or "$$") followed by digits. */ + +extern int get_number (char **); + +/* An object of this type is passed to get_number_or_range. It must + be initialized by calling init_number_or_range. This type is + defined here so that it can be stack-allocated, but all members + other than `finished' and `string' should be treated as opaque. */ + +struct get_number_or_range_state +{ + /* Non-zero if parsing has completed. */ + int finished; + + /* The string being parsed. When parsing has finished, this points + past the last parsed token. */ + char *string; + + /* Last value returned. */ + int last_retval; + + /* When parsing a range, the final value in the range. */ + int end_value; + + /* When parsing a range, a pointer past the final token in the + range. */ + char *end_ptr; + + /* Non-zero when parsing a range. */ + int in_range; +}; + +/* Initialize a get_number_or_range_state for use with + get_number_or_range_state. STRING is the string to be parsed. */ + +extern void init_number_or_range (struct get_number_or_range_state *state, + char *string); + +/* Parse a number or a range. + A number will be of the form handled by get_number. + A range will be of the form - , and + will represent all the integers between number1 and number2, + inclusive. + + While processing a range, this fuction is called iteratively; + At each call it will return the next value in the range. + + At the beginning of parsing a range, the char pointer STATE->string will + be advanced past and left pointing at the '-' token. + Subsequent calls will not advance the pointer until the range + is completed. The call that completes the range will advance + the pointer past . */ + +extern int get_number_or_range (struct get_number_or_range_state *state); + +/* Accept a number and a string-form list of numbers such as is + accepted by get_number_or_range. Return TRUE if the number is + in the list. + + By definition, an empty list includes all numbers. This is to + be interpreted as typing a command such as "delete break" with + no arguments. */ + +extern int number_is_in_list (char *list, int number); + +/* Skip leading whitespace characters in INP, returning an updated + pointer. If INP is NULL, return NULL. */ + +extern char *skip_spaces (char *inp); + +/* Skip leading non-whitespace characters in INP, returning an updated + pointer. If INP is NULL, return NULL. */ + +extern char *skip_to_space (char *inp); + +/* Reverse S to the last non-whitespace character without skipping past + START. */ + +extern char *remove_trailing_whitespace (const char *start, char *s); +#endif /* CLI_UTILS_H */ diff --git a/contrib/gdb-7/gdb/coff-pe-read.c b/contrib/gdb-7/gdb/coff-pe-read.c index 3e2b89c328..ca87b726d7 100644 --- a/contrib/gdb-7/gdb/coff-pe-read.c +++ b/contrib/gdb-7/gdb/coff-pe-read.c @@ -2,7 +2,8 @@ convert to internal format, for GDB. Used as a last resort if no debugging symbols recognized. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -19,7 +20,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ + Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ #include "coff-pe-read.h" @@ -36,10 +37,11 @@ struct read_pe_section_data { - CORE_ADDR vma_offset; /* Offset to loaded address of section. */ - unsigned long rva_start; /* Start offset within the pe. */ - unsigned long rva_end; /* End offset within the pe. */ - enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + CORE_ADDR vma_offset; /* Offset to loaded address of section. */ + unsigned long rva_start; /* Start offset within the pe. */ + unsigned long rva_end; /* End offset within the pe. */ + enum minimal_symbol_type ms_type; /* Type to assign symbols in + section. */ }; #define PE_SECTION_INDEX_TEXT 0 @@ -49,8 +51,8 @@ struct read_pe_section_data #define PE_SECTION_INDEX_INVALID -1 /* Get the index of the named section in our own array, which contains - text, data and bss in that order. Return PE_SECTION_INDEX_INVALID - if passed an unrecognised section name. */ + text, data and bss in that order. Return PE_SECTION_INDEX_INVALID + if passed an unrecognised section name. */ static int read_pe_section_index (const char *section_name) @@ -76,7 +78,7 @@ read_pe_section_index (const char *section_name) } } -/* Record the virtual memory address of a section. */ +/* Record the virtual memory address of a section. */ static void get_section_vmas (bfd *abfd, asection *sectp, void *context) @@ -87,14 +89,14 @@ get_section_vmas (bfd *abfd, asection *sectp, void *context) if (sectix != PE_SECTION_INDEX_INVALID) { /* Data within the section start at rva_start in the pe and at - bfd_get_section_vma() within memory. Store the offset. */ + bfd_get_section_vma() within memory. Store the offset. */ sections[sectix].vma_offset = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start; } } -/* Create a minimal symbol entry for an exported symbol. */ +/* Create a minimal symbol entry for an exported symbol. */ static void add_pe_exported_sym (char *sym_name, @@ -102,7 +104,7 @@ add_pe_exported_sym (char *sym_name, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { - /* Add the stored offset to get the loaded address of the symbol. */ + /* Add the stored offset to get the loaded address of the symbol. */ CORE_ADDR vma = func_rva + section_data->vma_offset; @@ -110,8 +112,8 @@ add_pe_exported_sym (char *sym_name, int dll_name_len = strlen (dll_name); /* Generate a (hopefully unique) qualified name using the first part - of the dll name, e.g. KERNEL32!AddAtomA. This matches the style - used by windbg from the "Microsoft Debugging Tools for Windows". */ + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); @@ -124,11 +126,12 @@ add_pe_exported_sym (char *sym_name, xfree (qualified_name); - /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile); + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (sym_name, vma, + section_data->ms_type, objfile); } -/* Truncate a dll_name at the first dot character. */ +/* Truncate a dll_name at the first dot character. */ static void read_pe_truncate_name (char *dll_name) @@ -137,7 +140,7 @@ read_pe_truncate_name (char *dll_name) { if ((*dll_name) == '.') { - *dll_name = '\0'; /* truncates and causes loop exit. */ + *dll_name = '\0'; /* truncates and causes loop exit. */ } else @@ -147,7 +150,7 @@ read_pe_truncate_name (char *dll_name) } } -/* Low-level support functions, direct from the ld module pe-dll.c. */ +/* Low-level support functions, direct from the ld module pe-dll.c. */ static unsigned int pe_get16 (bfd *abfd, int where) { @@ -177,8 +180,8 @@ pe_as32 (void *ptr) } /* Read the (non-debug) export symbol table from a portable - executable. Code originally lifted from the ld function - pe_implied_import_dll in pe-dll.c. */ + executable. Code originally lifted from the ld function + pe_implied_import_dll in pe-dll.c. */ void read_pe_exported_syms (struct objfile *objfile) @@ -195,7 +198,7 @@ read_pe_exported_syms (struct objfile *objfile) /* Array elements are for text, data and bss in that order Initialization with start_rva > end_rva guarantees that - unused sections won't be matched. */ + unused sections won't be matched. */ struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] = { {0, 1, 0, mst_text}, {0, 1, 0, mst_data}, @@ -217,7 +220,7 @@ read_pe_exported_syms (struct objfile *objfile) { /* This is not a recognized PE format file. Abort now, because the code is untested on anything else. *FIXME* test on - further architectures and loosen or remove this test. */ + further architectures and loosen or remove this test. */ return; } @@ -272,11 +275,12 @@ read_pe_exported_syms (struct objfile *objfile) if (export_size == 0) { - /* Empty export table. */ + /* Empty export table. */ return; } - /* Scan sections and store the base and size of the relevant sections. */ + /* Scan sections and store the base and size of the relevant + sections. */ for (i = 0; i < nsections; i++) { unsigned long secptr1 = secptr + 40 * i; @@ -311,14 +315,14 @@ read_pe_exported_syms (struct objfile *objfile) ordbase = pe_as32 (expdata + 16); exp_funcbase = pe_as32 (expdata + 28); - /* Use internal dll name instead of full pathname. */ + /* Use internal dll name instead of full pathname. */ dll_name = pe_as32 (expdata + 12) + erva; bfd_map_over_sections (dll, get_section_vmas, section_data); /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset - as the text section. */ + as the text section. */ for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) { section_data[i].vma_offset @@ -326,7 +330,7 @@ read_pe_exported_syms (struct objfile *objfile) } /* Truncate name at first dot. Should maybe also convert to all - lower case for convenience on Windows. */ + lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); /* Iterate through the list of symbols. */ @@ -338,7 +342,7 @@ read_pe_exported_syms (struct objfile *objfile) /* Pointer to the function address vector. */ unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); - /* Find this symbol's section in our own array. */ + /* Find this symbol's section in our own array. */ int sectix = 0; for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) @@ -354,6 +358,6 @@ read_pe_exported_syms (struct objfile *objfile) } } - /* discard expdata. */ + /* Discard expdata. */ do_cleanups (back_to); } diff --git a/contrib/gdb-7/gdb/coff-pe-read.h b/contrib/gdb-7/gdb/coff-pe-read.h index f34d271919..a8b41d3768 100644 --- a/contrib/gdb-7/gdb/coff-pe-read.h +++ b/contrib/gdb-7/gdb/coff-pe-read.h @@ -1,6 +1,7 @@ /* Interface to coff-pe-read.c (portable-executable-specific symbol reader). - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -17,14 +18,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ + Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ #if !defined (COFF_PE_READ_H) #define COFF_PE_READ_H struct objfile; -/* Read the export table and convert it to minimal symbol table entries */ +/* Read the export table and convert it to minimal symbol table + entries */ extern void read_pe_exported_syms (struct objfile *objfile); #endif /* !defined (COFF_PE_READ_H) */ diff --git a/contrib/gdb-7/gdb/coffread.c b/contrib/gdb-7/gdb/coffread.c index 52417b22f4..b11dd7387c 100644 --- a/contrib/gdb-7/gdb/coffread.c +++ b/contrib/gdb-7/gdb/coffread.c @@ -1,7 +1,7 @@ /* Read coff symbol tables and convert to internal format, for GDB. Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu). This file is part of GDB. @@ -51,19 +51,20 @@ extern void _initialize_coffread (void); struct coff_symfile_info { - file_ptr min_lineno_offset; /* Where in file lowest line#s are */ - file_ptr max_lineno_offset; /* 1+last byte of line#s in file */ + file_ptr min_lineno_offset; /* Where in file lowest line#s are. */ + file_ptr max_lineno_offset; /* 1+last byte of line#s in file. */ - CORE_ADDR textaddr; /* Addr of .text section. */ - unsigned int textsize; /* Size of .text section. */ + CORE_ADDR textaddr; /* Addr of .text section. */ + unsigned int textsize; /* Size of .text section. */ struct stab_section_list *stabsects; /* .stab sections. */ - asection *stabstrsect; /* Section pointer for .stab section */ + asection *stabstrsect; /* Section pointer for .stab section. */ char *stabstrdata; }; /* Translate an external name string into a user-visible name. */ #define EXTERNAL_NAME(string, abfd) \ - (string[0] == bfd_get_symbol_leading_char(abfd)? string+1: string) + (string[0] == bfd_get_symbol_leading_char (abfd) \ + ? string + 1 : string) /* To be an sdb debug type, type must have at least a basic or primary derived type. Using this rather than checking against T_NULL is @@ -85,7 +86,8 @@ static bfd *nlist_bfd_global; static int nlist_nsyms_global; -/* Pointers to scratch storage, used for reading raw symbols and auxents. */ +/* Pointers to scratch storage, used for reading raw symbols and + auxents. */ static char *temp_sym; static char *temp_aux; @@ -106,10 +108,10 @@ static unsigned local_n_tshift; #define N_TMASK local_n_tmask #define N_TSHIFT local_n_tshift -/* Local variables that hold the sizes in the file of various COFF structures. - (We only need to know this to read them from the file -- BFD will then - translate the data in them, into `internal_xxx' structs in the right - byte order, alignment, etc.) */ +/* Local variables that hold the sizes in the file of various COFF + structures. (We only need to know this to read them from the file + -- BFD will then translate the data in them, into `internal_xxx' + structs in the right byte order, alignment, etc.) */ static unsigned local_linesz; static unsigned local_symesz; @@ -124,14 +126,15 @@ static int pe_file; static struct symbol *opaque_type_chain[HASHSIZE]; -/* Simplified internal version of coff symbol table information */ +/* Simplified internal version of coff symbol table information. */ struct coff_symbol { char *c_name; - int c_symnum; /* symbol number of this entry */ - int c_naux; /* 0 if syment only, 1 if syment + auxent, etc */ - long c_value; + int c_symnum; /* Symbol number of this entry. */ + int c_naux; /* 0 if syment only, 1 if syment + + auxent, etc. */ + CORE_ADDR c_value; int c_sclass; int c_secnum; unsigned int c_type; @@ -143,7 +146,8 @@ static struct type *coff_read_struct_type (int, int, int, struct objfile *); static struct type *decode_base_type (struct coff_symbol *, - unsigned int, union internal_auxent *, + unsigned int, + union internal_auxent *, struct objfile *); static struct type *decode_type (struct coff_symbol *, unsigned int, @@ -174,7 +178,7 @@ static int init_lineno (bfd *, long, int); static char *getsymname (struct internal_syment *); -static char *coff_getfilename (union internal_auxent *); +static const char *coff_getfilename (union internal_auxent *); static void free_stringtab (void); @@ -183,7 +187,8 @@ static void free_stringtab_cleanup (void *ignore); static int init_stringtab (bfd *, long); static void read_one_sym (struct coff_symbol *, - struct internal_syment *, union internal_auxent *); + struct internal_syment *, + union internal_auxent *); static void coff_symtab_read (long, unsigned int, struct objfile *); @@ -361,13 +366,12 @@ coff_alloc_type (int index) it indicates the start of data for one original source file. */ static void -coff_start_symtab (char *name) +coff_start_symtab (const char *name) { start_symtab ( - /* We fill in the filename later. start_symtab puts - this pointer into last_source_file and we put it in - subfiles->name, which end_symtab frees; that's why - it must be malloc'd. */ + /* We fill in the filename later. start_symtab puts this pointer + into last_source_file and we put it in subfiles->name, which + end_symtab frees; that's why it must be malloc'd. */ xstrdup (name), /* We never know the directory name for COFF. */ NULL, @@ -379,11 +383,12 @@ coff_start_symtab (char *name) /* Save the vital information from when starting to read a file, for use when closing off the current file. - NAME is the file name the symbols came from, START_ADDR is the first - text address for the file, and SIZE is the number of bytes of text. */ + NAME is the file name the symbols came from, START_ADDR is the + first text address for the file, and SIZE is the number of bytes of + text. */ static void -complete_symtab (char *name, CORE_ADDR start_addr, unsigned int size) +complete_symtab (const char *name, CORE_ADDR start_addr, unsigned int size) { if (last_source_file != NULL) xfree (last_source_file); @@ -392,21 +397,20 @@ complete_symtab (char *name, CORE_ADDR start_addr, unsigned int size) current_source_end_addr = start_addr + size; } -/* Finish the symbol definitions for one main source file, - close off all the lexical contexts for that file - (creating struct block's for them), then make the - struct symtab for that file and put it in the list of all such. */ +/* Finish the symbol definitions for one main source file, close off + all the lexical contexts for that file (creating struct block's for + them), then make the struct symtab for that file and put it in the + list of all such. */ static void coff_end_symtab (struct objfile *objfile) { - struct symtab *symtab; - last_source_start_addr = current_source_start_addr; - symtab = end_symtab (current_source_end_addr, objfile, SECT_OFF_TEXT (objfile)); + end_symtab (current_source_end_addr, objfile, + SECT_OFF_TEXT (objfile)); - /* Reinitialize for beginning of new file. */ + /* Reinitialize for beginning of new file. */ last_source_file = NULL; } @@ -417,13 +421,14 @@ record_minimal_symbol (struct coff_symbol *cs, CORE_ADDR address, { struct bfd_section *bfd_section; - /* We don't want TDESC entry points in the minimal symbol table */ + /* We don't want TDESC entry points in the minimal symbol table. */ if (cs->c_name[0] == '@') return NULL; bfd_section = cs_to_bfd_section (cs, objfile); - return prim_record_minimal_symbol_and_info (cs->c_name, address, type, - section, bfd_section, objfile); + return prim_record_minimal_symbol_and_info (cs->c_name, address, + type, section, + bfd_section, objfile); } /* coff_symfile_init () @@ -433,26 +438,29 @@ record_minimal_symbol (struct coff_symbol *cs, CORE_ADDR address, a pointer to "private data" which we fill with cookies and other treats for coff_symfile_read (). - We will only be called if this is a COFF or COFF-like file. - BFD handles figuring out the format of the file, and code in symtab.c + We will only be called if this is a COFF or COFF-like file. BFD + handles figuring out the format of the file, and code in symtab.c uses BFD's determination to vector to us. - The ultimate result is a new symtab (or, FIXME, eventually a psymtab). */ + The ultimate result is a new symtab (or, FIXME, eventually a + psymtab). */ static void coff_symfile_init (struct objfile *objfile) { - /* Allocate struct to keep track of stab reading. */ + /* Allocate struct to keep track of stab reading. */ objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *) xmalloc (sizeof (struct dbx_symfile_info)); memset (objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info)); - /* Allocate struct to keep track of the symfile */ - objfile->deprecated_sym_private = xmalloc (sizeof (struct coff_symfile_info)); + /* Allocate struct to keep track of the symfile. */ + objfile->deprecated_sym_private + = xmalloc (sizeof (struct coff_symfile_info)); - memset (objfile->deprecated_sym_private, 0, sizeof (struct coff_symfile_info)); + memset (objfile->deprecated_sym_private, 0, + sizeof (struct coff_symfile_info)); /* COFF objects may be reordered, so set OBJF_REORDERED. If we find this causes a significant slowdown in gdb then we could @@ -462,9 +470,9 @@ coff_symfile_init (struct objfile *objfile) init_entry_point_info (objfile); } -/* This function is called for every section; it finds the outer limits - of the line table (minimum and maximum file offset) so that the - mainline code can read the whole thing for efficiency. */ +/* This function is called for every section; it finds the outer + limits of the line table (minimum and maximum file offset) so that + the mainline code can read the whole thing for efficiency. */ static void find_linenos (bfd *abfd, struct bfd_section *asect, void *vpinfo) @@ -473,18 +481,18 @@ find_linenos (bfd *abfd, struct bfd_section *asect, void *vpinfo) int size, count; file_ptr offset, maxoff; -/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ count = asect->lineno_count; -/* End of warning */ + /* End of warning. */ if (count == 0) return; size = count * local_linesz; info = (struct coff_symfile_info *) vpinfo; -/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ offset = asect->line_filepos; -/* End of warning */ + /* End of warning. */ if (offset < info->min_lineno_offset || info->min_lineno_offset == 0) info->min_lineno_offset = offset; @@ -519,7 +527,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags) info = (struct coff_symfile_info *) objfile->deprecated_sym_private; dbxinfo = objfile->deprecated_sym_stab_info; - symfile_bfd = abfd; /* Kludge for swap routines */ + symfile_bfd = abfd; /* Kludge for swap routines. */ /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ num_symbols = bfd_get_symcount (abfd); /* How many syms */ @@ -553,7 +561,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags) strncmp (bfd_get_target (objfile->obfd), "pe", 2) == 0 || strncmp (bfd_get_target (objfile->obfd), "epoc-pe", 7) == 0; -/* End of warning */ + /* End of warning. */ info->min_lineno_offset = 0; info->max_lineno_offset = 0; @@ -599,8 +607,8 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags) coff_symtab_read ((long) symtab_offset, num_symbols, objfile); - /* Install any minimal symbols that have been collected as the current - minimal symbols for this objfile. */ + /* Install any minimal symbols that have been collected as the + current minimal symbols for this objfile. */ install_minimal_symbols (objfile); @@ -613,8 +621,8 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags) { if (!info->stabstrsect) { - error (_("The debugging information in `%s' is corrupted.\n" - "The file has a `.stabs' section, but no `.stabstr' section."), + error (_("The debugging information in `%s' is corrupted.\nThe " + "file has a `.stabs' section, but no `.stabstr' section."), name); } @@ -661,10 +669,11 @@ coff_new_init (struct objfile *ignore) { } -/* Perform any local cleanups required when we are done with a particular - objfile. I.E, we are in the process of discarding all symbol information - for an objfile, freeing up all memory held for it, and unlinking the - objfile struct from the global list of known objfiles. */ +/* Perform any local cleanups required when we are done with a + particular objfile. I.E, we are in the process of discarding all + symbol information for an objfile, freeing up all memory held for + it, and unlinking the objfile struct from the global list of known + objfiles. */ static void coff_symfile_finish (struct objfile *objfile) @@ -674,7 +683,7 @@ coff_symfile_finish (struct objfile *objfile) xfree (objfile->deprecated_sym_private); } - /* Let stabs reader clean up */ + /* Let stabs reader clean up. */ stabsread_clear_cache (); dwarf2_free_objfile (objfile); @@ -704,7 +713,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, int in_source_file = 0; int next_file_symnum = -1; /* Name of the current file. */ - char *filestring = ""; + const char *filestring = ""; int depth = 0; int fcn_first_line = 0; CORE_ADDR fcn_first_line_addr = 0; @@ -716,8 +725,8 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, struct minimal_symbol *msym; /* Work around a stdio bug in SunOS4.1.1 (this makes me nervous.... - it's hard to know I've really worked around it. The fix should be - harmless, anyway). The symptom of the bug is that the first + it's hard to know I've really worked around it. The fix should + be harmless, anyway). The symptom of the bug is that the first fread (in read_one_sym), will (in my example) actually get data from file offset 268, when the fseek was to 264 (and ftell shows 264). This causes all hell to break loose. I was unable to @@ -731,7 +740,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, bfd_seek (objfile->obfd, 0, 0); - /* Position to read the symbol table. */ + /* Position to read the symbol table. */ val = bfd_seek (objfile->obfd, (long) symtab_offset, 0); if (val < 0) perror_with_name (objfile->name); @@ -742,7 +751,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, last_source_file = NULL; memset (opaque_type_chain, 0, sizeof opaque_type_chain); - if (type_vector) /* Get rid of previous one */ + if (type_vector) /* Get rid of previous one. */ xfree (type_vector); type_vector_length = 160; type_vector = (struct type **) @@ -770,10 +779,12 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, allow printing values in this symtab. */ current_subfile->language = language_minimal; complete_symtab ("_globals_", 0, 0); - /* done with all files, everything from here on out is globals */ + /* Done with all files, everything from here on out is + globals. */ } - /* Special case for file with type declarations only, no text. */ + /* Special case for file with type declarations only, no + text. */ if (!last_source_file && SDB_TYPE (cs->c_type) && cs->c_secnum == N_DEBUG) complete_symtab (filestring, 0, 0); @@ -781,11 +792,14 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, /* Typedefs should not be treated as symbol definitions. */ if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) { - /* Record all functions -- external and static -- in minsyms. */ + /* Record all functions -- external and static -- in + minsyms. */ int section = cs_to_section (cs, objfile); - tmpaddr = cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - record_minimal_symbol (cs, tmpaddr, mst_text, section, objfile); + tmpaddr = cs->c_value + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + record_minimal_symbol (cs, tmpaddr, mst_text, + section, objfile); fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; fcn_start_addr = tmpaddr; @@ -804,13 +818,14 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, case C_LINE: case C_ALIAS: case C_HIDDEN: - complaint (&symfile_complaints, _("Bad n_sclass for symbol %s"), + complaint (&symfile_complaints, + _("Bad n_sclass for symbol %s"), cs->c_name); break; case C_FILE: - /* c_value field contains symnum of next .file entry in table - or symnum of first global after last .file. */ + /* c_value field contains symnum of next .file entry in + table or symnum of first global after last .file. */ next_file_symnum = cs->c_value; if (cs->c_naux > 0) filestring = coff_getfilename (&main_aux); @@ -827,12 +842,12 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, in_source_file = 1; break; - /* C_LABEL is used for labels and static functions. Including - it here allows gdb to see static functions when no debug - info is available. */ + /* C_LABEL is used for labels and static functions. + Including it here allows gdb to see static functions when + no debug info is available. */ case C_LABEL: - /* However, labels within a function can make weird backtraces, - so filter them out (from phdm@macqel.be). */ + /* However, labels within a function can make weird + backtraces, so filter them out (from phdm@macqel.be). */ if (within_function) break; case C_STAT: @@ -843,18 +858,19 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, { if (strcmp (cs->c_name, ".text") == 0) { - /* FIXME: don't wire in ".text" as section name - or symbol name! */ - /* Check for in_source_file deals with case of - a file with debugging symbols - followed by a later file with no symbols. */ + /* FIXME: don't wire in ".text" as section name or + symbol name! */ + /* Check for in_source_file deals with case of a + file with debugging symbols followed by a later + file with no symbols. */ if (in_source_file) complete_symtab (filestring, - cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)), + cs->c_value + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)), main_aux.x_scn.x_scnlen); in_source_file = 0; } - /* flush rest of '.' symbols */ + /* Flush rest of '.' symbols. */ break; } else if (!SDB_TYPE (cs->c_type) @@ -870,7 +886,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, /* At least on a 3b1, gcc generates swbeg and string labels that look like this. Ignore them. */ break; - /* fall in for static symbols that don't start with '.' */ + /* Fall in for static symbols that don't start with '.' */ case C_THUMBEXT: case C_THUMBEXTFUNC: case C_EXT: @@ -886,27 +902,19 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (cs->c_secnum == N_UNDEF) { - /* This is a common symbol. See if the target - environment knows where it has been relocated to. */ - CORE_ADDR reladdr; - - if (target_lookup_symbol (cs->c_name, &reladdr)) - { - /* Error in lookup; ignore symbol. */ - break; - } - tmpaddr = reladdr; - /* The address has already been relocated; make sure that - objfile_relocate doesn't relocate it again. */ - sec = -2; - ms_type = cs->c_sclass == C_EXT - || cs->c_sclass == C_THUMBEXT ? - mst_bss : mst_file_bss; + /* This is a common symbol. We used to rely on + the target to tell us whether it knows where + the symbol has been relocated to, but none of + the target implementations actually provided + that operation. So we just ignore the symbol, + the same way we would do if we had a target-side + symbol lookup which returned no match. */ + break; } else if (cs->c_secnum == N_ABS) { /* Use the correct minimal symbol type (and don't - relocate) for absolute values. */ + relocate) for absolute values. */ ms_type = mst_abs; sec = cs_to_section (cs, objfile); tmpaddr = cs->c_value; @@ -917,7 +925,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, sec = cs_to_section (cs, objfile); tmpaddr = cs->c_value; - /* Statics in a PE file also get relocated */ + /* Statics in a PE file also get relocated. */ if (cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXTFUNC || cs->c_sclass == C_THUMBEXT @@ -936,22 +944,24 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, && bfd_section->flags & SEC_LOAD) { ms_type = - cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ? - mst_data : mst_file_data; + cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT + ? mst_data : mst_file_data; } else if (bfd_section->flags & SEC_ALLOC) { ms_type = - cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ? - mst_bss : mst_file_bss; + cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT + ? mst_bss : mst_file_bss; } else ms_type = mst_unknown; } - msym = record_minimal_symbol (cs, tmpaddr, ms_type, sec, objfile); + msym = record_minimal_symbol (cs, tmpaddr, ms_type, + sec, objfile); if (msym) - gdbarch_coff_make_msymbol_special (gdbarch, cs->c_sclass, msym); + gdbarch_coff_make_msymbol_special (gdbarch, + cs->c_sclass, msym); if (SDB_TYPE (cs->c_type)) { @@ -970,12 +980,14 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, { within_function = 1; - /* value contains address of first non-init type code */ + /* Value contains address of first non-init type + code. */ /* main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains line number of '{' } */ + contains line number of '{' }. */ if (cs->c_naux != 1) complaint (&symfile_complaints, - _("`.bf' symbol %d has no aux entry"), cs->c_symnum); + _("`.bf' symbol %d has no aux entry"), + cs->c_symnum); fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; fcn_first_line_addr = cs->c_value; @@ -986,21 +998,23 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, new = push_context (depth, fcn_start_addr); fcn_cs_saved.c_name = getsymname (&fcn_sym_saved); new->name = - process_coff_symbol (&fcn_cs_saved, &fcn_aux_saved, objfile); + process_coff_symbol (&fcn_cs_saved, + &fcn_aux_saved, objfile); } else if (strcmp (cs->c_name, ".ef") == 0) { if (!within_function) error (_("Bad coff function information.")); - /* the value of .ef is the address of epilogue code; + /* The value of .ef is the address of epilogue code; not useful for gdb. */ /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno contains number of lines to '}' */ if (context_stack_depth <= 0) - { /* We attempted to pop an empty context stack */ + { /* We attempted to pop an empty context stack. */ complaint (&symfile_complaints, - _("`.ef' symbol without matching `.bf' symbol ignored starting at symnum %d"), + _("`.ef' symbol without matching `.bf' " + "symbol ignored starting at symnum %d"), cs->c_symnum); within_function = 0; break; @@ -1011,7 +1025,8 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (context_stack_depth > 0 || new == NULL) { complaint (&symfile_complaints, - _("Unmatched .ef symbol(s) ignored starting at symnum %d"), + _("Unmatched .ef symbol(s) ignored " + "starting at symnum %d"), cs->c_symnum); within_function = 0; break; @@ -1019,7 +1034,8 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (cs->c_naux != 1) { complaint (&symfile_complaints, - _("`.ef' symbol %d has no aux entry"), cs->c_symnum); + _("`.ef' symbol %d has no aux entry"), + cs->c_symnum); fcn_last_line = 0x7FFFFFFF; } else @@ -1028,23 +1044,25 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, } /* fcn_first_line is the line number of the opening '{'. Do not record it - because it would affect gdb's idea - of the line number of the first statement of the function - - except for one-line functions, for which it is also the line - number of all the statements and of the closing '}', and - for which we do not have any other statement-line-number. */ + of the line number of the first statement of the + function - except for one-line functions, for which + it is also the line number of all the statements and + of the closing '}', and for which we do not have any + other statement-line-number. */ if (fcn_last_line == 1) record_line (current_subfile, fcn_first_line, gdbarch_addr_bits_remove (gdbarch, fcn_first_line_addr)); else - enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line, - objfile); + enter_linenos (fcn_line_ptr, fcn_first_line, + fcn_last_line, objfile); - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, + finish_block (new->name, &local_symbols, + new->old_blocks, new->start_addr, fcn_cs_saved.c_value + fcn_aux_saved.x_sym.x_misc.x_fsize - + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)), + + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)), objfile ); within_function = 0; @@ -1055,15 +1073,17 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (strcmp (cs->c_name, ".bb") == 0) { tmpaddr = cs->c_value; - tmpaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + tmpaddr += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); push_context (++depth, tmpaddr); } else if (strcmp (cs->c_name, ".eb") == 0) { if (context_stack_depth <= 0) - { /* We attempted to pop an empty context stack */ + { /* We attempted to pop an empty context stack. */ complaint (&symfile_complaints, - _("`.eb' symbol without matching `.bb' symbol ignored starting at symnum %d"), + _("`.eb' symbol without matching `.bb' " + "symbol ignored starting at symnum %d"), cs->c_symnum); break; } @@ -1072,14 +1092,16 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (depth-- != new->depth) { complaint (&symfile_complaints, - _("Mismatched .eb symbol ignored starting at symnum %d"), + _("Mismatched .eb symbol ignored " + "starting at symnum %d"), symnum); break; } if (local_symbols && context_stack_depth > 0) { tmpaddr = - cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + cs->c_value + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); /* Make a block for the local symbols within. */ finish_block (0, &local_symbols, new->old_blocks, new->start_addr, tmpaddr, objfile); @@ -1098,7 +1120,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if ((nsyms == 0) && (pe_file)) { /* We've got no debugging symbols, but it's a portable - executable, so try to read the export table */ + executable, so try to read the export table. */ read_pe_exported_syms (objfile); } @@ -1115,9 +1137,10 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, /* Routines for reading headers and symbols from executable. */ -/* Read the next symbol, swap it, and return it in both internal_syment - form, and coff_symbol form. Also return its first auxent, if any, - in internal_auxent form, and skip any other auxents. */ +/* Read the next symbol, swap it, and return it in both + internal_syment form, and coff_symbol form. Also return its first + auxent, if any, in internal_auxent form, and skip any other + auxents. */ static void read_one_sym (struct coff_symbol *cs, @@ -1130,23 +1153,24 @@ read_one_sym (struct coff_symbol *cs, cs->c_symnum = symnum; bytes = bfd_bread (temp_sym, local_symesz, nlist_bfd_global); if (bytes != local_symesz) - error ("%s: error reading symbols", current_objfile->name); + error (_("%s: error reading symbols"), current_objfile->name); bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *) sym); cs->c_naux = sym->n_numaux & 0xff; if (cs->c_naux >= 1) { bytes = bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); if (bytes != local_auxesz) - error ("%s: error reading symbols", current_objfile->name); - bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, + error (_("%s: error reading symbols"), current_objfile->name); + bfd_coff_swap_aux_in (symfile_bfd, temp_aux, + sym->n_type, sym->n_sclass, 0, cs->c_naux, (char *) aux); /* If more than one aux entry, read past it (only the first aux - is important). */ + is important). */ for (i = 1; i < cs->c_naux; i++) { bytes = bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); if (bytes != local_auxesz) - error ("%s: error reading symbols", current_objfile->name); + error (_("%s: error reading symbols"), current_objfile->name); } } cs->c_name = getsymname (sym); @@ -1193,7 +1217,7 @@ read_one_sym (struct coff_symbol *cs, } } -/* Support for string table handling */ +/* Support for string table handling. */ static char *stringtab = NULL; @@ -1207,7 +1231,7 @@ init_stringtab (bfd *abfd, long offset) free_stringtab (); /* If the file is stripped, the offset might be zero, indicating no - string table. Just return with `stringtab' set to null. */ + string table. Just return with `stringtab' set to null. */ if (offset == 0) return 0; @@ -1218,19 +1242,19 @@ init_stringtab (bfd *abfd, long offset) length = bfd_h_get_32 (symfile_bfd, lengthbuf); /* If no string table is needed, then the file may end immediately - after the symbols. Just return with `stringtab' set to null. */ + after the symbols. Just return with `stringtab' set to null. */ if (val != sizeof lengthbuf || length < sizeof lengthbuf) return 0; stringtab = (char *) xmalloc (length); - /* This is in target format (probably not very useful, and not currently - used), not host format. */ + /* This is in target format (probably not very useful, and not + currently used), not host format. */ memcpy (stringtab, lengthbuf, sizeof lengthbuf); - if (length == sizeof length) /* Empty table -- just the count */ + if (length == sizeof length) /* Empty table -- just the count. */ return 0; - val = bfd_bread (stringtab + sizeof lengthbuf, length - sizeof lengthbuf, - abfd); + val = bfd_bread (stringtab + sizeof lengthbuf, + length - sizeof lengthbuf, abfd); if (val != length - sizeof lengthbuf || stringtab[length - 1] != '\0') return -1; @@ -1272,19 +1296,23 @@ getsymname (struct internal_syment *symbol_entry) return result; } -/* Extract the file name from the aux entry of a C_FILE symbol. Return - only the last component of the name. Result is in static storage and - is only good for temporary use. */ +/* Extract the file name from the aux entry of a C_FILE symbol. + Return only the last component of the name. Result is in static + storage and is only good for temporary use. */ -static char * +static const char * coff_getfilename (union internal_auxent *aux_entry) { static char buffer[BUFSIZ]; char *temp; - char *result; + const char *result; if (aux_entry->x_file.x_n.x_zeroes == 0) - strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset); + { + if (strlen (stringtab + aux_entry->x_file.x_n.x_offset) >= BUFSIZ) + internal_error (__FILE__, __LINE__, _("coff file name too long")); + strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset); + } else { strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); @@ -1295,8 +1323,7 @@ coff_getfilename (union internal_auxent *aux_entry) /* FIXME: We should not be throwing away the information about what directory. It should go into dirname of the symtab, or some such place. */ - if ((temp = strrchr (result, '/')) != NULL) - result = temp + 1; + result = lbasename (result); return (result); } @@ -1326,14 +1353,14 @@ init_lineno (bfd *abfd, long offset, int size) if (bfd_seek (abfd, offset, 0) < 0) return -1; - /* Allocate the desired table, plus a sentinel */ + /* Allocate the desired table, plus a sentinel. */ linetab = (char *) xmalloc (size + local_linesz); val = bfd_bread (linetab, size, abfd); if (val != size) return -1; - /* Terminate it with an all-zero sentinel record */ + /* Terminate it with an all-zero sentinel record. */ memset (linetab + size, 0, local_linesz); return 0; @@ -1372,16 +1399,17 @@ enter_linenos (long file_offset, int first_line, complaint (&symfile_complaints, _("Line number pointer %ld lower than start of line numbers"), file_offset); - if (file_offset > linetab_size) /* Too big to be an offset? */ + if (file_offset > linetab_size) /* Too big to be an offset? */ return; - file_offset += linetab_offset; /* Try reading at that linetab offset */ + file_offset += linetab_offset; /* Try reading at that linetab + offset. */ } rawptr = &linetab[file_offset - linetab_offset]; - /* skip first line entry for each function */ + /* Skip first line entry for each function. */ rawptr += local_linesz; - /* line numbers start at one for the first line of the function */ + /* Line numbers start at one for the first line of the function. */ first_line--; /* If the line number table is full (e.g. 64K lines in COFF debug @@ -1392,12 +1420,14 @@ enter_linenos (long file_offset, int first_line, bfd_coff_swap_lineno_in (symfile_bfd, rawptr, &lptr); rawptr += local_linesz; /* The next function, or the sentinel, will have L_LNNO32 zero; - we exit. */ + we exit. */ if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line) { CORE_ADDR addr = lptr.l_addr.l_paddr; - addr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - record_line (current_subfile, first_line + L_LNNO32 (&lptr), + addr += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + record_line (current_subfile, + first_line + L_LNNO32 (&lptr), gdbarch_addr_bits_remove (gdbarch, addr)); } else @@ -1414,20 +1444,25 @@ patch_type (struct type *type, struct type *real_type) TYPE_LENGTH (target) = TYPE_LENGTH (real_target); TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); - TYPE_FIELDS (target) = (struct field *) TYPE_ALLOC (target, field_size); + TYPE_FIELDS (target) = (struct field *) TYPE_ALLOC (target, + field_size); - memcpy (TYPE_FIELDS (target), TYPE_FIELDS (real_target), field_size); + memcpy (TYPE_FIELDS (target), + TYPE_FIELDS (real_target), + field_size); if (TYPE_NAME (real_target)) { if (TYPE_NAME (target)) xfree (TYPE_NAME (target)); - TYPE_NAME (target) = concat (TYPE_NAME (real_target), (char *)NULL); + TYPE_NAME (target) = concat (TYPE_NAME (real_target), + (char *) NULL); } } /* Patch up all appropriate typedef symbols in the opaque_type_chains - so that they can be used to print out opaque data structures properly. */ + so that they can be used to print out opaque data structures + properly. */ static void patch_opaque_types (struct symtab *s) @@ -1436,7 +1471,7 @@ patch_opaque_types (struct symtab *s) struct dict_iterator iter; struct symbol *real_sym; - /* Go through the per-file symbols only */ + /* Go through the per-file symbols only. */ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); ALL_BLOCK_SYMBOLS (b, iter, real_sym) { @@ -1512,7 +1547,7 @@ process_coff_symbol (struct coff_symbol *cs, memset (sym, 0, sizeof (struct symbol)); name = cs->c_name; name = EXTERNAL_NAME (name, objfile->obfd); - SYMBOL_LANGUAGE (sym) = current_subfile->language; + SYMBOL_SET_LANGUAGE (sym, current_subfile->language); SYMBOL_SET_NAMES (sym, name, strlen (name), 1, objfile); /* default assumptions */ @@ -1522,9 +1557,11 @@ process_coff_symbol (struct coff_symbol *cs, if (ISFCN (cs->c_type)) { - SYMBOL_VALUE (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SYMBOL_VALUE (sym) += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); SYMBOL_TYPE (sym) = - lookup_function_type (decode_function_type (cs, cs->c_type, aux, objfile)); + lookup_function_type (decode_function_type (cs, cs->c_type, + aux, objfile)); SYMBOL_CLASS (sym) = LOC_BLOCK; if (cs->c_sclass == C_STAT || cs->c_sclass == C_THUMBSTAT @@ -1552,7 +1589,8 @@ process_coff_symbol (struct coff_symbol *cs, case C_EXT: SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value; - SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); add_symbol_to_list (sym, &global_symbols); break; @@ -1561,15 +1599,16 @@ process_coff_symbol (struct coff_symbol *cs, case C_STAT: SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value; - SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); if (within_function) { - /* Static symbol of local scope */ + /* Static symbol of local scope. */ add_symbol_to_list (sym, &local_symbols); } else { - /* Static symbol at top level of file */ + /* Static symbol at top level of file. */ add_symbol_to_list (sym, &file_symbols); } break; @@ -1606,25 +1645,25 @@ process_coff_symbol (struct coff_symbol *cs, SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - /* If type has no name, give it one */ + /* If type has no name, give it one. */ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) { if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC) { - /* If we are giving a name to a type such as "pointer to - foo" or "function returning foo", we better not set - the TYPE_NAME. If the program contains "typedef char - *caddr_t;", we don't want all variables of type char - * to print as caddr_t. This is not just a - consequence of GDB's type management; CC and GCC (at - least through version 2.4) both output variables of - either type char * or caddr_t with the type - refering to the C_TPDEF symbol for caddr_t. If a future - compiler cleans this up it GDB is not ready for it - yet, but if it becomes ready we somehow need to - disable this check (without breaking the PCC/GCC2.4 - case). + /* If we are giving a name to a type such as + "pointer to foo" or "function returning foo", we + better not set the TYPE_NAME. If the program + contains "typedef char *caddr_t;", we don't want + all variables of type char * to print as caddr_t. + This is not just a consequence of GDB's type + management; CC and GCC (at least through version + 2.4) both output variables of either type char * + or caddr_t with the type refering to the C_TPDEF + symbol for caddr_t. If a future compiler cleans + this up it GDB is not ready for it yet, but if it + becomes ready we somehow need to disable this + check (without breaking the PCC/GCC2.4 case). Sigh. @@ -1634,14 +1673,15 @@ process_coff_symbol (struct coff_symbol *cs, } else TYPE_NAME (SYMBOL_TYPE (sym)) = - concat (SYMBOL_LINKAGE_NAME (sym), (char *)NULL); + concat (SYMBOL_LINKAGE_NAME (sym), (char *) NULL); } - /* Keep track of any type which points to empty structured type, - so it can be filled from a definition from another file. A - simple forward reference (TYPE_CODE_UNDEF) is not an - empty structured type, though; the forward references - work themselves out via the magic of coff_lookup_type. */ + /* Keep track of any type which points to empty structured + type, so it can be filled from a definition from another + file. A simple forward reference (TYPE_CODE_UNDEF) is + not an empty structured type, though; the forward + references work themselves out via the magic of + coff_lookup_type. */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0 && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) @@ -1663,7 +1703,7 @@ process_coff_symbol (struct coff_symbol *cs, /* Some compilers try to be helpful by inventing "fake" names for anonymous enums, structures, and unions, like - "~0fake" or ".0fake". Thanks, but no thanks... */ + "~0fake" or ".0fake". Thanks, but no thanks... */ if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0) if (SYMBOL_LINKAGE_NAME (sym) != NULL && *SYMBOL_LINKAGE_NAME (sym) != '~' @@ -1710,11 +1750,11 @@ decode_type (struct coff_symbol *cs, unsigned int c_type, struct type *base_type, *index_type, *range_type; /* Define an array type. */ - /* auxent refers to array, not base type */ + /* auxent refers to array, not base type. */ if (aux->x_sym.x_tagndx.l == 0) cs->c_naux = 0; - /* shift the indices down */ + /* Shift the indices down. */ dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; i = 1; n = dim[0]; @@ -1725,20 +1765,21 @@ decode_type (struct coff_symbol *cs, unsigned int c_type, base_type = decode_type (cs, new_c_type, aux, objfile); index_type = objfile_type (objfile)->builtin_int; range_type = - create_range_type ((struct type *) NULL, index_type, 0, n - 1); + create_range_type ((struct type *) NULL, + index_type, 0, n - 1); type = - create_array_type ((struct type *) NULL, base_type, range_type); + create_array_type ((struct type *) NULL, + base_type, range_type); } return type; } - /* Reference to existing type. This only occurs with the - struct, union, and enum types. EPI a29k coff - fakes us out by producing aux entries with a nonzero - x_tagndx for definitions of structs, unions, and enums, so we - have to check the c_sclass field. SCO 3.2v4 cc gets confused - with pointers to pointers to defined structs, and generates - negative x_tagndx fields. */ + /* Reference to existing type. This only occurs with the struct, + union, and enum types. EPI a29k coff fakes us out by producing + aux entries with a nonzero x_tagndx for definitions of structs, + unions, and enums, so we have to check the c_sclass field. SCO + 3.2v4 cc gets confused with pointers to pointers to defined + structs, and generates negative x_tagndx fields. */ if (cs->c_naux > 0 && aux->x_sym.x_tagndx.l != 0) { if (cs->c_sclass != C_STRTAG @@ -1754,7 +1795,7 @@ decode_type (struct coff_symbol *cs, unsigned int c_type, complaint (&symfile_complaints, _("Symbol table entry for %s has bad tagndx value"), cs->c_name); - /* And fall through to decode_base_type... */ + /* And fall through to decode_base_type... */ } } @@ -1765,20 +1806,25 @@ decode_type (struct coff_symbol *cs, unsigned int c_type, return the type that the function returns. */ static struct type * -decode_function_type (struct coff_symbol *cs, unsigned int c_type, - union internal_auxent *aux, struct objfile *objfile) +decode_function_type (struct coff_symbol *cs, + unsigned int c_type, + union internal_auxent *aux, + struct objfile *objfile) { if (aux->x_sym.x_tagndx.l == 0) - cs->c_naux = 0; /* auxent refers to function, not base type */ + cs->c_naux = 0; /* auxent refers to function, not base + type. */ return decode_type (cs, DECREF (c_type), aux, objfile); } -/* basic C types */ +/* Basic C types. */ static struct type * -decode_base_type (struct coff_symbol *cs, unsigned int c_type, - union internal_auxent *aux, struct objfile *objfile) +decode_base_type (struct coff_symbol *cs, + unsigned int c_type, + union internal_auxent *aux, + struct objfile *objfile) { struct gdbarch *gdbarch = get_objfile_arch (objfile); struct type *type; @@ -1786,7 +1832,7 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, switch (c_type) { case T_NULL: - /* shows up with "void (*foo)();" structure members */ + /* Shows up with "void (*foo)();" structure members. */ return objfile_type (objfile)->builtin_void; #ifdef T_VOID @@ -1824,13 +1870,13 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, case T_STRUCT: if (cs->c_naux != 1) { - /* anonymous structure type */ + /* Anonymous structure type. */ type = coff_alloc_type (cs->c_symnum); TYPE_CODE (type) = TYPE_CODE_STRUCT; TYPE_NAME (type) = NULL; - /* This used to set the tag to "". But I think setting it - to NULL is right, and the printing code can print it as - "struct {...}". */ + /* This used to set the tag to "". But I think + setting it to NULL is right, and the printing code can + print it as "struct {...}". */ TYPE_TAG_NAME (type) = NULL; INIT_CPLUS_SPECIFIC (type); TYPE_LENGTH (type) = 0; @@ -1849,12 +1895,12 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, case T_UNION: if (cs->c_naux != 1) { - /* anonymous union type */ + /* Anonymous union type. */ type = coff_alloc_type (cs->c_symnum); TYPE_NAME (type) = NULL; - /* This used to set the tag to "". But I think setting it - to NULL is right, and the printing code can print it as - "union {...}". */ + /* This used to set the tag to "". But I think + setting it to NULL is right, and the printing code can + print it as "union {...}". */ TYPE_TAG_NAME (type) = NULL; INIT_CPLUS_SPECIFIC (type); TYPE_LENGTH (type) = 0; @@ -1874,13 +1920,13 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, case T_ENUM: if (cs->c_naux != 1) { - /* anonymous enum type */ + /* Anonymous enum type. */ type = coff_alloc_type (cs->c_symnum); TYPE_CODE (type) = TYPE_CODE_ENUM; TYPE_NAME (type) = NULL; - /* This used to set the tag to "". But I think setting it - to NULL is right, and the printing code can print it as - "enum {...}". */ + /* This used to set the tag to "". But I think + setting it to NULL is right, and the printing code can + print it as "enum {...}". */ TYPE_TAG_NAME (type) = NULL; TYPE_LENGTH (type) = 0; TYPE_FIELDS (type) = 0; @@ -1896,7 +1942,7 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, return type; case T_MOE: - /* shouldn't show up here */ + /* Shouldn't show up here. */ break; case T_UCHAR: @@ -1916,7 +1962,8 @@ decode_base_type (struct coff_symbol *cs, unsigned int c_type, else return objfile_type (objfile)->builtin_unsigned_long; } - complaint (&symfile_complaints, _("Unexpected type for symbol %s"), cs->c_name); + complaint (&symfile_complaints, + _("Unexpected type for symbol %s"), cs->c_name); return objfile_type (objfile)->builtin_void; } @@ -1969,10 +2016,10 @@ coff_read_struct_type (int index, int length, int lastsym, list = new; /* Save the data. */ - list->field.name = - obsavestring (name, strlen (name), &objfile->objfile_obstack); - FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux, - objfile); + list->field.name = obsavestring (name, strlen (name), + &objfile->objfile_obstack); + FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, + &sub_aux, objfile); SET_FIELD_BITPOS (list->field, 8 * ms->c_value); FIELD_BITSIZE (list->field) = 0; nfields++; @@ -1986,10 +2033,10 @@ coff_read_struct_type (int index, int length, int lastsym, list = new; /* Save the data. */ - list->field.name = - obsavestring (name, strlen (name), &objfile->objfile_obstack); - FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux, - objfile); + list->field.name = obsavestring (name, strlen (name), + &objfile->objfile_obstack); + FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, + &sub_aux, objfile); SET_FIELD_BITPOS (list->field, ms->c_value); FIELD_BITSIZE (list->field) = sub_aux.x_sym.x_misc.x_lnsz.x_size; nfields++; @@ -2124,22 +2171,29 @@ coff_read_enum_type (int index, int length, int lastsym, return type; } -/* Register our ability to parse symbols for coff BFD files. */ +/* Register our ability to parse symbols for coff BFD files. */ -static struct sym_fns coff_sym_fns = +static const struct sym_fns coff_sym_fns = { bfd_target_coff_flavour, - coff_new_init, /* sym_new_init: init anything gbl to entire symtab */ - coff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - coff_symfile_read, /* sym_read: read a symbol file into symtab */ - coff_symfile_finish, /* sym_finish: finished with file, cleanup */ - default_symfile_offsets, /* sym_offsets: xlate external to internal form */ - default_symfile_segments, /* sym_segments: Get segment information from - a file. */ + coff_new_init, /* sym_new_init: init anything gbl to + entire symtab */ + coff_symfile_init, /* sym_init: read initial info, setup + for sym_read() */ + coff_symfile_read, /* sym_read: read a symbol file into + symtab */ + NULL, /* sym_read_psymbols */ + coff_symfile_finish, /* sym_finish: finished with file, + cleanup */ + default_symfile_offsets, /* sym_offsets: xlate external to + internal form */ + default_symfile_segments, /* sym_segments: Get segment + information from a file */ NULL, /* sym_read_linetable */ - default_symfile_relocate, /* sym_relocate: Relocate a debug section. */ - &psym_functions, - NULL /* next: pointer to next struct sym_fns */ + + default_symfile_relocate, /* sym_relocate: Relocate a debug + section. */ + &psym_functions }; void diff --git a/contrib/gdb-7/gdb/command.h b/contrib/gdb-7/gdb/command.h index f53dc3e75c..0e2547e7e3 100644 --- a/contrib/gdb-7/gdb/command.h +++ b/contrib/gdb-7/gdb/command.h @@ -1,7 +1,7 @@ /* Header file for command-reading library command.c. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, - 2002, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,8 +19,9 @@ #if !defined (COMMAND_H) #define COMMAND_H 1 -/* Command classes are top-level categories into which commands are broken - down for "help" purposes. +/* Command classes are top-level categories into which commands are + broken down for "help" purposes. + Notes on classes: class_alias is for alias commands which are not abbreviations of the original command. class-pseudo is for commands which are not really commands nor help topics ("stop"). */ @@ -30,10 +31,12 @@ enum command_class /* Special args to help_list */ class_deprecated = -3, all_classes = -2, all_commands = -1, /* Classes of commands */ - no_class = -1, class_run = 0, class_vars, class_stack, - class_files, class_support, class_info, class_breakpoint, class_trace, + no_class = -1, class_run = 0, class_vars, class_stack, class_files, + class_support, class_info, class_breakpoint, class_trace, class_alias, class_bookmark, class_obscure, class_maintenance, - class_pseudo, class_tui, class_user, class_xdb + class_pseudo, class_tui, class_user, class_xdb, + no_set_class /* Used for "show" commands that have no corresponding + "set" command. */ }; /* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum @@ -60,19 +63,20 @@ typedef enum var_types "auto. *VAR is an ``enum auto_boolean''. NOTE: In general a custom show command will need to be implemented - one that for "auto" prints both the "auto" and the current auto-selected - value. */ + value. */ var_auto_boolean, - /* Unsigned Integer. *VAR is an unsigned int. The user can type 0 - to mean "unlimited", which is stored in *VAR as UINT_MAX. */ + /* Unsigned Integer. *VAR is an unsigned int. The user can type + 0 to mean "unlimited", which is stored in *VAR as UINT_MAX. */ var_uinteger, - /* Like var_uinteger but signed. *VAR is an int. The user can type 0 - to mean "unlimited", which is stored in *VAR as INT_MAX. */ + /* Like var_uinteger but signed. *VAR is an int. The user can + type 0 to mean "unlimited", which is stored in *VAR as + INT_MAX. */ var_integer, - /* String which the user enters with escapes (e.g. the user types \n and - it is a real newline in the stored string). + /* String which the user enters with escapes (e.g. the user types + \n and it is a real newline in the stored string). *VAR is a malloc'd string, or NULL if the string is empty. */ var_string, /* String which stores what the user types verbatim. @@ -90,8 +94,9 @@ typedef enum var_types /* ZeroableUnsignedInteger. *VAR is an unsigned int. Zero really means zero. */ var_zuinteger, - /* Enumerated type. Can only have one of the specified values. *VAR is a - char pointer to the name of the element that we find. */ + /* Enumerated type. Can only have one of the specified values. + *VAR is a char pointer to the name of the element that we + find. */ var_enum } var_types; @@ -137,17 +142,18 @@ typedef void cmd_sfunc_ftype (char *args, int from_tty, extern void set_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc); -extern void set_cmd_completer (struct cmd_list_element *cmd, - char **(*completer) (struct cmd_list_element *cmd, - char *text, char *word)); +extern void set_cmd_completer (struct cmd_list_element *, + char **(*completer) (struct cmd_list_element *, + char *, char *)); /* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs around in cmd objects to test the value of the commands sfunc(). */ extern int cmd_cfunc_eq (struct cmd_list_element *cmd, void (*cfunc) (char *args, int from_tty)); -/* Each command object has a local context attached to it. . */ -extern void set_cmd_context (struct cmd_list_element *cmd, void *context); +/* Each command object has a local context attached to it. */ +extern void set_cmd_context (struct cmd_list_element *cmd, + void *context); extern void *get_cmd_context (struct cmd_list_element *cmd); @@ -170,39 +176,42 @@ extern struct cmd_list_element *lookup_cmd_1 (char **, struct cmd_list_element **, int); -extern struct cmd_list_element * - deprecate_cmd (struct cmd_list_element *, char * ); +extern struct cmd_list_element *deprecate_cmd (struct cmd_list_element *, + char * ); -extern void - deprecated_cmd_warning (char **); +extern void deprecated_cmd_warning (char **); -extern int - lookup_cmd_composition (char *text, - struct cmd_list_element **alias, - struct cmd_list_element **prefix_cmd, - struct cmd_list_element **cmd); +extern int lookup_cmd_composition (char *text, + struct cmd_list_element **alias, + struct cmd_list_element **prefix_cmd, + struct cmd_list_element **cmd); extern struct cmd_list_element *add_com (char *, enum command_class, - void (*fun) (char *, int), char *); + void (*fun) (char *, int), + char *); extern struct cmd_list_element *add_com_alias (char *, char *, enum command_class, int); -extern struct cmd_list_element *add_info (char *, void (*fun) (char *, int), +extern struct cmd_list_element *add_info (char *, + void (*fun) (char *, int), char *); extern struct cmd_list_element *add_info_alias (char *, char *, int); -extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *); +extern char **complete_on_cmdlist (struct cmd_list_element *, + char *, char *); -extern char **complete_on_enum (const char *enumlist[], char *, char *); +extern char **complete_on_enum (const char *enumlist[], + char *, char *); extern void help_cmd (char *, struct ui_file *); extern void help_list (struct cmd_list_element *, char *, enum command_class, struct ui_file *); -extern void help_cmd_list (struct cmd_list_element *, enum command_class, +extern void help_cmd_list (struct cmd_list_element *, + enum command_class, char *, int, struct ui_file *); /* Method for show a set/show variable's VALUE on FILE. If this @@ -342,22 +351,25 @@ extern void add_setshow_zuinteger_cmd (char *name, extern void cmd_show_list (struct cmd_list_element *, int, char *); /* Used everywhere whenever at least one parameter is required and - none is specified. */ + none is specified. */ extern void error_no_arg (char *) ATTRIBUTE_NORETURN; extern void dont_repeat (void); +extern struct cleanup *prevent_dont_repeat (void); + /* Used to mark commands that don't do anything. If we just leave the function field NULL, the command is interpreted as a help topic, or as a class of commands. */ extern void not_just_help_class_command (char *, int); -/* check function pointer */ +/* Check function pointer. */ extern int cmd_func_p (struct cmd_list_element *cmd); -/* call the command function */ -extern void cmd_func (struct cmd_list_element *cmd, char *args, int from_tty); +/* Call the command function. */ +extern void cmd_func (struct cmd_list_element *cmd, + char *args, int from_tty); #endif /* !defined (COMMAND_H) */ diff --git a/contrib/gdb-7/gdb/common/ax.def b/contrib/gdb-7/gdb/common/ax.def new file mode 100644 index 0000000000..5fe2ebfdd2 --- /dev/null +++ b/contrib/gdb-7/gdb/common/ax.def @@ -0,0 +1,97 @@ +/* Definition of agent opcode values. -*- c -*- + Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* The actual values of the various bytecode operations. + + Other independent implementations of the agent bytecode engine will + rely on the exact values of these enums, and may not be recompiled + when we change this table. The numeric values should remain fixed + whenever possible. Thus, we assign them values explicitly here (to + allow gaps to form safely), and the disassembly table in + agentexpr.h behaves like an opcode map. If you want to see them + grouped logically, see doc/agentexpr.texi. + + Each line is of the form: + + DEFOP (name, size, data_size, consumed, produced, opcode) + + NAME is the name of the operation. + SIZE is the number of argument bytes that the operation takes from + the bytecode stream. + DATA_SIZE is the size of data operated on, in bits, for operations + that care (ref and const). It is zero otherwise. + CONSUMED is the number of stack elements consumed. + PRODUCED is the number of stack elements produced. + OPCODE is the operation's encoding. */ + +DEFOP (float, 0, 0, 0, 0, 0x01) +DEFOP (add, 0, 0, 2, 1, 0x02) +DEFOP (sub, 0, 0, 2, 1, 0x03) +DEFOP (mul, 0, 0, 2, 1, 0x04) +DEFOP (div_signed, 0, 0, 2, 1, 0x05) +DEFOP (div_unsigned, 0, 0, 2, 1, 0x06) +DEFOP (rem_signed, 0, 0, 2, 1, 0x07) +DEFOP (rem_unsigned, 0, 0, 2, 1, 0x08) +DEFOP (lsh, 0, 0, 2, 1, 0x09) +DEFOP (rsh_signed, 0, 0, 2, 1, 0x0a) +DEFOP (rsh_unsigned, 0, 0, 2, 1, 0x0b) +DEFOP (trace, 0, 0, 2, 0, 0x0c) +DEFOP (trace_quick, 1, 0, 1, 1, 0x0d) +DEFOP (log_not, 0, 0, 1, 1, 0x0e) +DEFOP (bit_and, 0, 0, 2, 1, 0x0f) +DEFOP (bit_or, 0, 0, 2, 1, 0x10) +DEFOP (bit_xor, 0, 0, 2, 1, 0x11) +DEFOP (bit_not, 0, 0, 1, 1, 0x12) +DEFOP (equal, 0, 0, 2, 1, 0x13) +DEFOP (less_signed, 0, 0, 2, 1, 0x14) +DEFOP (less_unsigned, 0, 0, 2, 1, 0x15) +DEFOP (ext, 1, 0, 1, 1, 0x16) +DEFOP (ref8, 0, 8, 1, 1, 0x17) +DEFOP (ref16, 0, 16, 1, 1, 0x18) +DEFOP (ref32, 0, 32, 1, 1, 0x19) +DEFOP (ref64, 0, 64, 1, 1, 0x1a) +DEFOP (ref_float, 0, 0, 1, 1, 0x1b) +DEFOP (ref_double, 0, 0, 1, 1, 0x1c) +DEFOP (ref_long_double, 0, 0, 1, 1, 0x1d) +DEFOP (l_to_d, 0, 0, 1, 1, 0x1e) +DEFOP (d_to_l, 0, 0, 1, 1, 0x1f) +DEFOP (if_goto, 2, 0, 1, 0, 0x20) +DEFOP (goto, 2, 0, 0, 0, 0x21) +DEFOP (const8, 1, 8, 0, 1, 0x22) +DEFOP (const16, 2, 16, 0, 1, 0x23) +DEFOP (const32, 4, 32, 0, 1, 0x24) +DEFOP (const64, 8, 64, 0, 1, 0x25) +DEFOP (reg, 2, 0, 0, 1, 0x26) +DEFOP (end, 0, 0, 0, 0, 0x27) +DEFOP (dup, 0, 0, 1, 2, 0x28) +DEFOP (pop, 0, 0, 1, 0, 0x29) +DEFOP (zero_ext, 1, 0, 1, 1, 0x2a) +DEFOP (swap, 0, 0, 2, 2, 0x2b) +DEFOP (getv, 2, 0, 0, 1, 0x2c) +DEFOP (setv, 2, 0, 0, 1, 0x2d) +DEFOP (tracev, 2, 0, 0, 1, 0x2e) +/* We need something here just to make the tables come out ok. */ +DEFOP (invalid, 0, 0, 0, 0, 0x2f) +DEFOP (trace16, 2, 0, 1, 1, 0x30) +/* We need something here just to make the tables come out ok. */ +DEFOP (invalid2, 0, 0, 0, 0, 0x31) +/* The "consumed" number for pick is wrong, but there's no way to + express the right thing. */ +DEFOP (pick, 1, 0, 0, 1, 0x32) +DEFOP (rot, 0, 0, 3, 3, 0x33) diff --git a/contrib/gdb-7/gdb/common/gdb_signals.h b/contrib/gdb-7/gdb/common/gdb_signals.h index 476d89b953..c04d795279 100644 --- a/contrib/gdb-7/gdb/common/gdb_signals.h +++ b/contrib/gdb-7/gdb/common/gdb_signals.h @@ -1,6 +1,6 @@ /* Target signal translation functions for GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. diff --git a/contrib/gdb-7/gdb/common/i386-xstate.h b/contrib/gdb-7/gdb/common/i386-xstate.h index ec40a0de58..5a081f4d63 100644 --- a/contrib/gdb-7/gdb/common/i386-xstate.h +++ b/contrib/gdb-7/gdb/common/i386-xstate.h @@ -1,6 +1,6 @@ /* Common code for i386 XSAVE extended state. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/common/signals.c b/contrib/gdb-7/gdb/common/signals.c index 1dec502738..55f708493d 100644 --- a/contrib/gdb-7/gdb/common/signals.c +++ b/contrib/gdb-7/gdb/common/signals.c @@ -1,6 +1,6 @@ /* Target signal translation functions for GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -48,175 +48,18 @@ struct gdbarch; # endif #endif -/* This table must match in order and size the signals in enum target_signal - in src/include/gdb/signals.h. */ -/* *INDENT-OFF* */ +/* This table must match in order and size the signals in enum + target_signal. */ + static const struct { const char *name; const char *string; } signals [] = { - {"0", "Signal 0"}, - {"SIGHUP", "Hangup"}, - {"SIGINT", "Interrupt"}, - {"SIGQUIT", "Quit"}, - {"SIGILL", "Illegal instruction"}, - {"SIGTRAP", "Trace/breakpoint trap"}, - {"SIGABRT", "Aborted"}, - {"SIGEMT", "Emulation trap"}, - {"SIGFPE", "Arithmetic exception"}, - {"SIGKILL", "Killed"}, - {"SIGBUS", "Bus error"}, - {"SIGSEGV", "Segmentation fault"}, - {"SIGSYS", "Bad system call"}, - {"SIGPIPE", "Broken pipe"}, - {"SIGALRM", "Alarm clock"}, - {"SIGTERM", "Terminated"}, - {"SIGURG", "Urgent I/O condition"}, - {"SIGSTOP", "Stopped (signal)"}, - {"SIGTSTP", "Stopped (user)"}, - {"SIGCONT", "Continued"}, - {"SIGCHLD", "Child status changed"}, - {"SIGTTIN", "Stopped (tty input)"}, - {"SIGTTOU", "Stopped (tty output)"}, - {"SIGIO", "I/O possible"}, - {"SIGXCPU", "CPU time limit exceeded"}, - {"SIGXFSZ", "File size limit exceeded"}, - {"SIGVTALRM", "Virtual timer expired"}, - {"SIGPROF", "Profiling timer expired"}, - {"SIGWINCH", "Window size changed"}, - {"SIGLOST", "Resource lost"}, - {"SIGUSR1", "User defined signal 1"}, - {"SIGUSR2", "User defined signal 2"}, - {"SIGPWR", "Power fail/restart"}, - {"SIGPOLL", "Pollable event occurred"}, - {"SIGWIND", "SIGWIND"}, - {"SIGPHONE", "SIGPHONE"}, - {"SIGWAITING", "Process's LWPs are blocked"}, - {"SIGLWP", "Signal LWP"}, - {"SIGDANGER", "Swap space dangerously low"}, - {"SIGGRANT", "Monitor mode granted"}, - {"SIGRETRACT", "Need to relinquish monitor mode"}, - {"SIGMSG", "Monitor mode data available"}, - {"SIGSOUND", "Sound completed"}, - {"SIGSAK", "Secure attention"}, - {"SIGPRIO", "SIGPRIO"}, - {"SIG33", "Real-time event 33"}, - {"SIG34", "Real-time event 34"}, - {"SIG35", "Real-time event 35"}, - {"SIG36", "Real-time event 36"}, - {"SIG37", "Real-time event 37"}, - {"SIG38", "Real-time event 38"}, - {"SIG39", "Real-time event 39"}, - {"SIG40", "Real-time event 40"}, - {"SIG41", "Real-time event 41"}, - {"SIG42", "Real-time event 42"}, - {"SIG43", "Real-time event 43"}, - {"SIG44", "Real-time event 44"}, - {"SIG45", "Real-time event 45"}, - {"SIG46", "Real-time event 46"}, - {"SIG47", "Real-time event 47"}, - {"SIG48", "Real-time event 48"}, - {"SIG49", "Real-time event 49"}, - {"SIG50", "Real-time event 50"}, - {"SIG51", "Real-time event 51"}, - {"SIG52", "Real-time event 52"}, - {"SIG53", "Real-time event 53"}, - {"SIG54", "Real-time event 54"}, - {"SIG55", "Real-time event 55"}, - {"SIG56", "Real-time event 56"}, - {"SIG57", "Real-time event 57"}, - {"SIG58", "Real-time event 58"}, - {"SIG59", "Real-time event 59"}, - {"SIG60", "Real-time event 60"}, - {"SIG61", "Real-time event 61"}, - {"SIG62", "Real-time event 62"}, - {"SIG63", "Real-time event 63"}, - {"SIGCANCEL", "LWP internal signal"}, - {"SIG32", "Real-time event 32"}, - {"SIG64", "Real-time event 64"}, - {"SIG65", "Real-time event 65"}, - {"SIG66", "Real-time event 66"}, - {"SIG67", "Real-time event 67"}, - {"SIG68", "Real-time event 68"}, - {"SIG69", "Real-time event 69"}, - {"SIG70", "Real-time event 70"}, - {"SIG71", "Real-time event 71"}, - {"SIG72", "Real-time event 72"}, - {"SIG73", "Real-time event 73"}, - {"SIG74", "Real-time event 74"}, - {"SIG75", "Real-time event 75"}, - {"SIG76", "Real-time event 76"}, - {"SIG77", "Real-time event 77"}, - {"SIG78", "Real-time event 78"}, - {"SIG79", "Real-time event 79"}, - {"SIG80", "Real-time event 80"}, - {"SIG81", "Real-time event 81"}, - {"SIG82", "Real-time event 82"}, - {"SIG83", "Real-time event 83"}, - {"SIG84", "Real-time event 84"}, - {"SIG85", "Real-time event 85"}, - {"SIG86", "Real-time event 86"}, - {"SIG87", "Real-time event 87"}, - {"SIG88", "Real-time event 88"}, - {"SIG89", "Real-time event 89"}, - {"SIG90", "Real-time event 90"}, - {"SIG91", "Real-time event 91"}, - {"SIG92", "Real-time event 92"}, - {"SIG93", "Real-time event 93"}, - {"SIG94", "Real-time event 94"}, - {"SIG95", "Real-time event 95"}, - {"SIG96", "Real-time event 96"}, - {"SIG97", "Real-time event 97"}, - {"SIG98", "Real-time event 98"}, - {"SIG99", "Real-time event 99"}, - {"SIG100", "Real-time event 100"}, - {"SIG101", "Real-time event 101"}, - {"SIG102", "Real-time event 102"}, - {"SIG103", "Real-time event 103"}, - {"SIG104", "Real-time event 104"}, - {"SIG105", "Real-time event 105"}, - {"SIG106", "Real-time event 106"}, - {"SIG107", "Real-time event 107"}, - {"SIG108", "Real-time event 108"}, - {"SIG109", "Real-time event 109"}, - {"SIG110", "Real-time event 110"}, - {"SIG111", "Real-time event 111"}, - {"SIG112", "Real-time event 112"}, - {"SIG113", "Real-time event 113"}, - {"SIG114", "Real-time event 114"}, - {"SIG115", "Real-time event 115"}, - {"SIG116", "Real-time event 116"}, - {"SIG117", "Real-time event 117"}, - {"SIG118", "Real-time event 118"}, - {"SIG119", "Real-time event 119"}, - {"SIG120", "Real-time event 120"}, - {"SIG121", "Real-time event 121"}, - {"SIG122", "Real-time event 122"}, - {"SIG123", "Real-time event 123"}, - {"SIG124", "Real-time event 124"}, - {"SIG125", "Real-time event 125"}, - {"SIG126", "Real-time event 126"}, - {"SIG127", "Real-time event 127"}, - - {"SIGINFO", "Information request"}, - - {NULL, "Unknown signal"}, - {NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"}, - - /* Mach exceptions */ - {"EXC_BAD_ACCESS", "Could not access memory"}, - {"EXC_BAD_INSTRUCTION", "Illegal instruction/operand"}, - {"EXC_ARITHMETIC", "Arithmetic exception"}, - {"EXC_EMULATION", "Emulation instruction"}, - {"EXC_SOFTWARE", "Software generated exception"}, - {"EXC_BREAKPOINT", "Breakpoint"}, - - /* Last entry, used to check whether the table is the right size. */ - {NULL, "TARGET_SIGNAL_MAGIC"} +#define SET(symbol, constant, name, string) { name, string }, +#include "gdb/signals.def" +#undef SET }; -/* *INDENT-ON* */ - /* Return the string for a signal. */ @@ -506,7 +349,8 @@ target_signal_from_host (int hostsig) return (enum target_signal) (hostsig - 64 + (int) TARGET_SIGNAL_REALTIME_64); else - error ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal"); + error (_("GDB bug: target.c (target_signal_from_host): " + "unrecognized real-time signal")); } #endif @@ -800,7 +644,7 @@ target_signal_to_host (enum target_signal oursig) { /* The user might be trying to do "signal SIGSAK" where this system doesn't have SIGSAK. */ - warning ("Signal %s does not exist on this system.\n", + warning (_("Signal %s does not exist on this system."), target_signal_to_name (oursig)); return 0; } @@ -823,8 +667,8 @@ target_signal_from_command (int num) { if (num >= 1 && num <= 15) return (enum target_signal) num; - error ("Only signals 1-15 are valid as numeric signals.\n\ -Use \"info signals\" for a list of symbolic signals."); + error (_("Only signals 1-15 are valid as numeric signals.\n\ +Use \"info signals\" for a list of symbolic signals.")); } extern initialize_file_ftype _initialize_signals; /* -Wmissing-prototype */ diff --git a/contrib/gdb-7/gdb/complaints.c b/contrib/gdb-7/gdb/complaints.c index 476f3f4331..9129b98a6e 100644 --- a/contrib/gdb-7/gdb/complaints.c +++ b/contrib/gdb-7/gdb/complaints.c @@ -1,7 +1,7 @@ /* Support for complaint handling during symbol reading in GDB. Copyright (C) 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000, 2002, 2004, - 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -26,8 +26,8 @@ extern void _initialize_complaints (void); -/* Should each complaint message be self explanatory, or should we assume that - a series of complaints is being produced? */ +/* Should each complaint message be self explanatory, or should we + assume that a series of complaints is being produced? */ /* case 1: First message of a series that must start off with explanation. case 2: Subsequent message of a series @@ -165,11 +165,13 @@ static int stop_whining = 0; later handling. */ static void ATTRIBUTE_PRINTF (4, 0) -vcomplaint (struct complaints **c, const char *file, int line, const char *fmt, +vcomplaint (struct complaints **c, const char *file, + int line, const char *fmt, va_list args) { struct complaints *complaints = get_complaints (c); - struct complain *complaint = find_complaint (complaints, file, line, fmt); + struct complain *complaint = find_complaint (complaints, file, + line, fmt); enum complaint_series series; gdb_assert (complaints != NULL); @@ -184,7 +186,8 @@ vcomplaint (struct complaints **c, const char *file, int line, const char *fmt, series = complaints->series; if (complaint->file != NULL) - internal_vwarning (complaint->file, complaint->line, complaint->fmt, args); + internal_vwarning (complaint->file, complaint->line, + complaint->fmt, args); else if (deprecated_warning_hook) (*deprecated_warning_hook) (complaint->fmt, args); else @@ -294,7 +297,8 @@ clear_complaints (struct complaints **c, int less_verbose, int noisy) case SUBSEQUENT_MESSAGE: /* It would be really nice to use begin_line() here. Unfortunately that function doesn't track GDB_STDERR and - consequently will sometimes supress a line when it shouldn't. */ + consequently will sometimes supress a line when it + shouldn't. */ fputs_unfiltered ("\n", gdb_stderr); break; default: @@ -321,7 +325,8 @@ complaints_show_value (struct ui_file *file, int from_tty, void _initialize_complaints (void) { - add_setshow_zinteger_cmd ("complaints", class_support, &stop_whining, _("\ + add_setshow_zinteger_cmd ("complaints", class_support, + &stop_whining, _("\ Set max number of complaints about incorrect symbols."), _("\ Show max number of complaints about incorrect symbols."), NULL, NULL, complaints_show_value, diff --git a/contrib/gdb-7/gdb/complaints.h b/contrib/gdb-7/gdb/complaints.h index 4ff8d9bd87..c18ec69b6b 100644 --- a/contrib/gdb-7/gdb/complaints.h +++ b/contrib/gdb-7/gdb/complaints.h @@ -1,7 +1,7 @@ /* Definitions for complaint handling during symbol reading in GDB. Copyright (C) 1990, 1991, 1992, 1995, 1998, 2000, 2002, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -30,10 +30,12 @@ struct complaints; extern struct complaints *symfile_complaints; /* Register a complaint. */ -extern void complaint (struct complaints **complaints, const char *fmt, +extern void complaint (struct complaints **complaints, + const char *fmt, ...) ATTRIBUTE_PRINTF (2, 3); extern void internal_complaint (struct complaints **complaints, - const char *file, int line, const char *fmt, + const char *file, int line, + const char *fmt, ...) ATTRIBUTE_PRINTF (4, 5); /* Clear out / initialize all complaint counters that have ever been diff --git a/contrib/gdb-7/gdb/completer.c b/contrib/gdb-7/gdb/completer.c index 3ba481ee52..606f78b38a 100644 --- a/contrib/gdb-7/gdb/completer.c +++ b/contrib/gdb-7/gdb/completer.c @@ -1,5 +1,5 @@ /* Line completion stuff for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -24,6 +24,7 @@ #include "filenames.h" /* For DOSish file names. */ #include "language.h" #include "gdb_assert.h" +#include "exceptions.h" #include "cli/cli-decode.h" @@ -49,21 +50,22 @@ char *line_completion_function (const char *text, int matches, /* readline uses the word breaks for two things: (1) In figuring out where to point the TEXT parameter to the rl_completion_entry_function. Since we don't use TEXT for much, - it doesn't matter a lot what the word breaks are for this purpose, but - it does affect how much stuff M-? lists. + it doesn't matter a lot what the word breaks are for this purpose, + but it does affect how much stuff M-? lists. (2) If one of the matches contains a word break character, readline will quote it. That's why we switch between current_language->la_word_break_characters() and gdb_completer_command_word_break_characters. I'm not sure when - we need this behavior (perhaps for funky characters in C++ symbols?). */ + we need this behavior (perhaps for funky characters in C++ + symbols?). */ /* Variables which are necessary for fancy command line editing. */ /* When completing on command names, we remove '-' from the list of word break characters, since we use it in command names. If the readline library sees one in any of the current completion strings, - it thinks that the string needs to be quoted and automatically supplies - a leading quote. */ + it thinks that the string needs to be quoted and automatically + supplies a leading quote. */ static char *gdb_completer_command_word_break_characters = " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,"; @@ -79,9 +81,9 @@ static char *gdb_completer_file_name_break_characters = " \t\n*|\"';?><@"; static char *gdb_completer_file_name_break_characters = " \t\n*|\"';:?><"; #endif -/* Characters that can be used to quote completion strings. Note that we - can't include '"' because the gdb C parser treats such quoted sequences - as strings. */ +/* Characters that can be used to quote completion strings. Note that + we can't include '"' because the gdb C parser treats such quoted + sequences as strings. */ static char *gdb_completer_quote_characters = "'"; /* Accessor for some completer data that may interest other files. */ @@ -97,20 +99,23 @@ get_gdb_completer_quote_characters (void) char * readline_line_completion_function (const char *text, int matches) { - return line_completion_function (text, matches, rl_line_buffer, rl_point); + return line_completion_function (text, matches, + rl_line_buffer, rl_point); } -/* This can be used for functions which don't want to complete on symbols - but don't want to complete on anything else either. */ +/* This can be used for functions which don't want to complete on + symbols but don't want to complete on anything else either. */ char ** -noop_completer (struct cmd_list_element *ignore, char *text, char *prefix) +noop_completer (struct cmd_list_element *ignore, + char *text, char *prefix) { return NULL; } /* Complete on filenames. */ char ** -filename_completer (struct cmd_list_element *ignore, char *text, char *word) +filename_completer (struct cmd_list_element *ignore, + char *text, char *word) { int subsequent_name; char **return_val; @@ -141,12 +146,12 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word) break; } /* We need to set subsequent_name to a non-zero value before the - continue line below, because otherwise, if the first file seen - by GDB is a backup file whose name ends in a `~', we will loop - indefinitely. */ + continue line below, because otherwise, if the first file + seen by GDB is a backup file whose name ends in a `~', we + will loop indefinitely. */ subsequent_name = 1; - /* Like emacs, don't complete on old versions. Especially useful - in the "source" command. */ + /* Like emacs, don't complete on old versions. Especially + useful in the "source" command. */ if (p[strlen (p) - 1] == '~') { xfree (p); @@ -176,9 +181,9 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word) } } #if 0 - /* There is no way to do this just long enough to affect quote inserting - without also affecting the next completion. This should be fixed in - readline. FIXME. */ + /* There is no way to do this just long enough to affect quote + inserting without also affecting the next completion. This + should be fixed in readline. FIXME. */ /* Ensure that readline does the right thing with respect to inserting quotes. */ rl_completer_word_break_characters = ""; @@ -192,9 +197,12 @@ filename_completer (struct cmd_list_element *ignore, char *text, char *word) or symbol+offset - This is intended to be used in commands that set breakpoints etc. */ + This is intended to be used in commands that set breakpoints + etc. */ + char ** -location_completer (struct cmd_list_element *ignore, char *text, char *word) +location_completer (struct cmd_list_element *ignore, + char *text, char *word) { int n_syms = 0, n_files = 0; char ** fn_list = NULL; @@ -350,7 +358,15 @@ count_struct_fields (struct type *type) if (i < TYPE_N_BASECLASSES (type)) result += count_struct_fields (TYPE_BASECLASS (type, i)); else if (TYPE_FIELD_NAME (type, i)) - ++result; + { + if (TYPE_FIELD_NAME (type, i)[0] != '\0') + ++result; + else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION) + { + /* Recurse into anonymous unions. */ + result += count_struct_fields (TYPE_FIELD_TYPE (type, i)); + } + } } for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i) @@ -377,13 +393,25 @@ add_struct_fields (struct type *type, int *nextp, char **output, for (i = 0; i < TYPE_NFIELDS (type); ++i) { if (i < TYPE_N_BASECLASSES (type)) - add_struct_fields (TYPE_BASECLASS (type, i), nextp, output, - fieldname, namelen); - else if (TYPE_FIELD_NAME (type, i) - && ! strncmp (TYPE_FIELD_NAME (type, i), fieldname, namelen)) + add_struct_fields (TYPE_BASECLASS (type, i), nextp, + output, fieldname, namelen); + else if (TYPE_FIELD_NAME (type, i)) { - output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i)); - ++*nextp; + if (TYPE_FIELD_NAME (type, i)[0] != '\0') + { + if (! strncmp (TYPE_FIELD_NAME (type, i), + fieldname, namelen)) + { + output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i)); + ++*nextp; + } + } + else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION) + { + /* Recurse into anonymous unions. */ + add_struct_fields (TYPE_FIELD_TYPE (type, i), nextp, + output, fieldname, namelen); + } } } @@ -412,15 +440,22 @@ add_struct_fields (struct type *type, int *nextp, char **output, names, but some language parsers also have support for completing field names. */ char ** -expression_completer (struct cmd_list_element *ignore, char *text, char *word) +expression_completer (struct cmd_list_element *ignore, + char *text, char *word) { - struct type *type; + struct type *type = NULL; char *fieldname, *p; + volatile struct gdb_exception except; /* Perform a tentative parse of the expression, to see whether a field completion is required. */ fieldname = NULL; - type = parse_field_expression (text, &fieldname); + TRY_CATCH (except, RETURN_MASK_ERROR) + { + type = parse_field_expression (text, &fieldname); + } + if (except.reason < 0) + return NULL; if (fieldname && type) { for (;;) @@ -455,12 +490,13 @@ expression_completer (struct cmd_list_element *ignore, char *text, char *word) p--) ; - /* Not ideal but it is what we used to do before... */ + /* Not ideal but it is what we used to do before... */ return location_completer (ignore, p, word); } -/* Here are some useful test cases for completion. FIXME: These should - be put in the test suite. They should be tested with both M-? and TAB. +/* Here are some useful test cases for completion. FIXME: These + should be put in the test suite. They should be tested with both + M-? and TAB. "show output-" "radix" "show output" "-radix" @@ -495,18 +531,18 @@ complete_line_internal_reason; TEXT is the caller's idea of the "word" we are looking at. - LINE_BUFFER is available to be looked at; it contains the entire text - of the line. POINT is the offset in that line of the cursor. You - should pretend that the line ends at POINT. + LINE_BUFFER is available to be looked at; it contains the entire + text of the line. POINT is the offset in that line of the cursor. + You should pretend that the line ends at POINT. REASON is of type complete_line_internal_reason. If REASON is handle_brkchars: - Preliminary phase, called by gdb_completion_word_break_characters function, - is used to determine the correct set of chars that are word delimiters - depending on the current command in line_buffer. - No completion list should be generated; the return value should be NULL. - This is checked by an assertion in that function. + Preliminary phase, called by gdb_completion_word_break_characters + function, is used to determine the correct set of chars that are + word delimiters depending on the current command in line_buffer. + No completion list should be generated; the return value should be + NULL. This is checked by an assertion in that function. If REASON is handle_completions: Main phase, called by complete_line function, is used to get the list @@ -518,7 +554,8 @@ complete_line_internal_reason; */ static char ** -complete_line_internal (const char *text, char *line_buffer, int point, +complete_line_internal (const char *text, + char *line_buffer, int point, complete_line_internal_reason reason) { char **list = NULL; @@ -527,16 +564,18 @@ complete_line_internal (const char *text, char *line_buffer, int point, char *word; struct cmd_list_element *c, *result_list; - /* Choose the default set of word break characters to break completions. - If we later find out that we are doing completions on command strings - (as opposed to strings supplied by the individual command completer - functions, which can be any string) then we will switch to the - special word break set for command strings, which leaves out the - '-' character used in some commands. */ + /* Choose the default set of word break characters to break + completions. If we later find out that we are doing completions + on command strings (as opposed to strings supplied by the + individual command completer functions, which can be any string) + then we will switch to the special word break set for command + strings, which leaves out the '-' character used in some + commands. */ rl_completer_word_break_characters = current_language->la_word_break_characters(); - /* Decide whether to complete on a list of gdb commands or on symbols. */ + /* Decide whether to complete on a list of gdb commands or on + symbols. */ tmp_command = (char *) alloca (point + 1); p = tmp_command; @@ -551,7 +590,7 @@ complete_line_internal (const char *text, char *line_buffer, int point, { /* An empty line we want to consider ambiguous; that is, it could be any command. */ - c = (struct cmd_list_element *) -1; + c = CMD_LIST_AMBIGUOUS; result_list = 0; } else @@ -571,7 +610,7 @@ complete_line_internal (const char *text, char *line_buffer, int point, possible completions. */ list = NULL; } - else if (c == (struct cmd_list_element *) -1) + else if (c == CMD_LIST_AMBIGUOUS) { char *q; @@ -616,12 +655,13 @@ complete_line_internal (const char *text, char *line_buffer, int point, if (p == tmp_command + point) { - /* There is no non-whitespace in the line beyond the command. */ + /* There is no non-whitespace in the line beyond the + command. */ if (p[-1] == ' ' || p[-1] == '\t') { - /* The command is followed by whitespace; we need to complete - on whatever comes after command. */ + /* The command is followed by whitespace; we need to + complete on whatever comes after command. */ if (c->prefixlist) { /* It is a prefix command; what comes after it is @@ -682,7 +722,7 @@ complete_line_internal (const char *text, char *line_buffer, int point, else { /* The command is not followed by whitespace; we need to - complete on the command itself. e.g. "p" which is a + complete on the command itself, e.g. "p" which is a command itself but also can complete to "print", "ptype" etc. */ char *q; @@ -732,7 +772,8 @@ complete_line_internal (const char *text, char *line_buffer, int point, of file-name completion. */ for (p = word; p > tmp_command - && strchr (gdb_completer_file_name_break_characters, p[-1]) == NULL; + && strchr (gdb_completer_file_name_break_characters, + p[-1]) == NULL; p--) ; rl_completer_word_break_characters = @@ -760,8 +801,8 @@ complete_line_internal (const char *text, char *line_buffer, int point, TEXT is the caller's idea of the "word" we are looking at. - LINE_BUFFER is available to be looked at; it contains the entire text - of the line. + LINE_BUFFER is available to be looked at; it contains the entire + text of the line. POINT is the offset in that line of the cursor. You should pretend that the line ends at POINT. */ @@ -769,14 +810,17 @@ complete_line_internal (const char *text, char *line_buffer, int point, char ** complete_line (const char *text, char *line_buffer, int point) { - return complete_line_internal (text, line_buffer, point, handle_completions); + return complete_line_internal (text, line_buffer, + point, handle_completions); } /* Complete on command names. Used by "help". */ char ** -command_completer (struct cmd_list_element *ignore, char *text, char *word) +command_completer (struct cmd_list_element *ignore, + char *text, char *word) { - return complete_line_internal (word, text, strlen (text), handle_help); + return complete_line_internal (word, text, + strlen (text), handle_help); } /* Get the list of chars that are considered as word breaks @@ -793,26 +837,26 @@ gdb_completion_word_break_characters (void) return rl_completer_word_break_characters; } -/* Generate completions one by one for the completer. Each time we are - called return another potential completion to the caller. - line_completion just completes on commands or passes the buck to the - command's completer function, the stuff specific to symbol completion - is in make_symbol_completion_list. +/* Generate completions one by one for the completer. Each time we + are called return another potential completion to the caller. + line_completion just completes on commands or passes the buck to + the command's completer function, the stuff specific to symbol + completion is in make_symbol_completion_list. TEXT is the caller's idea of the "word" we are looking at. - MATCHES is the number of matches that have currently been collected from - calling this completion function. When zero, then we need to initialize, - otherwise the initialization has already taken place and we can just - return the next potential completion string. + MATCHES is the number of matches that have currently been collected + from calling this completion function. When zero, then we need to + initialize, otherwise the initialization has already taken place + and we can just return the next potential completion string. - LINE_BUFFER is available to be looked at; it contains the entire text - of the line. POINT is the offset in that line of the cursor. You - should pretend that the line ends at POINT. + LINE_BUFFER is available to be looked at; it contains the entire + text of the line. POINT is the offset in that line of the cursor. + You should pretend that the line ends at POINT. - Returns NULL if there are no more completions, else a pointer to a string - which is a possible completion, it is the caller's responsibility to - free the string. */ + Returns NULL if there are no more completions, else a pointer to a + string which is a possible completion, it is the caller's + responsibility to free the string. */ static char * line_completion_function (const char *text, int matches, @@ -824,15 +868,16 @@ line_completion_function (const char *text, int matches, if (matches == 0) { - /* The caller is beginning to accumulate a new set of completions, so - we need to find all of them now, and cache them for returning one at - a time on future calls. */ + /* The caller is beginning to accumulate a new set of + completions, so we need to find all of them now, and cache + them for returning one at a time on future calls. */ if (list) { - /* Free the storage used by LIST, but not by the strings inside. - This is because rl_complete_internal () frees the strings. - As complete_line may abort by calling `error' clear LIST now. */ + /* Free the storage used by LIST, but not by the strings + inside. This is because rl_complete_internal () frees + the strings. As complete_line may abort by calling + `error' clear LIST now. */ xfree (list); list = NULL; } @@ -840,11 +885,11 @@ line_completion_function (const char *text, int matches, list = complete_line (text, line_buffer, point); } - /* If we found a list of potential completions during initialization then - dole them out one at a time. The vector of completions is NULL - terminated, so after returning the last one, return NULL (and continue - to do so) each time we are called after that, until a new list is - available. */ + /* If we found a list of potential completions during initialization + then dole them out one at a time. The vector of completions is + NULL terminated, so after returning the last one, return NULL + (and continue to do so) each time we are called after that, until + a new list is available. */ if (list) { @@ -859,8 +904,8 @@ line_completion_function (const char *text, int matches, /* Can't do this because readline hasn't yet checked the word breaks for figuring out whether to insert a quote. */ if (output == NULL) - /* Make sure the word break characters are set back to normal for the - next time that readline tries to complete something. */ + /* Make sure the word break characters are set back to normal for + the next time that readline tries to complete something. */ rl_completer_word_break_characters = current_language->la_word_break_characters(); #endif @@ -869,10 +914,10 @@ line_completion_function (const char *text, int matches, } /* Skip over the possibly quoted word STR (as defined by the quote - characters QUOTECHARS and the the word break characters - BREAKCHARS). Returns pointer to the location after the "word". If - either QUOTECHARS or BREAKCHARS is NULL, use the same values used - by the completer. */ + characters QUOTECHARS and the word break characters BREAKCHARS). + Returns pointer to the location after the "word". If either + QUOTECHARS or BREAKCHARS is NULL, use the same values used by the + completer. */ char * skip_quoted_chars (char *str, char *quotechars, char *breakchars) @@ -900,7 +945,7 @@ skip_quoted_chars (char *str, char *quotechars, char *breakchars) } else if (strchr (quotechars, *scan)) { - /* Found start of a quoted string. */ + /* Found start of a quoted string. */ quote_char = *scan; } else if (strchr (breakchars, *scan)) diff --git a/contrib/gdb-7/gdb/completer.h b/contrib/gdb-7/gdb/completer.h index 817530497d..18367e53ff 100644 --- a/contrib/gdb-7/gdb/completer.h +++ b/contrib/gdb-7/gdb/completer.h @@ -1,5 +1,6 @@ /* Header for GDB line completion. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,19 +18,27 @@ #if !defined (COMPLETER_H) #define COMPLETER_H 1 -extern char **complete_line (const char *text, char *line_buffer, int point); +extern char **complete_line (const char *text, + char *line_buffer, + int point); -extern char *readline_line_completion_function (const char *text, int matches); +extern char *readline_line_completion_function (const char *text, + int matches); -extern char **noop_completer (struct cmd_list_element *, char *, char *); +extern char **noop_completer (struct cmd_list_element *, + char *, char *); -extern char **filename_completer (struct cmd_list_element *, char *, char *); +extern char **filename_completer (struct cmd_list_element *, + char *, char *); -extern char **expression_completer (struct cmd_list_element *, char *, char *); +extern char **expression_completer (struct cmd_list_element *, + char *, char *); -extern char **location_completer (struct cmd_list_element *, char *, char *); +extern char **location_completer (struct cmd_list_element *, + char *, char *); -extern char **command_completer (struct cmd_list_element *, char *, char *); +extern char **command_completer (struct cmd_list_element *, + char *, char *); extern char *get_gdb_completer_quote_characters (void); diff --git a/contrib/gdb-7/gdb/config.in b/contrib/gdb-7/gdb/config.in index 1fc457daf4..01ba750ebd 100644 --- a/contrib/gdb-7/gdb/config.in +++ b/contrib/gdb-7/gdb/config.in @@ -118,6 +118,10 @@ */ #undef HAVE_DECL_GETOPT +/* Define to 1 if you have the declaration of `getthrds', and to 0 if you + don't. */ +#undef HAVE_DECL_GETTHRDS + /* Define to 1 if you have the declaration of `malloc', and to 0 if you don't. */ #undef HAVE_DECL_MALLOC @@ -190,9 +194,6 @@ /* Define if has gregset_t. */ #undef HAVE_GREGSET_T -/* Define if you have HPUX threads */ -#undef HAVE_HPUX_THREAD_SUPPORT - /* Define if you have the iconv() function. */ #undef HAVE_ICONV @@ -461,6 +462,9 @@ /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH +/* Define to 1 if you have the `resize_term' function. */ +#undef HAVE_RESIZE_TERM + /* Define to 1 if you have the `sbrk' function. */ #undef HAVE_SBRK @@ -673,6 +677,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + /* Define to 1 if you have the header file. */ #undef HAVE_WAIT_H @@ -694,6 +701,9 @@ /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK +/* Define to 1 if you have the `wresize' function. */ +#undef HAVE_WRESIZE + /* Define to 1 if you have the `XML_StopParser' function. */ #undef HAVE_XML_STOPPARSER diff --git a/contrib/gdb-7/gdb/configure.ac b/contrib/gdb-7/gdb/configure.ac index b69c3b6dfa..f51a567a61 100644 --- a/contrib/gdb-7/gdb/configure.ac +++ b/contrib/gdb-7/gdb/configure.ac @@ -1,6 +1,6 @@ dnl Autoconf configure script for GDB, the GNU debugger. -dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -dnl 2005, 2006, 2007, 2008, 2009, 2010 +dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, +dnl 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 dnl Free Software Foundation, Inc. dnl dnl This file is part of GDB. @@ -108,7 +108,7 @@ AS_HELP_STRING([--with-relocated-sources=PATH], [automatically relocate this pat [Relocated directory for source files. ]) ]) -AC_CONFIG_SUBDIRS(doc testsuite) +AC_CONFIG_SUBDIRS(testsuite) # Check whether to support alternative target configurations AC_ARG_ENABLE(targets, @@ -538,6 +538,7 @@ if test "$with_system_readline" = yes; then READLINE=-lreadline READLINE_DEPS= READLINE_CFLAGS= + READLINE_TEXI_INCFLAG= # readline-6.0 started to use the name `_rl_echoing_p'. # `$(READLINE_DIR)/' of bundled readline would not resolve in configure. @@ -557,10 +558,12 @@ else READLINE='$(READLINE_DIR)/libreadline.a' READLINE_DEPS='$(READLINE)' READLINE_CFLAGS='-I$(READLINE_SRC)/..' + READLINE_TEXI_INCFLAG='-I $(READLINE_DIR)' fi AC_SUBST(READLINE) AC_SUBST(READLINE_DEPS) AC_SUBST(READLINE_CFLAGS) +AC_SUBST(READLINE_TEXI_INCFLAG) AC_ARG_WITH(expat, AS_HELP_STRING([--with-expat], [include expat support (auto/yes/no)]), @@ -607,12 +610,14 @@ AC_DEFUN([AC_TRY_LIBPYTHON], CPPFLAGS="$CPPFLAGS $new_CPPFLAGS" LIBS="$LIBS $new_LIBS" found_usable_python=no - AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]], + AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "Python.h"]], [[Py_Initialize ();]]), [have_libpython_var=${version} - found_usable_python=yes], - [CPPFLAGS=$save_CPPFLAGS - LIBS=$save_LIBS]) + found_usable_python=yes + PYTHON_CPPFLAGS=$new_CPPFLAGS + PYTHON_LIBS=$new_LIBS]) + CPPFLAGS=$save_CPPFLAGS + LIBS=$save_LIBS AC_MSG_RESULT([${found_usable_python}]) ]) @@ -664,6 +669,13 @@ else # Assume the python binary is ${with_python}/bin/python. python_prog="${with_python}/bin/python" python_prefix= + # If python does not exit ${with_python}/bin, then try in + # ${with_python}. On Windows/MinGW, this is where the Python + # executable is. + if test ! -x "${python_prog}"; then + python_prog="${with_python}/python" + python_prefix= + fi if test ! -x "${python_prog}"; then # Fall back to gdb 7.0/7.1 behaviour. python_prog=missing @@ -741,34 +753,39 @@ else fi fi else - # Fall back to gdb 7.0/7.1 behaviour. - if test -z ${python_prefix}; then - python_includes= - python_libs= - else - python_includes="-I${python_prefix}/include" - python_libs="-L${python_prefix}/lib" - fi + # We do not have a python executable we can use to determine where + # to find the Python headers and libs. We cannot guess the include + # path from the python_prefix either, because that include path + # depends on the Python version. So, there is nothing much we can + # do except assume that the compiler will be able to find those files. + python_includes= + python_libs= have_python_config=no fi - # Having "/pythonX.Y" in the include path is awkward. - # All those python headers get bubbled up to the top inviting lots - # of random collisions. GDB originally didn't use python-config to - # find the compilation parameters and includes "pythonX.Y/" in the - # path of the, umm, include file. So strip away this part of the - # output of python-config --includes. - python_includes=`echo "${python_includes} " \ - | sed -e 's,/python[[0-9]]*[[.]][[0-9]]* , ,g'` - # If we have python-config, only try the configuration it provides. # Otherwise fallback on the old way of trying different versions of # python in turn. have_libpython=no if test "${have_python_config}" = yes; then + # Determine the Python version by extracting "-lpython" + # part of the python_libs. is usually X.Y with X and Y + # being decimal numbers, but can also be XY (seen on Windows). + # + # The extraction is performed using sed with a regular expression. + # Initially, the regexp used was using the '?' quantifier to make + # the dot in the version number optional. Unfortunately, this + # does not work with non-GNU versions of sed because, because of + # what looks like a limitation (the '?' quantifier does not work + # with back-references). We work around this limitation by using + # the '*' quantifier instead. It means that, in theory, we might + # match unexpected version strings such as "-lpython2..7", but + # this seems unlikely in practice. And even if that happens, + # an error will be triggered later on, when checking that version + # number. python_version=`echo " ${python_libs} " \ - | sed -e 's,^.* -l\(python[[0-9]]*[[.]][[0-9]]*\) .*$,\1,'` + | sed -e 's,^.* -l\(python[[0-9]]*[[.]]*[[0-9]]*\).*$,\1,'` case "${python_version}" in python*) AC_TRY_LIBPYTHON(${python_version}, have_libpython, @@ -796,13 +813,13 @@ else ${python_includes}, "${python_libs} -lpython2.4") fi fi - if test "${have_libpython}" = python2.7; then + if test "${have_libpython}" = python2.7 -o "${have_libpython}" = python27; then AC_DEFINE(HAVE_LIBPYTHON2_7, 1, [Define if Python 2.7 is being used.]) - elif test "${have_libpython}" = python2.6; then + elif test "${have_libpython}" = python2.6 -o "${have_libpython}" = python26; then AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.]) - elif test "${have_libpython}" = python2.5; then + elif test "${have_libpython}" = python2.5 -o "${have_libpython}" = python25; then AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.]) - elif test "${have_libpython}" = python2.4; then + elif test "${have_libpython}" = python2.4 -o "${have_libpython}" = python24; then AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.]) fi @@ -855,6 +872,21 @@ if test "${have_libpython}" != no; then done AC_MSG_RESULT(${PYTHON_CFLAGS}) fi + + # On IRIX, type siginfo is not defined. Instead, sys/siginfo.h provides: + # #if _SGIAPI + # #define siginfo __siginfo + # #endif + # The problem is that including Python causes some XOPEN macros to be + # unilaterally defined, and that in turn causes _SGIAPI to evaluate + # to false. So, we work around this issue by defining siginfo ourself + # though the command-line. + case "$gdb_host" in + irix*) if test "${GCC}" = yes; then + CPPFLAGS="$CPPFLAGS -Dsiginfo=__siginfo" + fi + ;; + esac else # Even if Python support is not compiled in, we need to have these files # included. @@ -863,6 +895,8 @@ else python/py-prettyprint.c python/py-auto-load.c" fi AC_SUBST(PYTHON_CFLAGS) +AC_SUBST(PYTHON_CPPFLAGS) +AC_SUBST(PYTHON_LIBS) # ------------------------- # # Checks for header files. # @@ -959,10 +993,10 @@ AC_FUNC_ALLOCA AC_FUNC_MMAP AC_FUNC_VFORK AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \ - getgid pipe poll pread64 sbrk setpgid setpgrp setsid \ + getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \ sigaction sigprocmask sigsetmask socketpair syscall \ - ttrace wborder setlocale iconvlist libiconvlist btowc \ - setrlimit getrlimit posix_madvise]) + ttrace wborder wresize setlocale iconvlist libiconvlist btowc \ + setrlimit getrlimit posix_madvise waitpid]) AM_LANGINFO_CODESET # Check the return and argument types of ptrace. No canned test for @@ -1510,22 +1544,6 @@ dnl and not doing a canadian cross build (build == host). if test ${build} = ${host} -a ${host} = ${target} ; then case ${host_os} in - hpux*) - AC_MSG_CHECKING(for HPUX/OSF thread support) - if test -f /usr/include/dce/cma_config.h ; then - if test "$GCC" = "yes" ; then - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_HPUX_THREAD_SUPPORT, 1, - [Define if you have HPUX threads]) - CONFIG_OBS="${CONFIG_OBS} hpux-thread.o" - CONFIG_SRCS="${CONFIG_SRCS} hpux-thread.c" - else - AC_MSG_RESULT(no (suppressed because you are not using GCC)) - fi - else - AC_MSG_RESULT(no) - fi - ;; solaris*) # See if thread_db library is around for Solaris thread debugging. # Note that we must explicitly test for version 1 of the library @@ -1575,6 +1593,11 @@ if test ${build} = ${host} -a ${host} = ${target} ; then CONFIG_SRCS="${CONFIG_SRCS} aix-thread.c" CONFIG_OBS="${CONFIG_OBS} aix-thread.o" CONFIG_LDFLAGS="${CONFIG_LDFLAGS} -lpthdebug" + + # Older versions of AIX do not provide the declaration for + # the getthrds function (it appears that it was introduced + # with AIX 6.x). + AC_CHECK_DECLS(getthrds, [], [], [[#include ]]) fi ;; esac @@ -1833,6 +1856,10 @@ OLD_LIBS=$LIBS CFLAGS="$CFLAGS -I${srcdir}/../include -I../bfd -I${srcdir}/../bfd" LDFLAGS="$LDFLAGS -L../bfd -L../libiberty" intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'` +# -ldl is provided by bfd/Makfile.am (LIBDL) . +if test "$plugins" = "yes"; then + LIBS="-ldl $LIBS" +fi LIBS="-lbfd -liberty $intl $LIBS" AC_CACHE_CHECK([for ELF support in BFD], gdb_cv_var_elf, [AC_TRY_LINK( @@ -1846,6 +1873,10 @@ if test $gdb_cv_var_elf = yes; then CONFIG_OBS="$CONFIG_OBS elfread.o" AC_DEFINE(HAVE_ELF, 1, [Define if ELF support should be included.]) + # -ldl is provided by bfd/Makfile.am (LIBDL) . + if test "$plugins" = "yes"; then + OLD_LIBS="-ldl $OLD_LIBS" + fi fi CFLAGS=$OLD_CFLAGS LDFLAGS=$OLD_LDFLAGS @@ -2080,17 +2111,33 @@ if test "x$enable_multi_ice" = xyes; then AC_CONFIG_SUBDIRS(multi-ice) fi -# We only build gdbserver automatically in a native configuration. -if test "$gdb_native" = "yes"; then +AC_ARG_ENABLE(gdbserver, +AS_HELP_STRING([--enable-gdbserver], + [automatically build gdbserver (yes/no/auto, default is auto)]), +[case "${enableval}" in + yes| no|auto) ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-gdbserver option) ;; +esac],[enable_gdbserver=auto]) + +# We only build gdbserver automatically in a native configuration, and +# only if the user did not explicitly disable its build. +if test "$gdb_native" = "yes" -a "$enable_gdbserver" != "no"; then AC_MSG_CHECKING(whether gdbserver is supported on this host) if test "x$build_gdbserver" = xyes; then AC_MSG_RESULT(yes) AC_CONFIG_SUBDIRS(gdbserver) + gdbserver_build_enabled=yes else AC_MSG_RESULT(no) fi fi +# If the user explicitly request the gdbserver to be built, verify that +# we were in fact able to enable it. +if test "$enable_gdbserver" = "yes" -a "$gdbserver_build_enabled" != "yes"; then + AC_MSG_ERROR(Automatic gdbserver build is not supported for this configuration) +fi + # If nativefile (NAT_FILE) is not set in config/*/*.m[ht] files, we link # to an empty version. @@ -2119,7 +2166,7 @@ dnl At the moment, we just assume it's UTF-8. AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "UTF-8", [Define to be a string naming the default host character set.]) -AC_OUTPUT(Makefile .gdbinit:gdbinit.in gnulib/Makefile, +AC_OUTPUT(Makefile .gdbinit:gdbinit.in doc/Makefile gnulib/Makefile data-directory/Makefile, [ case x$CONFIG_HEADERS in xconfig.h:config.in) diff --git a/contrib/gdb-7/gdb/configure.host b/contrib/gdb-7/gdb/configure.host index 794eeee573..bcebdafdc6 100644 --- a/contrib/gdb-7/gdb/configure.host +++ b/contrib/gdb-7/gdb/configure.host @@ -105,6 +105,7 @@ i[34567]86-*-solaris2.1[0-9]* | x86_64-*-solaris2.1[0-9]*) i[34567]86-*-solaris*) gdb_host=i386sol2 ;; i[34567]86-*-cygwin*) gdb_host=cygwin ;; +ia64-*-hpux*) gdb_host=hpux ;; ia64-*-linux*) gdb_host=linux ;; m68*-*-linux*) gdb_host=linux ;; @@ -202,6 +203,11 @@ m68*-*-*) gdb_host_double_format="&floatformat_ieee_double_big" gdb_host_long_double_format="&floatformat_m68881_ext" ;; +ia64-*-hpux*) + gdb_host_float_format="&floatformat_ieee_single_big" + gdb_host_double_format="&floatformat_ieee_double_big" + gdb_host_long_double_format="&floatformat_ia64_quad_big" + ;; *) gdb_host_float_format=0 gdb_host_double_format=0 diff --git a/contrib/gdb-7/gdb/configure.tgt b/contrib/gdb-7/gdb/configure.tgt index 97a532f9fe..5ab1554df7 100644 --- a/contrib/gdb-7/gdb/configure.tgt +++ b/contrib/gdb-7/gdb/configure.tgt @@ -39,7 +39,7 @@ alpha*-*-osf*) alpha*-*-linux*) # Target: Little-endian Alpha running Linux gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \ - solib.o solib-svr4.o" + linux-tdep.o solib.o solib-svr4.o" ;; alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu) # Target: FreeBSD/alpha @@ -65,8 +65,8 @@ alpha*-*-*) am33_2.0*-*-linux*) # Target: Matsushita mn10300 (AM33) running Linux - gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o corelow.o \ - solib.o solib-svr4.o" + gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o linux-tdep.o \ + corelow.o solib.o solib-svr4.o" ;; arm*-wince-pe | arm*-*-mingw32ce*) @@ -106,6 +106,18 @@ avr-*-*) gdb_sim=../sim/avr/libsim.a ;; +bfin-*-*linux*) + # Target: Blackfin Linux + gdb_target_obs="bfin-tdep.o bfin-linux-tdep.o linux-tdep.o" + gdb_sim=../sim/bfin/libsim.a + build_gdbserver=yes + ;; +bfin-*-*) + # Target: Blackfin processor + gdb_target_obs="bfin-tdep.o" + gdb_sim=../sim/bfin/libsim.a + ;; + cris*) # Target: CRIS gdb_target_obs="cris-tdep.o corelow.o solib.o solib-svr4.o" @@ -113,7 +125,7 @@ cris*) frv-*-*) # Target: Fujitsu FRV processor - gdb_target_obs="frv-tdep.o frv-linux-tdep.o \ + gdb_target_obs="frv-tdep.o frv-linux-tdep.o linux-tdep.o \ solib.o solib-frv.o corelow.o" gdb_sim=../sim/frv/libsim.a ;; @@ -137,7 +149,7 @@ hppa*-*-hpux*) hppa*-*-linux*) # Target: HP PA-RISC running Linux gdb_target_obs="hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o \ - solib.o solib-svr4.o symfile-mem.o" + linux-tdep.o solib.o solib-svr4.o symfile-mem.o" ;; hppa*-*-netbsd*) # Target: NetBSD/hppa @@ -234,9 +246,13 @@ i[34567]86-*-*) gdb_target_obs="i386-tdep.o i387-tdep.o" ;; +ia64-*-hpux*) + # Target: Intel IA-64 running HP-UX + gdb_target_obs="ia64-tdep.o ia64-hpux-tdep.o" + ;; ia64-*-linux*) # Target: Intel IA-64 running GNU/Linux - gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o \ + gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o linux-tdep.o \ solib.o solib-svr4.o symfile-mem.o" build_gdbserver=yes ;; @@ -266,7 +282,8 @@ m32c-*-*) m32r*-*-linux*) # Target: Renesas M32R running GNU/Linux gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o \ - glibc-tdep.o solib.o solib-svr4.o symfile-mem.o" + glibc-tdep.o solib.o solib-svr4.o symfile-mem.o \ + linux-tdep.o" gdb_sim=../sim/m32r/libsim.a build_gdbserver=yes ;; @@ -291,7 +308,7 @@ fido-*-elf*) m68*-*-linux*) # Target: Motorola m68k with a.out and ELF gdb_target_obs="m68k-tdep.o m68klinux-tdep.o solib.o solib-svr4.o \ - glibc-tdep.o symfile-mem.o" + linux-tdep.o glibc-tdep.o symfile-mem.o" build_gdbserver=yes ;; m68*-*-netbsd* | m68*-*-knetbsd*-gnu) @@ -316,14 +333,14 @@ mep-*-*) # No sim needed. Target uses SID. ;; -microblaze*-linux-*) +microblaze*-linux-*|microblaze*-*-linux*) # Target: Xilinx MicroBlaze running Linux gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o \ monitor.o dsrec.o solib.o solib-svr4.o corelow.o \ - symfile-mem.o" + symfile-mem.o linux-tdep.o" gdb_sim=../sim/microblaze/libsim.a ;; -microblaze*-xilinx-*) +microblaze*-*-*) # Target: Xilinx MicroBlaze running standalone gdb_target_obs="microblaze-tdep.o microblaze-rom.o monitor.o dsrec.o" gdb_sim=../sim/microblaze/libsim.a @@ -340,7 +357,8 @@ mips*-sgi-irix6*) mips*-*-linux*) # Target: Linux/MIPS gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \ - corelow.o solib.o solib-svr4.o symfile-mem.o" + corelow.o solib.o solib-svr4.o symfile-mem.o \ + linux-tdep.o" gdb_sim=../sim/mips/libsim.a build_gdbserver=yes ;; @@ -355,6 +373,11 @@ mips64*-*-openbsd*) gdb_target_obs="mips-tdep.o mips64obsd-tdep.o \ corelow.o solib.o solib-svr4.o" ;; +mips*-*-elf) + # Target: MIPS ELF + gdb_target_obs="mips-tdep.o remote-mips.o" + gdb_sim=../sim/mips/libsim.a + ;; mips*-*-*) # Target: MIPS gdb_target_obs="mips-tdep.o" @@ -430,7 +453,7 @@ sh*-*-linux*) # Target: GNU/Linux Super-H gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \ dsrec.o solib.o solib-svr4.o symfile-mem.o \ - glibc-tdep.o corelow.o" + glibc-tdep.o corelow.o linux-tdep.o" gdb_sim=../sim/sh/libsim.a build_gdbserver=yes ;; @@ -458,7 +481,8 @@ sh*) sparc-*-linux*) # Target: GNU/Linux SPARC gdb_target_obs="sparc-tdep.o sparc-sol2-tdep.o sol2-tdep.o \ - sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o" + sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o \ + linux-tdep.o" if test "x$enable_64_bit_bfd" = "xyes"; then # Target: GNU/Linux UltraSPARC gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o \ @@ -469,7 +493,7 @@ sparc64-*-linux*) # Target: GNU/Linux UltraSPARC gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \ sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \ - sparc-linux-tdep.o solib.o solib-svr4.o" + sparc-linux-tdep.o solib.o solib-svr4.o linux-tdep.o" build_gdbserver=yes ;; sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu) @@ -511,14 +535,11 @@ sparc-*-solaris2* | sparcv9-*-solaris2* | sparc64-*-solaris2*) gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sparc-tdep.o \ sparc-sol2-tdep.o sol2-tdep.o solib.o solib-svr4.o" ;; -sparc-*-rtems*) - # Target: SPARC embedded with simulator - gdb_target_obs="sparc-tdep.o" - gdb_sim=../sim/erc32/libsim.a - ;; sparc-*-*) # Target: SPARC - gdb_target_obs="sparc-tdep.o" + gdb_target_obs="sparc-tdep.o ravenscar-thread.o \ + ravenscar-sparc-thread.o" + gdb_sim=../sim/erc32/libsim.a ;; sparc64-*-*) # Target: UltraSPARC @@ -605,7 +626,8 @@ x86_64-*-openbsd*) xtensa*-*-linux*) gdb_target=linux # Target: GNU/Linux Xtensa gdb_target_obs="xtensa-tdep.o xtensa-config.o xtensa-linux-tdep.o \ - solib.o solib-svr4.o corelow.o symfile-mem.o" + solib.o solib-svr4.o corelow.o symfile-mem.o \ + linux-tdep.o" build_gdbserver=yes ;; xtensa*) @@ -618,8 +640,10 @@ esac # map target onto default OS ABI case "${targ}" in -*-*-freebsd*) gdb_osabi=GDB_OSABI_FREEBSD_ELF ;; -*-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;; +*-*-freebsd* | *-*-kfreebsd*-gnu) + gdb_osabi=GDB_OSABI_FREEBSD_ELF ;; +*-*-linux* | *-*-uclinux*) + gdb_osabi=GDB_OSABI_LINUX ;; *-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;; m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;; *-*-openbsd*) gdb_osabi=GDB_OSABI_OPENBSD_ELF ;; diff --git a/contrib/gdb-7/gdb/copying.c b/contrib/gdb-7/gdb/copying.c index 6be9b8fb5b..d608a63669 100644 --- a/contrib/gdb-7/gdb/copying.c +++ b/contrib/gdb-7/gdb/copying.c @@ -649,10 +649,10 @@ show_warranty_command (char *ignore, int from_tty) void _initialize_copying (void) { - add_cmd ("copying", no_class, show_copying_command, + add_cmd ("copying", no_set_class, show_copying_command, _("Conditions for redistributing copies of GDB."), &showlist); - add_cmd ("warranty", no_class, show_warranty_command, + add_cmd ("warranty", no_set_class, show_warranty_command, _("Various kinds of warranty you do not have."), &showlist); diff --git a/contrib/gdb-7/gdb/copyright.py b/contrib/gdb-7/gdb/copyright.py new file mode 100644 index 0000000000..71f261d68f --- /dev/null +++ b/contrib/gdb-7/gdb/copyright.py @@ -0,0 +1,608 @@ +#! /usr/bin/env python + +"""copyright.py + +This script updates most of the files that are not already handled +by copyright.sh. It must be run from the gdb/ subdirectory of the +GDB source tree. + +""" + +import datetime +import re +import os +import os.path + +class Comment(object): + """A class describing comment. + + ATTRIBUTES + start: A string describing how comments are started. + stop: A string describing how comments end. If None, then + a comment ends at the end of the line. + start2: Some files accept more than 1 kind of comment. + For those that do, this is the alternative form. + For now, it is assumed that if start2 is not None, + then stop is None (thus no stop2 attribute). + """ + def __init__(self, start, stop=None, start2=None, max_lines=30): + """The "Copyright" keyword should be within MAX_LINES lines + from the start of the file.""" + self.start = start + self.stop = stop + self.start2 = start2 + self.max_lines = max_lines + +# The Comment object for Ada code (and GPR files). +ADA_COMMENT = Comment(start="--") + +THIS_YEAR = str(datetime.date.today().year) + +# Files which should not be modified, either because they are +# generated, non-FSF, or otherwise special (e.g. license text, +# or test cases which must be sensitive to line numbering). +EXCLUSION_LIST = ( + "COPYING", "COPYING.LIB", "CVS", "configure", "copying.c", "gdbarch.c", + "gdbarch.h", "fdl.texi", "gpl.texi", "gdbtk", "gdb.gdbtk", "osf-share", + "aclocal.m4", "step-line.inp", "step-line.c", + ) + +# Files that are too different from the rest to be processed automatically. +BY_HAND = ['../sim/ppc/psim.texinfo'] + +# Files for which we know that they do not have a copyright header. +# Ideally, this list should be empty (but it may not be possible to +# add a copyright header in some of them). +NO_COPYRIGHT = ( + # Configure files. We should fix those, one day. + "testsuite/gdb.cell/configure.ac", "testsuite/gdb.hp/configure.ac", + "testsuite/gdb.hp/gdb.aCC/configure.ac", + "testsuite/gdb.hp/gdb.base-hp/configure.ac", + "testsuite/gdb.hp/gdb.compat/configure.ac", + "testsuite/gdb.hp/gdb.defects/configure.ac", + "testsuite/gdb.hp/gdb.objdbg/configure.ac", + "testsuite/gdb.stabs/configure.ac", + "../sim/arm/configure.ac", "../sim/avr/configure.ac", + "../sim/common/configure.ac", "../sim/configure.ac", + "../sim/cr16/configure.ac", "../sim/cris/configure.ac", + "../sim/d10v/configure.ac", "../sim/erc32/configure.ac", + "../sim/frv/configure.ac", "../sim/h8300/configure.ac", + "../sim/igen/configure.ac", "../sim/iq2000/configure.ac", + "../sim/lm32/configure.ac", "../sim/m32r/configure.ac", + "../sim/m68hc11/configure.ac", "../sim/mcore/configure.ac", + "../sim/microblaze/configure.ac", "../sim/mips/configure.ac", + "../sim/mn10300/configure.ac", "../sim/moxie/configure.ac", + "../sim/ppc/configure.ac", "../sim/sh/configure.ac", + "../sim/sh64/configure.ac", "../sim/testsuite/configure.ac", + "../sim/testsuite/d10v-elf/configure.ac", + "../sim/testsuite/frv-elf/configure.ac", + "../sim/testsuite/m32r-elf/configure.ac", + "../sim/testsuite/mips64el-elf/configure.ac", "../sim/v850/configure.ac", + # Assembly files. It's not certain that we can add a copyright + # header in a way that works for all platforms supported by the + # testcase... + "testsuite/gdb.arch/pa-nullify.s", "testsuite/gdb.arch/pa64-nullify.s", + "testsuite/gdb.asm/asmsrc1.s", "testsuite/gdb.asm/asmsrc2.s", + "testsuite/gdb.disasm/am33.s", "testsuite/gdb.disasm/h8300s.s", + "testsuite/gdb.disasm/hppa.s", "testsuite/gdb.disasm/mn10200.s", + "testsuite/gdb.disasm/mn10300.s", "testsuite/gdb.disasm/sh3.s", + "testsuite/gdb.disasm/t01_mov.s", "testsuite/gdb.disasm/t02_mova.s", + "testsuite/gdb.disasm/t03_add.s", "testsuite/gdb.disasm/t04_sub.s", + "testsuite/gdb.disasm/t05_cmp.s", "testsuite/gdb.disasm/t06_ari2.s", + "testsuite/gdb.disasm/t07_ari3.s", "testsuite/gdb.disasm/t08_or.s", + "testsuite/gdb.disasm/t09_xor.s", "testsuite/gdb.disasm/t10_and.s", + "testsuite/gdb.disasm/t11_logs.s", "testsuite/gdb.disasm/t12_bit.s", + "testsuite/gdb.disasm/t13_otr.s", "testsuite/gdb.hp/gdb.base-hp/reg-pa64.s", + "testsuite/gdb.hp/gdb.base-hp/reg.s", + "../sim/testsuite/d10v-elf/exit47.s", + "../sim/testsuite/d10v-elf/hello.s", + "../sim/testsuite/d10v-elf/loop.s", + "../sim/testsuite/d10v-elf/t-ae-ld-d.s", + "../sim/testsuite/d10v-elf/t-ae-ld-i.s", + "../sim/testsuite/d10v-elf/t-ae-ld-id.s", + "../sim/testsuite/d10v-elf/t-ae-ld-im.s", + "../sim/testsuite/d10v-elf/t-ae-ld-ip.s", + "../sim/testsuite/d10v-elf/t-ae-ld2w-d.s", + "../sim/testsuite/d10v-elf/t-ae-ld2w-i.s", + "../sim/testsuite/d10v-elf/t-ae-ld2w-id.s", + "../sim/testsuite/d10v-elf/t-ae-ld2w-im.s", + "../sim/testsuite/d10v-elf/t-ae-ld2w-ip.s", + "../sim/testsuite/d10v-elf/t-ae-st-d.s", + "../sim/testsuite/d10v-elf/t-ae-st-i.s", + "../sim/testsuite/d10v-elf/t-ae-st-id.s", + "../sim/testsuite/d10v-elf/t-ae-st-im.s", + "../sim/testsuite/d10v-elf/t-ae-st-ip.s", + "../sim/testsuite/d10v-elf/t-ae-st-is.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-d.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-i.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-id.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-im.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-ip.s", + "../sim/testsuite/d10v-elf/t-ae-st2w-is.s", + "../sim/testsuite/d10v-elf/t-dbt.s", + "../sim/testsuite/d10v-elf/t-ld-st.s", + "../sim/testsuite/d10v-elf/t-mac.s", + "../sim/testsuite/d10v-elf/t-mod-ld-pre.s", + "../sim/testsuite/d10v-elf/t-msbu.s", + "../sim/testsuite/d10v-elf/t-mulxu.s", + "../sim/testsuite/d10v-elf/t-mvtac.s", + "../sim/testsuite/d10v-elf/t-mvtc.s", + "../sim/testsuite/d10v-elf/t-rac.s", + "../sim/testsuite/d10v-elf/t-rachi.s", + "../sim/testsuite/d10v-elf/t-rdt.s", + "../sim/testsuite/d10v-elf/t-rep.s", + "../sim/testsuite/d10v-elf/t-rie-xx.s", + "../sim/testsuite/d10v-elf/t-rte.s", + "../sim/testsuite/d10v-elf/t-sac.s", + "../sim/testsuite/d10v-elf/t-sachi.s", + "../sim/testsuite/d10v-elf/t-sadd.s", + "../sim/testsuite/d10v-elf/t-slae.s", + "../sim/testsuite/d10v-elf/t-sp.s", + "../sim/testsuite/d10v-elf/t-sub.s", + "../sim/testsuite/d10v-elf/t-sub2w.s", + "../sim/testsuite/d10v-elf/t-subi.s", + "../sim/testsuite/d10v-elf/t-trap.s", + "../sim/testsuite/frv-elf/cache.s", + "../sim/testsuite/frv-elf/exit47.s", + "../sim/testsuite/frv-elf/grloop.s", + "../sim/testsuite/frv-elf/hello.s", + "../sim/testsuite/frv-elf/loop.s", + "../sim/testsuite/m32r-elf/exit47.s", + "../sim/testsuite/m32r-elf/hello.s", + "../sim/testsuite/m32r-elf/loop.s", + "../sim/testsuite/sim/cris/hw/rv-n-cris/quit.s", + "../sim/testsuite/sim/h8300/addb.s", + "../sim/testsuite/sim/h8300/addl.s", + "../sim/testsuite/sim/h8300/adds.s", + "../sim/testsuite/sim/h8300/addw.s", + "../sim/testsuite/sim/h8300/addx.s", + "../sim/testsuite/sim/h8300/andb.s", + "../sim/testsuite/sim/h8300/andl.s", + "../sim/testsuite/sim/h8300/andw.s", + "../sim/testsuite/sim/h8300/band.s", + "../sim/testsuite/sim/h8300/bfld.s", + "../sim/testsuite/sim/h8300/biand.s", + "../sim/testsuite/sim/h8300/bra.s", + "../sim/testsuite/sim/h8300/brabc.s", + "../sim/testsuite/sim/h8300/bset.s", + "../sim/testsuite/sim/h8300/cmpb.s", + "../sim/testsuite/sim/h8300/cmpl.s", + "../sim/testsuite/sim/h8300/cmpw.s", + "../sim/testsuite/sim/h8300/daa.s", + "../sim/testsuite/sim/h8300/das.s", + "../sim/testsuite/sim/h8300/dec.s", + "../sim/testsuite/sim/h8300/div.s", + "../sim/testsuite/sim/h8300/extl.s", + "../sim/testsuite/sim/h8300/extw.s", + "../sim/testsuite/sim/h8300/inc.s", + "../sim/testsuite/sim/h8300/jmp.s", + "../sim/testsuite/sim/h8300/ldc.s", + "../sim/testsuite/sim/h8300/ldm.s", + "../sim/testsuite/sim/h8300/mac.s", + "../sim/testsuite/sim/h8300/mova.s", + "../sim/testsuite/sim/h8300/movb.s", + "../sim/testsuite/sim/h8300/movl.s", + "../sim/testsuite/sim/h8300/movmd.s", + "../sim/testsuite/sim/h8300/movsd.s", + "../sim/testsuite/sim/h8300/movw.s", + "../sim/testsuite/sim/h8300/mul.s", + "../sim/testsuite/sim/h8300/neg.s", + "../sim/testsuite/sim/h8300/nop.s", + "../sim/testsuite/sim/h8300/not.s", + "../sim/testsuite/sim/h8300/orb.s", + "../sim/testsuite/sim/h8300/orl.s", + "../sim/testsuite/sim/h8300/orw.s", + "../sim/testsuite/sim/h8300/rotl.s", + "../sim/testsuite/sim/h8300/rotr.s", + "../sim/testsuite/sim/h8300/rotxl.s", + "../sim/testsuite/sim/h8300/rotxr.s", + "../sim/testsuite/sim/h8300/shal.s", + "../sim/testsuite/sim/h8300/shar.s", + "../sim/testsuite/sim/h8300/shll.s", + "../sim/testsuite/sim/h8300/shlr.s", + "../sim/testsuite/sim/h8300/stack.s", + "../sim/testsuite/sim/h8300/stc.s", + "../sim/testsuite/sim/h8300/subb.s", + "../sim/testsuite/sim/h8300/subl.s", + "../sim/testsuite/sim/h8300/subs.s", + "../sim/testsuite/sim/h8300/subw.s", + "../sim/testsuite/sim/h8300/subx.s", + "../sim/testsuite/sim/h8300/tas.s", + "../sim/testsuite/sim/h8300/xorb.s", + "../sim/testsuite/sim/h8300/xorl.s", + "../sim/testsuite/sim/h8300/xorw.s", + "../sim/testsuite/sim/mips/fpu64-ps-sb1.s", + "../sim/testsuite/sim/mips/fpu64-ps.s", + "../sim/testsuite/sim/mips/hilo-hazard-1.s", + "../sim/testsuite/sim/mips/hilo-hazard-2.s", + "../sim/testsuite/sim/mips/hilo-hazard-3.s", + "../sim/testsuite/sim/mips/mdmx-ob-sb1.s", + "../sim/testsuite/sim/mips/mdmx-ob.s", + "../sim/testsuite/sim/mips/mips32-dsp.s", + "../sim/testsuite/sim/mips/mips32-dsp2.s", + "../sim/testsuite/sim/mips/sanity.s", + "../sim/testsuite/sim/sh/add.s", + "../sim/testsuite/sim/sh/and.s", + "../sim/testsuite/sim/sh/bandor.s", + "../sim/testsuite/sim/sh/bandornot.s", + "../sim/testsuite/sim/sh/bclr.s", + "../sim/testsuite/sim/sh/bld.s", + "../sim/testsuite/sim/sh/bldnot.s", + "../sim/testsuite/sim/sh/bset.s", + "../sim/testsuite/sim/sh/bst.s", + "../sim/testsuite/sim/sh/bxor.s", + "../sim/testsuite/sim/sh/clip.s", + "../sim/testsuite/sim/sh/div.s", + "../sim/testsuite/sim/sh/dmxy.s", + "../sim/testsuite/sim/sh/fabs.s", + "../sim/testsuite/sim/sh/fadd.s", + "../sim/testsuite/sim/sh/fail.s", + "../sim/testsuite/sim/sh/fcmpeq.s", + "../sim/testsuite/sim/sh/fcmpgt.s", + "../sim/testsuite/sim/sh/fcnvds.s", + "../sim/testsuite/sim/sh/fcnvsd.s", + "../sim/testsuite/sim/sh/fdiv.s", + "../sim/testsuite/sim/sh/fipr.s", + "../sim/testsuite/sim/sh/fldi0.s", + "../sim/testsuite/sim/sh/fldi1.s", + "../sim/testsuite/sim/sh/flds.s", + "../sim/testsuite/sim/sh/float.s", + "../sim/testsuite/sim/sh/fmac.s", + "../sim/testsuite/sim/sh/fmov.s", + "../sim/testsuite/sim/sh/fmul.s", + "../sim/testsuite/sim/sh/fneg.s", + "../sim/testsuite/sim/sh/fpchg.s", + "../sim/testsuite/sim/sh/frchg.s", + "../sim/testsuite/sim/sh/fsca.s", + "../sim/testsuite/sim/sh/fschg.s", + "../sim/testsuite/sim/sh/fsqrt.s", + "../sim/testsuite/sim/sh/fsrra.s", + "../sim/testsuite/sim/sh/fsub.s", + "../sim/testsuite/sim/sh/ftrc.s", + "../sim/testsuite/sim/sh/ldrc.s", + "../sim/testsuite/sim/sh/loop.s", + "../sim/testsuite/sim/sh/macl.s", + "../sim/testsuite/sim/sh/macw.s", + "../sim/testsuite/sim/sh/mov.s", + "../sim/testsuite/sim/sh/movi.s", + "../sim/testsuite/sim/sh/movli.s", + "../sim/testsuite/sim/sh/movua.s", + "../sim/testsuite/sim/sh/movxy.s", + "../sim/testsuite/sim/sh/mulr.s", + "../sim/testsuite/sim/sh/pabs.s", + "../sim/testsuite/sim/sh/padd.s", + "../sim/testsuite/sim/sh/paddc.s", + "../sim/testsuite/sim/sh/pand.s", + "../sim/testsuite/sim/sh/pass.s", + "../sim/testsuite/sim/sh/pclr.s", + "../sim/testsuite/sim/sh/pdec.s", + "../sim/testsuite/sim/sh/pdmsb.s", + "../sim/testsuite/sim/sh/pinc.s", + "../sim/testsuite/sim/sh/pmuls.s", + "../sim/testsuite/sim/sh/prnd.s", + "../sim/testsuite/sim/sh/pshai.s", + "../sim/testsuite/sim/sh/pshar.s", + "../sim/testsuite/sim/sh/pshli.s", + "../sim/testsuite/sim/sh/pshlr.s", + "../sim/testsuite/sim/sh/psub.s", + "../sim/testsuite/sim/sh/pswap.s", + "../sim/testsuite/sim/sh/pushpop.s", + "../sim/testsuite/sim/sh/resbank.s", + "../sim/testsuite/sim/sh/sett.s", + "../sim/testsuite/sim/sh/shll.s", + "../sim/testsuite/sim/sh/shll16.s", + "../sim/testsuite/sim/sh/shll2.s", + "../sim/testsuite/sim/sh/shll8.s", + "../sim/testsuite/sim/sh/shlr.s", + "../sim/testsuite/sim/sh/shlr16.s", + "../sim/testsuite/sim/sh/shlr2.s", + "../sim/testsuite/sim/sh/shlr8.s", + "../sim/testsuite/sim/sh/swap.s", + "../sim/testsuite/sim/sh64/misc/fr-dr.s", + # .inc files. These are usually assembly or C files... + "testsuite/gdb.asm/alpha.inc", + "testsuite/gdb.asm/arm.inc", + "testsuite/gdb.asm/common.inc", + "testsuite/gdb.asm/empty.inc", + "testsuite/gdb.asm/frv.inc", + "testsuite/gdb.asm/h8300.inc", + "testsuite/gdb.asm/i386.inc", + "testsuite/gdb.asm/ia64.inc", + "testsuite/gdb.asm/iq2000.inc", + "testsuite/gdb.asm/m32c.inc", + "testsuite/gdb.asm/m32r-linux.inc", + "testsuite/gdb.asm/m32r.inc", + "testsuite/gdb.asm/m68hc11.inc", + "testsuite/gdb.asm/m68k.inc", + "testsuite/gdb.asm/mips.inc", + "testsuite/gdb.asm/netbsd.inc", + "testsuite/gdb.asm/openbsd.inc", + "testsuite/gdb.asm/pa.inc", + "testsuite/gdb.asm/pa64.inc", + "testsuite/gdb.asm/powerpc.inc", + "testsuite/gdb.asm/powerpc64.inc", + "testsuite/gdb.asm/s390.inc", + "testsuite/gdb.asm/s390x.inc", + "testsuite/gdb.asm/sh.inc", + "testsuite/gdb.asm/sparc.inc", + "testsuite/gdb.asm/sparc64.inc", + "testsuite/gdb.asm/spu.inc", + "testsuite/gdb.asm/v850.inc", + "testsuite/gdb.asm/x86_64.inc", + "testsuite/gdb.asm/xstormy16.inc", + "../sim/testsuite/sim/arm/iwmmxt/testutils.inc", + "../sim/testsuite/sim/arm/testutils.inc", + "../sim/testsuite/sim/arm/thumb/testutils.inc", + "../sim/testsuite/sim/arm/xscale/testutils.inc", + "../sim/testsuite/sim/cr16/testutils.inc", + "../sim/testsuite/sim/cris/asm/testutils.inc", + "../sim/testsuite/sim/cris/hw/rv-n-cris/testutils.inc", + "../sim/testsuite/sim/fr30/testutils.inc", + "../sim/testsuite/sim/frv/testutils.inc", + "../sim/testsuite/sim/h8300/testutils.inc", + "../sim/testsuite/sim/m32r/testutils.inc", + "../sim/testsuite/sim/sh/testutils.inc", + "../sim/testsuite/sim/sh64/compact/testutils.inc", + "../sim/testsuite/sim/sh64/media/testutils.inc", + "../sim/testsuite/sim/v850/testutils.inc", + ) + +# A mapping between file extensions to their associated Comment object. +# This dictionary also contains a number of exceptions, based on +# filename. +COMMENT_MAP = \ + {".1" : Comment(start=r'.\"'), + ".ac" : Comment(start="dnl", start2="#"), + ".ads" : ADA_COMMENT, + ".adb" : ADA_COMMENT, + ".f" : Comment(start="c"), + ".f90" : Comment(start="!"), + ".gpr" : ADA_COMMENT, + ".inc" : Comment(start="#", start2=";"), + ".s" : Comment(start="!"), + ".tex" : Comment(start="%"), + ".texi" : Comment(start="@c"), + ".texinfo" : Comment(start="@c"), + + # Files that use a different way of including the copyright + # header... + "ada-operator.inc" : Comment(start="/*", stop="*/"), + "gdbint.texinfo" : Comment(start='@copying', stop="@end copying"), + "annotate.texinfo" : Comment(start='@copying', stop="@end copying", + max_lines=50), + "stabs.texinfo" : Comment(start='@copying', stop="@end copying"), + } + +class NotFound(Exception): + pass + +class AlreadyDone(Exception): + pass + +def process_header(src, dst, cdescr): + """Read from SRC for up to CDESCR.MAX_LINES until we find a copyright + notice. If found, then write the entire file, with the copyright + noticed updated with the current year added. + + Raises NotFound if the copyright notice could not be found or has + some inconsistencies. + + Raises AlreadyDone if the copyright notice already includes the current + year. + """ + line_count = 0 + # The start-of-comment marker used for this file. Only really useful + # in the case where comments ends at the end of the line, as this + # allows us to know which comment marker to use when breaking long + # lines (in the cases where there are more than one. + cdescr_start = "" + + while True: + # If we still haven't found a copyright line within a certain + # number of lines, then give up. + if line_count > cdescr.max_lines: + raise NotFound("start of Copyright not found") + + line = src.readline() + line_count += 1 + if not line: + raise NotFound("start of Copyright not found (EOF)") + + # Is this a copyright line? If not, then no transformation is + # needed. Write it as is, and continue. + if not re.search(r"Copyright\b.*\b(199\d|20\d\d)\b", line): + dst.write(line) + continue + + # If a start-of-comment marker is needed for every line, try to + # figure out which one it is that is being used in this file (most + # files only accept one, in which case it's easy - but some accept + # two or more...). + if cdescr.stop is None: + stripped_line = line.lstrip() + if stripped_line.startswith(cdescr.start): + cdescr_start = cdescr.start + elif (cdescr.start2 is not None + and stripped_line.startswith(cdescr.start2)): + cdescr_start = cdescr.start2 + elif cdescr.start in stripped_line: + cdescr_start = cdescr.start + elif (cdescr.start2 is not None + and cdescr.start2 in stripped_line): + cdescr_start = cdescr.start2 + else: + # This can't be a line with a comment, so not the copyright + # line we were looking for. Ignore. + continue + + comment = line + break + + while not re.search(r"Free\s+Software\s+Foundation", comment): + line = src.readline() + line_count += 1 + if not line: + raise NotFound("Copyright owner not found (EOF)") + + if cdescr.stop is None: + # Expect a new comment marker at the start of each line + line = line.lstrip() + if not line.startswith(cdescr_start): + raise NotFound("Copyright owner not found " + "(end of comment)") + comment += " " + line[len(cdescr_start):] + else: + if cdescr.stop in comment: + raise NotFound("Copyright owner not found " + "(end of comment)") + comment += line + + # Normalize a bit the copyright string (we preserve the string + # up until "Copyright", in order to help preserve any original + # alignment. + (before, after) = comment.split("Copyright", 1) + after = after.replace("\n", " ") + after = re.sub("\s+", " ", after) + after = after.rstrip() + + # If the copyright year has already been added, the nothing else + # to do. + if THIS_YEAR in after: + raise AlreadyDone + + m = re.match("(.*[0-9]+)(.*)", after) + if m is None: + raise NotFound("Internal error - cannot split copyright line: " + "`%s'" % comment) + + # Reconstruct the comment line + comment = before + "Copyright" + m.group(1) + ', %s' % THIS_YEAR + owner_part = m.group(2).lstrip() + + # Max comment len... + max_len = 76 + + # If we have to break the copyright line into multiple lines, + # we want to align all the lines on the "Copyright" keyword. + # Create a small "indent" string that we can use for that. + if cdescr.stop is None: + # The comment marker is needed on every line, so put it at the + # start of our "indent" string. + indent = cdescr_start + ' ' * (len(before) - len(cdescr_start)) + else: + indent = ' ' * len(before) + + # If the line is too long... + while len(comment) > max_len: + # Split the line at the first space before max_len. + space_index = comment[0:max_len].rfind(' ') + if space_index < 0: # No space in the first max_len characters??? + # Split at the first space, then... + space_index = comment.find(' ') + if space_index < 0: + # Still no space found. This is extremely unlikely, but + # just pretend there is one at the end of the string. + space_index = len(comment) + + # Write the first part of the string up until the space + # we selected to break our line. + dst.write(comment[:space_index] + '\n') + + # Strip the part of comment that we have finished printing. + if space_index < len(comment): + comment = comment[space_index + 1:] + else: + comment = "" + + # Prepend the "indent" string to make sure that we remain + # aligned on the "Copyright" word. + comment = indent + comment + + # And finally, write the rest of the last line... We want to write + # "Free Software Foundation, Inc" on the same line, so handle this + # with extra care. + dst.write(comment) + if len(comment) + 1 + len (owner_part) > max_len: + dst.write('\n' + indent) + else: + dst.write(' ') + dst.write(owner_part + '\n') + +def comment_for_filename(filename): + """Return the Comment object that best describes the given file. + This a smart lookup of the COMMENT_MAP dictionary where we check + for filename-based exceptions first, before looking up the comment + by filename extension. """ + # First, consult the COMMENT_MAP using the filename, in case this + # file needs special treatment. + basename = os.path.basename(filename) + if basename in COMMENT_MAP: + return COMMENT_MAP[basename] + # Not a special file. Check the file extension. + ext = os.path.splitext(filename)[1] + if ext in COMMENT_MAP: + return COMMENT_MAP[ext] + # Not a know extension either, return None. + return None + +def process_file(filename): + """Processes the given file. + """ + cdescr = comment_for_filename(filename) + if cdescr is None: + # Either no filename extension, or not an extension that we + # know how to handle. + return + + dst_filename = filename + '.new' + src = open(filename) + dst = open(dst_filename, 'w') + try: + process_header(src, dst, cdescr) + except AlreadyDone: + print "+++ Already up to date: `%s'." % filename + dst.close() + os.unlink(dst_filename) + if filename in NO_COPYRIGHT: + # We expect the search for a copyright header to fail, and + # yet we found one... + print "Warning: `%s' should not be in NO_COPYRIGHT" % filename + return + except NotFound as inst: + dst.close() + os.unlink(dst_filename) + if not filename in NO_COPYRIGHT: + print "*** \033[31m%s\033[0m: %s" % (filename, inst) + return + + if filename in NO_COPYRIGHT: + # We expect the search for a copyright header to fail, and + # yet we found one... + print "Warning: `%s' should not be in NO_COPYRIGHT" % filename + + for line in src: + dst.write(line) + src.close() + dst.close() + os.rename(dst_filename, filename) + +if __name__ == "__main__": + if not os.path.isfile("doc/gdb.texinfo"): + print "Error: This script must be called from the gdb directory." + for gdb_dir in ('.', '../sim', '../include/gdb'): + for root, dirs, files in os.walk(gdb_dir): + for filename in files: + fullpath = os.path.join(root, filename) + if fullpath.startswith('./'): + fullpath = fullpath[2:] + if filename not in EXCLUSION_LIST and fullpath not in BY_HAND: + # Paths that start with './' are ugly, so strip that. + # This also allows us to omit them in the NO_COPYRIGHT + # list... + process_file(fullpath) + print + print "\033[32mREMINDER: The following files must be updated by hand." \ + "\033[0m" + for filename in BY_HAND: + print " ", filename + diff --git a/contrib/gdb-7/gdb/corefile.c b/contrib/gdb-7/gdb/corefile.c index 7c1db864f7..ce3b755680 100644 --- a/contrib/gdb-7/gdb/corefile.c +++ b/contrib/gdb-7/gdb/corefile.c @@ -1,7 +1,7 @@ /* Core dump and executable file functions above target vector, for GDB. Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1996, 1997, 1998, - 1999, 2000, 2001, 2003, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -52,13 +52,18 @@ static void call_extra_exec_file_hooks (char *filename); typedef void (*hook_type) (char *); -hook_type deprecated_exec_file_display_hook; /* the original hook */ -static hook_type *exec_file_extra_hooks; /* array of additional hooks */ -static int exec_file_hook_count = 0; /* size of array */ +hook_type deprecated_exec_file_display_hook; /* The original hook. */ +static hook_type *exec_file_extra_hooks; /* Array of additional + hooks. */ +static int exec_file_hook_count = 0; /* Size of array. */ /* Binary file diddling handle for the core file. */ bfd *core_bfd = NULL; + +/* corelow.c target (if included for this gdb target). */ + +struct target_ops *core_target; /* Backward compatability with old way of specifying core files. */ @@ -66,18 +71,15 @@ bfd *core_bfd = NULL; void core_file_command (char *filename, int from_tty) { - struct target_ops *t; - - dont_repeat (); /* Either way, seems bogus. */ + dont_repeat (); /* Either way, seems bogus. */ - t = find_core_target (); - if (t == NULL) + if (core_target == NULL) error (_("GDB can't read core files on this machine.")); if (!filename) - (t->to_detach) (t, filename, from_tty); + (core_target->to_detach) (core_target, filename, from_tty); else - (t->to_open) (filename, from_tty); + (core_target->to_open) (filename, from_tty); } @@ -105,11 +107,13 @@ specify_exec_file_hook (void (*hook) (char *)) if (deprecated_exec_file_display_hook != NULL) { /* There's already a hook installed. Arrange to have both it - * and the subsequent hooks called. */ + and the subsequent hooks called. */ if (exec_file_hook_count == 0) { - /* If this is the first extra hook, initialize the hook array. */ - exec_file_extra_hooks = (hook_type *) xmalloc (sizeof (hook_type)); + /* If this is the first extra hook, initialize the hook + array. */ + exec_file_extra_hooks = (hook_type *) + xmalloc (sizeof (hook_type)); exec_file_extra_hooks[0] = deprecated_exec_file_display_hook; deprecated_exec_file_display_hook = call_extra_exec_file_hooks; exec_file_hook_count = 1; @@ -119,9 +123,9 @@ specify_exec_file_hook (void (*hook) (char *)) Yes, it's inefficient to grow it by one each time but since this is hardly ever called it's not a big deal. */ exec_file_hook_count++; - new_array = - (hook_type *) xrealloc (exec_file_extra_hooks, - exec_file_hook_count * sizeof (hook_type)); + new_array = (hook_type *) + xrealloc (exec_file_extra_hooks, + exec_file_hook_count * sizeof (hook_type)); exec_file_extra_hooks = new_array; exec_file_extra_hooks[exec_file_hook_count - 1] = hook; } @@ -154,11 +158,11 @@ reopen_exec_file (void) struct stat st; struct cleanup *cleanups; - /* Don't do anything if there isn't an exec file. */ + /* Don't do anything if there isn't an exec file. */ if (exec_bfd == NULL) return; - /* If the timestamp of the exec file has changed, reopen it. */ + /* If the timestamp of the exec file has changed, reopen it. */ filename = xstrdup (bfd_get_filename (exec_bfd)); cleanups = make_cleanup (xfree, filename); res = stat (filename, &st); @@ -264,7 +268,7 @@ struct captured_read_memory_integer_arguments }; /* Helper function for gdb_read_memory_integer(). DATA must be a - pointer to a captured_read_memory_integer_arguments struct. + pointer to a captured_read_memory_integer_arguments struct. Return 1 if successful. Note that the catch_errors() interface will return 0 if an error occurred while reading memory. This choice of return code is so that we can distinguish between @@ -273,7 +277,8 @@ struct captured_read_memory_integer_arguments static int do_captured_read_memory_integer (void *data) { - struct captured_read_memory_integer_arguments *args = (struct captured_read_memory_integer_arguments*) data; + struct captured_read_memory_integer_arguments *args + = (struct captured_read_memory_integer_arguments*) data; CORE_ADDR memaddr = args->memaddr; int len = args->len; enum bfd_endian byte_order = args->byte_order; @@ -300,7 +305,7 @@ safe_read_memory_integer (CORE_ADDR memaddr, int len, args.byte_order = byte_order; status = catch_errors (do_captured_read_memory_integer, &args, - "", RETURN_MASK_ALL); + "", RETURN_MASK_ALL); if (status) *return_value = args.result; @@ -308,7 +313,8 @@ safe_read_memory_integer (CORE_ADDR memaddr, int len, } LONGEST -read_memory_integer (CORE_ADDR memaddr, int len, enum bfd_endian byte_order) +read_memory_integer (CORE_ADDR memaddr, int len, + enum bfd_endian byte_order) { gdb_byte buf[sizeof (LONGEST)]; @@ -317,7 +323,8 @@ read_memory_integer (CORE_ADDR memaddr, int len, enum bfd_endian byte_order) } ULONGEST -read_memory_unsigned_integer (CORE_ADDR memaddr, int len, enum bfd_endian byte_order) +read_memory_unsigned_integer (CORE_ADDR memaddr, int len, + enum bfd_endian byte_order) { gdb_byte buf[sizeof (ULONGEST)]; @@ -361,9 +368,11 @@ read_memory_typed_address (CORE_ADDR addr, struct type *type) return extract_typed_address (buf, type); } -/* Same as target_write_memory, but report an error if can't write. */ +/* Same as target_write_memory, but report an error if can't + write. */ void -write_memory (CORE_ADDR memaddr, const bfd_byte *myaddr, int len) +write_memory (CORE_ADDR memaddr, + const bfd_byte *myaddr, int len) { int status; @@ -372,7 +381,8 @@ write_memory (CORE_ADDR memaddr, const bfd_byte *myaddr, int len) memory_error (status, memaddr); } -/* Store VALUE at ADDR in the inferior as a LEN-byte unsigned integer. */ +/* Store VALUE at ADDR in the inferior as a LEN-byte unsigned + integer. */ void write_memory_unsigned_integer (CORE_ADDR addr, int len, enum bfd_endian byte_order, @@ -384,7 +394,8 @@ write_memory_unsigned_integer (CORE_ADDR addr, int len, write_memory (addr, buf, len); } -/* Store VALUE at ADDR in the inferior as a LEN-byte signed integer. */ +/* Store VALUE at ADDR in the inferior as a LEN-byte signed + integer. */ void write_memory_signed_integer (CORE_ADDR addr, int len, enum bfd_endian byte_order, @@ -404,15 +415,19 @@ char *gnutarget; static char *gnutarget_string; static void show_gnutarget_string (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) + struct cmd_list_element *c, + const char *value) { - fprintf_filtered (file, _("The current BFD target is \"%s\".\n"), value); + fprintf_filtered (file, + _("The current BFD target is \"%s\".\n"), value); } -static void set_gnutarget_command (char *, int, struct cmd_list_element *); +static void set_gnutarget_command (char *, int, + struct cmd_list_element *); static void -set_gnutarget_command (char *ignore, int from_tty, struct cmd_list_element *c) +set_gnutarget_command (char *ignore, int from_tty, + struct cmd_list_element *c) { if (strcmp (gnutarget_string, "auto") == 0) gnutarget = NULL; diff --git a/contrib/gdb-7/gdb/corelow.c b/contrib/gdb-7/gdb/corelow.c index 9523f32731..f34b8e1b9d 100644 --- a/contrib/gdb-7/gdb/corelow.c +++ b/contrib/gdb-7/gdb/corelow.c @@ -1,8 +1,8 @@ /* Core dump and executable file functions below target vector, for GDB. Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -59,8 +59,8 @@ static struct core_fns *core_file_fns = NULL; -/* The core_fns for a core file handler that is prepared to read the core - file currently open on core_bfd. */ +/* The core_fns for a core file handler that is prepared to read the + core file currently open on core_bfd. */ static struct core_fns *core_vec = NULL; @@ -100,15 +100,15 @@ static void init_core_ops (void); void _initialize_corelow (void); -struct target_ops core_ops; +static struct target_ops core_ops; /* An arbitrary identifier for the core inferior. */ #define CORELOW_PID 1 -/* Link a new core_fns into the global core_file_fns list. Called on gdb - startup by the _initialize routine in each core file register reader, to - register information about each format the the reader is prepared to - handle. */ +/* Link a new core_fns into the global core_file_fns list. Called on + gdb startup by the _initialize routine in each core file register + reader, to register information about each format the reader is + prepared to handle. */ void deprecated_add_core_fns (struct core_fns *cf) @@ -119,7 +119,7 @@ deprecated_add_core_fns (struct core_fns *cf) /* The default function that core file handlers can use to examine a core file BFD and decide whether or not to accept the job of - reading the core file. */ + reading the core file. */ int default_core_sniffer (struct core_fns *our_fns, bfd *abfd) @@ -133,7 +133,7 @@ default_core_sniffer (struct core_fns *our_fns, bfd *abfd) /* Walk through the list of core functions to find a set that can handle the core file open on ABFD. Default to the first one in the list if nothing matches. Returns pointer to set that is - selected. */ + selected. */ static struct core_fns * sniff_core_bfd (bfd *abfd) @@ -142,7 +142,8 @@ sniff_core_bfd (bfd *abfd) struct core_fns *yummy = NULL; int matches = 0;; - /* Don't sniff if we have support for register sets in CORE_GDBARCH. */ + /* Don't sniff if we have support for register sets in + CORE_GDBARCH. */ if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch)) return NULL; @@ -161,7 +162,8 @@ sniff_core_bfd (bfd *abfd) } else if (matches == 0) { - warning (_("\"%s\": no core file handler recognizes format, using default"), + warning (_("\"%s\": no core file handler " + "recognizes format, using default"), bfd_get_filename (abfd)); } if (yummy == NULL) @@ -173,7 +175,7 @@ sniff_core_bfd (bfd *abfd) /* The default is to reject every core file format we see. Either BFD has to recognize it, or we have to provide a function in the - core file handler that recognizes it. */ + core file handler that recognizes it. */ int default_check_format (bfd *abfd) @@ -181,7 +183,7 @@ default_check_format (bfd *abfd) return (0); } -/* Attempt to recognize core file formats that BFD rejects. */ +/* Attempt to recognize core file formats that BFD rejects. */ static int gdb_check_format (bfd *abfd) @@ -198,8 +200,8 @@ gdb_check_format (bfd *abfd) return (0); } -/* Discard all vestiges of any previous core file and mark data and stack - spaces as empty. */ +/* Discard all vestiges of any previous core file and mark data and + stack spaces as empty. */ static void core_close (int quitting) @@ -209,11 +211,12 @@ core_close (int quitting) if (core_bfd) { int pid = ptid_get_pid (inferior_ptid); - inferior_ptid = null_ptid; /* Avoid confusion from thread stuff */ + inferior_ptid = null_ptid; /* Avoid confusion from thread + stuff. */ exit_inferior_silent (pid); - /* Clear out solib state while the bfd is still open. See - comments in clear_solib in solib.c. */ + /* Clear out solib state while the bfd is still open. See + comments in clear_solib in solib.c. */ clear_solib (); xfree (core_data->sections); @@ -236,8 +239,8 @@ core_close_cleanup (void *ignore) core_close (0/*ignored*/); } -/* Look for sections whose names start with `.reg/' so that we can extract the - list of threads in a core file. */ +/* Look for sections whose names start with `.reg/' so that we can + extract the list of threads in a core file. */ static void add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg) @@ -252,29 +255,15 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg) core_tid = atoi (bfd_section_name (abfd, asect) + 5); - if (core_gdbarch - && gdbarch_core_reg_section_encodes_pid (core_gdbarch)) - { - uint32_t merged_pid = core_tid; - pid = merged_pid & 0xffff; - lwpid = merged_pid >> 16; - - /* This can happen on solaris core, for example, if we don't - find a NT_PSTATUS note in the core, but do find NT_LWPSTATUS - notes. */ - if (pid == 0) - { - core_has_fake_pid = 1; - pid = CORELOW_PID; - } - } - else + pid = bfd_core_file_pid (core_bfd); + if (pid == 0) { core_has_fake_pid = 1; pid = CORELOW_PID; - lwpid = core_tid; } + lwpid = core_tid; + if (current_inferior ()->pid == 0) inferior_appeared (current_inferior (), pid); @@ -285,8 +274,8 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg) /* Warning, Will Robinson, looking at BFD private data! */ if (reg_sect != NULL - && asect->filepos == reg_sect->filepos) /* Did we find .reg? */ - inferior_ptid = ptid; /* Yes, make it current */ + && asect->filepos == reg_sect->filepos) /* Did we find .reg? */ + inferior_ptid = ptid; /* Yes, make it current. */ } /* This routine opens and sets up the core file bfd. */ @@ -306,15 +295,17 @@ core_open (char *filename, int from_tty) if (!filename) { if (core_bfd) - error (_("No core file specified. (Use `detach' to stop debugging a core file.)")); + error (_("No core file specified. (Use `detach' " + "to stop debugging a core file.)")); else error (_("No core file specified.")); } filename = tilde_expand (filename); - if (!IS_ABSOLUTE_PATH(filename)) + if (!IS_ABSOLUTE_PATH (filename)) { - temp = concat (current_directory, "/", filename, (char *)NULL); + temp = concat (current_directory, "/", + filename, (char *) NULL); xfree (filename); filename = temp; } @@ -340,15 +331,16 @@ core_open (char *filename, int from_tty) && !gdb_check_format (temp_bfd)) { /* Do it after the err msg */ - /* FIXME: should be checking for errors from bfd_close (for one thing, - on error it does not free all the storage associated with the - bfd). */ + /* FIXME: should be checking for errors from bfd_close (for one + thing, on error it does not free all the storage associated + with the bfd). */ make_cleanup_bfd_close (temp_bfd); error (_("\"%s\" is not a core dump: %s"), filename, bfd_errmsg (bfd_get_error ())); } - /* Looks semi-reasonable. Toss the old core file and work on the new. */ + /* Looks semi-reasonable. Toss the old core file and work on the + new. */ discard_cleanups (old_chain); /* Don't free filename any more */ unpush_target (&core_ops); @@ -372,7 +364,8 @@ core_open (char *filename, int from_tty) /* Find the data section */ if (build_section_table (core_bfd, - &core_data->sections, &core_data->sections_end)) + &core_data->sections, + &core_data->sections_end)) error (_("\"%s\": Can't find sections: %s"), bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); @@ -405,7 +398,7 @@ core_open (char *filename, int from_tty) /* Build up thread list from BFD sections, and possibly set the current thread to the .reg/NN section matching the .reg - section. */ + section. */ bfd_map_over_sections (core_bfd, add_to_thread_list, bfd_get_section_by_name (core_bfd, ".reg")); @@ -443,15 +436,19 @@ core_open (char *filename, int from_tty) siggy = bfd_core_file_failing_signal (core_bfd); if (siggy > 0) - /* NOTE: target_signal_from_host() converts a target signal value - into gdb's internal signal value. Unfortunately gdb's internal - value is called ``target_signal'' and this function got the - name ..._from_host(). */ - printf_filtered (_("Program terminated with signal %d, %s.\n"), siggy, - target_signal_to_string ( - (core_gdbarch != NULL) ? - gdbarch_target_signal_from_host (core_gdbarch, siggy) - : siggy)); + { + /* NOTE: target_signal_from_host() converts a target signal + value into gdb's internal signal value. Unfortunately gdb's + internal value is called ``target_signal'' and this function + got the name ..._from_host(). */ + enum target_signal sig = (core_gdbarch != NULL + ? gdbarch_target_signal_from_host (core_gdbarch, + siggy) + : target_signal_from_host (siggy)); + + printf_filtered (_("Program terminated with signal %d, %s.\n"), + siggy, target_signal_to_string (sig)); + } /* Fetch all registers from core file. */ target_fetch_registers (get_current_regcache (), -1); @@ -504,7 +501,8 @@ deprecated_core_resize_section_table (int num_added) NAME section contains, for use in error messages. If REQUIRED is non-zero, print an error if the core file doesn't - have a section by the appropriate name. Otherwise, just do nothing. */ + have a section by the appropriate name. Otherwise, just do + nothing. */ static void get_core_register_section (struct regcache *regcache, @@ -520,22 +518,9 @@ get_core_register_section (struct regcache *regcache, xfree (section_name); - if (core_gdbarch - && gdbarch_core_reg_section_encodes_pid (core_gdbarch)) - { - uint32_t merged_pid; - int pid = ptid_get_pid (inferior_ptid); - - if (core_has_fake_pid) - pid = 0; - - merged_pid = ptid_get_lwp (inferior_ptid); - merged_pid = merged_pid << 16 | pid; - - section_name = xstrprintf ("%s/%s", name, plongest (merged_pid)); - } - else if (ptid_get_lwp (inferior_ptid)) - section_name = xstrprintf ("%s/%ld", name, ptid_get_lwp (inferior_ptid)); + if (ptid_get_lwp (inferior_ptid)) + section_name = xstrprintf ("%s/%ld", name, + ptid_get_lwp (inferior_ptid)); else section_name = xstrdup (name); @@ -543,7 +528,8 @@ get_core_register_section (struct regcache *regcache, if (! section) { if (required) - warning (_("Couldn't find %s registers in core file."), human_name); + warning (_("Couldn't find %s registers in core file."), + human_name); return; } @@ -561,7 +547,8 @@ get_core_register_section (struct regcache *regcache, { const struct regset *regset; - regset = gdbarch_regset_from_core_section (core_gdbarch, name, size); + regset = gdbarch_regset_from_core_section (core_gdbarch, + name, size); if (regset == NULL) { if (required) @@ -583,7 +570,8 @@ get_core_register_section (struct regcache *regcache, /* Get the registers out of a core file. This is the machine- independent part. Fetch_core_registers is the machine-dependent - part, typically implemented in the xm-file for each architecture. */ + part, typically implemented in the xm-file for each + architecture. */ /* We just get all the registers, so we don't use regno. */ @@ -627,9 +615,9 @@ get_core_registers (struct target_ops *ops, ".reg2", 2, "floating-point", 0); } - /* Supply dummy value for all registers not found in the core. */ + /* Mark all registers not found in the core as unavailable. */ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++) - if (!regcache_valid_p (regcache, i)) + if (regcache_register_status (regcache, i) == REG_UNKNOWN) regcache_raw_supply (regcache, i, NULL); } @@ -653,7 +641,7 @@ add_to_spuid_list (bfd *abfd, asection *asect, void *list_p) { struct spuid_list *list = list_p; enum bfd_endian byte_order - = bfd_big_endian (abfd)? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; + = bfd_big_endian (abfd) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; int fd, pos = 0; sscanf (bfd_section_name (abfd, asect), "SPU/%d/regs%n", &fd, &pos); @@ -672,7 +660,8 @@ add_to_spuid_list (bfd *abfd, asection *asect, void *list_p) static LONGEST core_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, LONGEST len) + const gdb_byte *writebuf, ULONGEST offset, + LONGEST len) { switch (object) { @@ -718,7 +707,8 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, if (readbuf) { /* When the StackGhost cookie is stored in core file, BFD - represents this with a fake section called ".wcookie". */ + represents this with a fake section called + ".wcookie". */ struct bfd_section *section; bfd_size_type size; @@ -761,7 +751,8 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, if (readbuf && annex) { /* When the SPU contexts are stored in a core file, BFD - represents this with a fake section called "SPU/". */ + represents this with a fake section called + "SPU/". */ struct bfd_section *section; bfd_size_type size; @@ -806,15 +797,17 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, default: if (ops->beneath != NULL) - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len); + return ops->beneath->to_xfer_partial (ops->beneath, object, + annex, readbuf, + writebuf, offset, len); return -1; } } /* If mourn is being called in all the right places, this could be say - `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */ + `gdb internal error' (since generic_mourn calls + breakpoint_init_inferior). */ static int ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt) @@ -844,7 +837,8 @@ static const struct target_desc * core_read_description (struct target_ops *target) { if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch)) - return gdbarch_core_read_description (core_gdbarch, target, core_bfd); + return gdbarch_core_read_description (core_gdbarch, + target, core_bfd); return NULL; } @@ -853,21 +847,29 @@ static char * core_pid_to_str (struct target_ops *ops, ptid_t ptid) { static char buf[64]; + int pid; + /* The preferred way is to have a gdbarch/OS specific + implementation. */ if (core_gdbarch && gdbarch_core_pid_to_str_p (core_gdbarch)) - { - char *ret = gdbarch_core_pid_to_str (core_gdbarch, ptid); + return gdbarch_core_pid_to_str (core_gdbarch, ptid); - if (ret != NULL) - return ret; - } + /* Otherwise, if we don't have one, we'll just fallback to + "process", with normal_pid_to_str. */ - if (ptid_get_lwp (ptid) == 0) - xsnprintf (buf, sizeof buf, "
"); - else - xsnprintf (buf, sizeof buf, "Thread %ld", ptid_get_lwp (ptid)); + /* Try the LWPID field first. */ + pid = ptid_get_lwp (ptid); + if (pid != 0) + return normal_pid_to_str (pid_to_ptid (pid)); + /* Otherwise, this isn't a "threaded" core -- use the PID field, but + only if it isn't a fake PID. */ + if (!core_has_fake_pid) + return normal_pid_to_str (ptid); + + /* No luck. We simply don't have a valid PID to print. */ + xsnprintf (buf, sizeof buf, "
"); return buf; } @@ -911,11 +913,17 @@ init_core_ops (void) core_ops.to_thread_alive = core_thread_alive; core_ops.to_read_description = core_read_description; core_ops.to_pid_to_str = core_pid_to_str; - core_ops.to_stratum = core_stratum; + core_ops.to_stratum = process_stratum; core_ops.to_has_memory = core_has_memory; core_ops.to_has_stack = core_has_stack; core_ops.to_has_registers = core_has_registers; core_ops.to_magic = OPS_MAGIC; + + if (core_target) + internal_error (__FILE__, __LINE__, + _("init_core_ops: core target already exists (\"%s\")."), + core_target->to_longname); + core_target = &core_ops; } void diff --git a/contrib/gdb-7/gdb/cp-abi.c b/contrib/gdb-7/gdb/cp-abi.c index 14552d1e6d..040962eba2 100644 --- a/contrib/gdb-7/gdb/cp-abi.c +++ b/contrib/gdb-7/gdb/cp-abi.c @@ -1,6 +1,6 @@ /* Generic code for supporting multiple C++ ABI's - Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -25,7 +25,7 @@ #include "exceptions.h" #include "gdbcmd.h" #include "ui-out.h" - +#include "gdb_assert.h" #include "gdb_string.h" static struct cp_abi_ops *find_cp_abi (const char *short_name); @@ -70,25 +70,46 @@ is_operator_name (const char *name) } int -baseclass_offset (struct type *type, int index, const bfd_byte *valaddr, - CORE_ADDR address) +baseclass_offset (struct type *type, int index, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + const struct value *val) { - if (current_cp_abi.baseclass_offset == NULL) - error (_("ABI doesn't define required function baseclass_offset")); - return (*current_cp_abi.baseclass_offset) (type, index, valaddr, address); + volatile struct gdb_exception ex; + int res = 0; + + gdb_assert (current_cp_abi.baseclass_offset != NULL); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + res = (*current_cp_abi.baseclass_offset) (type, index, valaddr, + embedded_offset, + address, val); + } + + if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + throw_error (NOT_AVAILABLE_ERROR, + _("Cannot determine virtual baseclass offset " + "of incomplete object")); + else if (ex.reason < 0) + throw_exception (ex); + else + return res; } struct value * -value_virtual_fn_field (struct value **arg1p, struct fn_field *f, int j, +value_virtual_fn_field (struct value **arg1p, + struct fn_field *f, int j, struct type *type, int offset) { if ((current_cp_abi.virtual_fn_field) == NULL) return NULL; - return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset); + return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, + type, offset); } struct type * -value_rtti_type (struct value *v, int *full, int *top, int *using_enc) +value_rtti_type (struct value *v, int *full, + int *top, int *using_enc) { struct type *ret = NULL; struct gdb_exception e; @@ -105,7 +126,8 @@ value_rtti_type (struct value *v, int *full, int *top, int *using_enc) } void -cplus_print_method_ptr (const gdb_byte *contents, struct type *type, +cplus_print_method_ptr (const gdb_byte *contents, + struct type *type, struct ui_file *stream) { if (current_cp_abi.print_method_ptr == NULL) @@ -131,7 +153,8 @@ cplus_make_method_ptr (struct type *type, gdb_byte *contents, } CORE_ADDR -cplus_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc) +cplus_skip_trampoline (struct frame_info *frame, + CORE_ADDR stop_pc) { if (current_cp_abi.skip_trampoline == NULL) return 0; @@ -139,7 +162,8 @@ cplus_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc) } struct value * -cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr) +cplus_method_ptr_to_value (struct value **this_p, + struct value *method_ptr) { if (current_cp_abi.method_ptr_to_value == NULL) error (_("GDB does not support pointers to methods on this target")); @@ -176,7 +200,8 @@ register_cp_abi (struct cp_abi_ops *abi) { if (num_cp_abis == CP_ABI_MAX) internal_error (__FILE__, __LINE__, - _("Too many C++ ABIs, please increase CP_ABI_MAX in cp-abi.c")); + _("Too many C++ ABIs, please increase " + "CP_ABI_MAX in cp-abi.c")); cp_abis[num_cp_abis++] = abi; @@ -241,7 +266,8 @@ list_cp_abis (int from_tty) int i; ui_out_text (uiout, "The available C++ ABIs are:\n"); - cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "cp-abi-list"); + cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, + "cp-abi-list"); for (i = 0; i < num_cp_abis; i++) { char pad[14]; @@ -305,5 +331,6 @@ Set the ABI used for inspecting C++ objects.\n\ &setlist); add_cmd ("cp-abi", class_obscure, show_cp_abi_cmd, - _("Show the ABI used for inspecting C++ objects."), &showlist); + _("Show the ABI used for inspecting C++ objects."), + &showlist); } diff --git a/contrib/gdb-7/gdb/cp-abi.h b/contrib/gdb-7/gdb/cp-abi.h index 586be91dbd..9bfa1b0356 100644 --- a/contrib/gdb-7/gdb/cp-abi.h +++ b/contrib/gdb-7/gdb/cp-abi.h @@ -3,7 +3,7 @@ Contributed by Daniel Berlin - Copyright (C) 2001, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -69,7 +69,8 @@ enum dtor_kinds { `delete'. */ complete_object_dtor, - /* A destructor which finalizes a subobject of some larger object. */ + /* A destructor which finalizes a subobject of some larger + object. */ base_object_dtor }; @@ -105,8 +106,10 @@ extern int is_operator_name (const char *name); this is the type containing F. OFFSET is the offset of that base type within *VALUEP. */ extern struct value *value_virtual_fn_field (struct value **valuep, - struct fn_field *f, int j, - struct type *type, int offset); + struct fn_field *f, + int j, + struct type *type, + int offset); /* Try to find the run-time type of VALUE, using C++ run-time type @@ -133,47 +136,53 @@ extern struct value *value_virtual_fn_field (struct value **valuep, FULL, TOP, and USING_ENC can each be zero, in which case we don't provide the corresponding piece of information. */ extern struct type *value_rtti_type (struct value *value, - int *full, int *top, int *using_enc); + int *full, int *top, + int *using_enc); -/* Compute the offset of the baseclass which is - the INDEXth baseclass of class TYPE, - for value at VALADDR (in host) at ADDRESS (in target). - The result is the offset of the baseclass value relative - to (the address of)(ARG) + OFFSET. +/* Compute the offset of the baseclass which is the INDEXth baseclass + of class TYPE, for value at VALADDR (in host) at ADDRESS (in + target), offset by EMBEDDED_OFFSET. VALADDR points to the raw + contents of VAL. The result is the offset of the baseclass value + relative to (the address of)(ARG) + OFFSET. */ - -1 is returned on error. */ +extern int baseclass_offset (struct type *type, + int index, const gdb_byte *valaddr, + int embedded_offset, + CORE_ADDR address, + const struct value *val); -extern int baseclass_offset (struct type *type, int index, - const bfd_byte *valaddr, CORE_ADDR address); - /* Describe the target of a pointer to method. CONTENTS is the byte pattern representing the pointer to method. TYPE is the pointer to method type. STREAM is the stream to print it to. */ -void cplus_print_method_ptr (const gdb_byte *contents, struct type *type, +void cplus_print_method_ptr (const gdb_byte *contents, + struct type *type, struct ui_file *stream); -/* Return the size of a pointer to member function of type TO_TYPE. */ +/* Return the size of a pointer to member function of type + TO_TYPE. */ int cplus_method_ptr_size (struct type *to_type); -/* Return the method which should be called by applying METHOD_PTR - to *THIS_P, and adjust *THIS_P if necessary. */ +/* Return the method which should be called by applying METHOD_PTR to + *THIS_P, and adjust *THIS_P if necessary. */ struct value *cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr); -/* Create the byte pattern in CONTENTS representing a pointer of - type TYPE to member function at ADDRESS (if IS_VIRTUAL is 0) - or with virtual table offset ADDRESS (if IS_VIRTUAL is 1). - This is the opposite of cplus_method_ptr_to_value. */ +/* Create the byte pattern in CONTENTS representing a pointer of type + TYPE to member function at ADDRESS (if IS_VIRTUAL is 0) or with + virtual table offset ADDRESS (if IS_VIRTUAL is 1). This is the + opposite of cplus_method_ptr_to_value. */ void cplus_make_method_ptr (struct type *type, gdb_byte *CONTENTS, CORE_ADDR address, int is_virtual); -/* Determine if we are currently in a C++ thunk. If so, get the address - of the routine we are thunking to and continue to there instead. */ +/* Determine if we are currently in a C++ thunk. If so, get the + address of the routine we are thunking to and continue to there + instead. */ -CORE_ADDR cplus_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc); +CORE_ADDR cplus_skip_trampoline (struct frame_info *frame, + CORE_ADDR stop_pc); -/* Return non-zero if an argument of type TYPE should be passed by reference - instead of value. */ +/* Return non-zero if an argument of type TYPE should be passed by + reference instead of value. */ extern int cp_pass_by_reference (struct type *type); struct cp_abi_ops @@ -182,22 +191,29 @@ struct cp_abi_ops const char *longname; const char *doc; - /* ABI-specific implementations for the functions declared above. */ + /* ABI-specific implementations for the functions declared + above. */ enum ctor_kinds (*is_constructor_name) (const char *name); enum dtor_kinds (*is_destructor_name) (const char *name); int (*is_vtable_name) (const char *name); int (*is_operator_name) (const char *name); - struct value *(*virtual_fn_field) (struct value **arg1p, struct fn_field * f, - int j, struct type * type, int offset); - struct type *(*rtti_type) (struct value *v, int *full, int *top, - int *using_enc); + struct value *(*virtual_fn_field) (struct value **arg1p, + struct fn_field * f, + int j, struct type * type, + int offset); + struct type *(*rtti_type) (struct value *v, int *full, + int *top, int *using_enc); int (*baseclass_offset) (struct type *type, int index, - const bfd_byte *valaddr, CORE_ADDR address); - void (*print_method_ptr) (const gdb_byte *contents, struct type *type, + const bfd_byte *valaddr, int embedded_offset, + CORE_ADDR address, const struct value *val); + void (*print_method_ptr) (const gdb_byte *contents, + struct type *type, struct ui_file *stream); int (*method_ptr_size) (struct type *); - void (*make_method_ptr) (struct type *, gdb_byte *, CORE_ADDR, int); - struct value * (*method_ptr_to_value) (struct value **, struct value *); + void (*make_method_ptr) (struct type *, gdb_byte *, + CORE_ADDR, int); + struct value * (*method_ptr_to_value) (struct value **, + struct value *); CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR); int (*pass_by_reference) (struct type *type); }; diff --git a/contrib/gdb-7/gdb/cp-name-parser.y b/contrib/gdb-7/gdb/cp-name-parser.y index 6d7b600a95..87367779a0 100644 --- a/contrib/gdb-7/gdb/cp-name-parser.y +++ b/contrib/gdb-7/gdb/cp-name-parser.y @@ -1,6 +1,6 @@ /* YACC parser for C++ names, for GDB. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Parts of the lexer are based on c-exp.y from GDB. @@ -1568,14 +1568,14 @@ yylex (void) c = cp_parse_escape (&lexptr); else if (c == '\'') { - yyerror ("empty character constant"); + yyerror (_("empty character constant")); return ERROR; } c = *lexptr++; if (c != '\'') { - yyerror ("invalid character constant"); + yyerror (_("invalid character constant")); return ERROR; } @@ -1699,7 +1699,7 @@ yylex (void) memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - yyerror ("invalid number"); + yyerror (_("invalid number")); return ERROR; } lexptr = p; @@ -1775,14 +1775,14 @@ yylex (void) case '"': /* These can't occur in C++ names. */ - yyerror ("unexpected string literal"); + yyerror (_("unexpected string literal")); return ERROR; } if (!(c == '_' || c == '$' || ISALPHA (c))) { /* We must have come across a bad character (e.g. ';'). */ - yyerror ("invalid character"); + yyerror (_("invalid character")); return ERROR; } diff --git a/contrib/gdb-7/gdb/cp-namespace.c b/contrib/gdb-7/gdb/cp-namespace.c index d0fdcbe440..cc761c8cd1 100644 --- a/contrib/gdb-7/gdb/cp-namespace.c +++ b/contrib/gdb-7/gdb/cp-namespace.c @@ -1,5 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -32,6 +32,7 @@ #include "command.h" #include "frame.h" #include "buildsym.h" +#include "language.h" static struct symbol *lookup_namespace_scope (const char *name, const struct block *block, @@ -69,10 +70,6 @@ static void maintenance_cplus_namespace (char *args, int from_tty); /* Check to see if SYMBOL refers to an object contained within an anonymous namespace; if so, add an appropriate using directive. */ -/* Optimize away strlen ("(anonymous namespace)"). */ - -#define ANONYMOUS_NAMESPACE_LEN 21 - void cp_scan_for_anonymous_namespaces (const struct symbol *symbol) { @@ -93,12 +90,14 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) while (name[next_component] == ':') { - if ((next_component - previous_component) == ANONYMOUS_NAMESPACE_LEN + if (((next_component - previous_component) + == CP_ANONYMOUS_NAMESPACE_LEN) && strncmp (name + previous_component, - "(anonymous namespace)", - ANONYMOUS_NAMESPACE_LEN) == 0) + CP_ANONYMOUS_NAMESPACE_STR, + CP_ANONYMOUS_NAMESPACE_LEN) == 0) { - int dest_len = (previous_component == 0 ? 0 : previous_component - 2); + int dest_len = (previous_component == 0 + ? 0 : previous_component - 2); int src_len = next_component; char *dest = alloca (dest_len + 1); @@ -127,14 +126,16 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) } -/* Add a using directive to using_directives. If the using directive in - question has already been added, don't add it twice. - Create a new struct using_direct which imports the namespace SRC into the - scope DEST. ALIAS is the name of the imported namespace in the current - scope. If ALIAS is NULL then the namespace is known by its original name. - DECLARATION is the name if the imported varable if this is a declaration - import (Eg. using A::x), otherwise it is NULL. The arguments are copied - into newly allocated memory so they can be temporaries. */ +/* Add a using directive to using_directives. If the using directive + in question has already been added, don't add it twice. + + Create a new struct using_direct which imports the namespace SRC + into the scope DEST. ALIAS is the name of the imported namespace + in the current scope. If ALIAS is NULL then the namespace is known + by its original name. DECLARATION is the name if the imported + varable if this is a declaration import (Eg. using A::x), otherwise + it is NULL. The arguments are copied into newly allocated memory + so they can be temporaries. */ void cp_add_using_directive (const char *dest, @@ -221,7 +222,7 @@ cp_set_block_scope (const struct symbol *symbol, int cp_is_anonymous (const char *namespace) { - return (strstr (namespace, "(anonymous namespace)") + return (strstr (namespace, CP_ANONYMOUS_NAMESPACE_STR) != NULL); } @@ -229,8 +230,9 @@ cp_is_anonymous (const char *namespace) names. This makes sure that names get looked for in all namespaces that are in scope. NAME is the natural name of the symbol that we're looking for, BLOCK is the block that we're searching within, - DOMAIN says what kind of symbols we're looking for, and if SYMTAB is - non-NULL, we should store the symtab where we found the symbol in it. */ + DOMAIN says what kind of symbols we're looking for, and if SYMTAB + is non-NULL, we should store the symtab where we found the symbol + in it. */ struct symbol * cp_lookup_symbol_nonlocal (const char *name, @@ -240,15 +242,17 @@ cp_lookup_symbol_nonlocal (const char *name, struct symbol *sym; const char *scope = block_scope (block); - sym = lookup_namespace_scope (name, block, domain, scope, 0); + sym = lookup_namespace_scope (name, block, + domain, scope, 0); if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, block, domain); + return cp_lookup_symbol_namespace (scope, name, + block, domain); } -/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in - cp_lookup_symbol_nonlocal. */ +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are + as in cp_lookup_symbol_nonlocal. */ static struct symbol * cp_lookup_symbol_in_namespace (const char *namespace, @@ -262,14 +266,14 @@ cp_lookup_symbol_in_namespace (const char *namespace, } else { - char *concatenated_name = alloca (strlen (namespace) + 2 + - strlen (name) + 1); + char *concatenated_name = alloca (strlen (namespace) + 2 + + strlen (name) + 1); strcpy (concatenated_name, namespace); strcat (concatenated_name, "::"); strcat (concatenated_name, name); - return lookup_symbol_file (concatenated_name, block, - domain, cp_is_anonymous (namespace)); + return lookup_symbol_file (concatenated_name, block, domain, + cp_is_anonymous (namespace)); } } @@ -283,30 +287,30 @@ reset_directive_searched (void *data) direct->searched = 0; } -/* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. If DECLARATION_ONLY the search - is restricted to using declarations. +/* Search for NAME by applying all import statements belonging to + BLOCK which are applicable in SCOPE. If DECLARATION_ONLY the + search is restricted to using declarations. Example: - namespace A{ + namespace A { int x; } using A::x; - If SEARCH_PARENTS the search will include imports which are applicable in - parents of SCOPE. + If SEARCH_PARENTS the search will include imports which are + applicable in parents of SCOPE. Example: - namespace A{ + namespace A { using namespace X; - namespace B{ + namespace B { using namespace Y; } } - If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X - and Y will be considered. If SEARCH_PARENTS is false only the import of Y - is considered. */ + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of + namespaces X and Y will be considered. If SEARCH_PARENTS is false + only the import of Y is considered. */ struct symbol * cp_lookup_symbol_imports (const char *scope, @@ -324,14 +328,15 @@ cp_lookup_symbol_imports (const char *scope, /* First, try to find the symbol in the given namespace. */ if (!declaration_only) - sym = cp_lookup_symbol_in_namespace (scope, name, block, domain); + sym = cp_lookup_symbol_in_namespace (scope, name, + block, domain); if (sym != NULL) return sym; - /* Go through the using directives. If any of them add new - names to the namespace we're searching in, see if we can find a - match by applying them. */ + /* Go through the using directives. If any of them add new names to + the namespace we're searching in, see if we can find a match by + applying them. */ for (current = block_using (block); current != NULL; @@ -342,33 +347,35 @@ cp_lookup_symbol_imports (const char *scope, ? (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0 && (len == 0 - || scope[len] == ':' || scope[len] == '\0')) + || scope[len] == ':' + || scope[len] == '\0')) : strcmp (scope, current->import_dest) == 0); - /* If the import destination is the current scope or one of its ancestors then - it is applicable. */ + /* If the import destination is the current scope or one of its + ancestors then it is applicable. */ if (directive_match && !current->searched) { - /* Mark this import as searched so that the recursive call does not - search it again. */ + /* Mark this import as searched so that the recursive call + does not search it again. */ current->searched = 1; - searched_cleanup = make_cleanup (reset_directive_searched, current); - - /* If there is an import of a single declaration, compare the imported - declaration (after optional renaming by its alias) with the sought - out name. If there is a match pass current->import_src as NAMESPACE - to direct the search towards the imported namespace. */ + searched_cleanup = make_cleanup (reset_directive_searched, + current); + + /* If there is an import of a single declaration, compare the + imported declaration (after optional renaming by its alias) + with the sought out name. If there is a match pass + current->import_src as NAMESPACE to direct the search + towards the imported namespace. */ if (current->declaration - && strcmp (name, current->alias ? current->alias - : current->declaration) == 0) + && strcmp (name, current->alias + ? current->alias : current->declaration) == 0) sym = cp_lookup_symbol_in_namespace (current->import_src, - current->declaration, - block, - domain); + current->declaration, + block, domain); - /* If this is a DECLARATION_ONLY search or a symbol was found or - this import statement was an import declaration, the search - of this import is complete. */ + /* If this is a DECLARATION_ONLY search or a symbol was found + or this import statement was an import declaration, the + search of this import is complete. */ if (declaration_only || sym != NULL || current->declaration) { current->searched = 0; @@ -380,26 +387,24 @@ cp_lookup_symbol_imports (const char *scope, continue; } - if (current->alias != NULL && strcmp (name, current->alias) == 0) - /* If the import is creating an alias and the alias matches the - sought name. Pass current->import_src as the NAME to direct the - search towards the aliased namespace. */ + if (current->alias != NULL + && strcmp (name, current->alias) == 0) + /* If the import is creating an alias and the alias matches + the sought name. Pass current->import_src as the NAME to + direct the search towards the aliased namespace. */ { sym = cp_lookup_symbol_in_namespace (scope, - current->import_src, - block, - domain); + current->import_src, + block, domain); } else if (current->alias == NULL) { - /* If this import statement creates no alias, pass current->inner as - NAMESPACE to direct the search towards the imported namespace. */ + /* If this import statement creates no alias, pass + current->inner as NAMESPACE to direct the search + towards the imported namespace. */ sym = cp_lookup_symbol_imports (current->import_src, - name, - block, - domain, - 0, - 0); + name, block, + domain, 0, 0); } current->searched = 0; discard_cleanups (searched_cleanup); @@ -412,9 +417,104 @@ cp_lookup_symbol_imports (const char *scope, return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import - statements belonging to BLOCK and its parents. SCOPE is the namespace scope - of the context in which the search is being evaluated. */ +/* Helper function that searches an array of symbols for one named + NAME. */ + +static struct symbol * +search_symbol_list (const char *name, int num, + struct symbol **syms) +{ + int i; + + /* Maybe we should store a dictionary in here instead. */ + for (i = 0; i < num; ++i) + { + if (strcmp (name, SYMBOL_NATURAL_NAME (syms[i])) == 0) + return syms[i]; + } + return NULL; +} + +/* Like cp_lookup_symbol_imports, but if BLOCK is a function, it + searches through the template parameters of the function and the + function's type. */ + +struct symbol * +cp_lookup_symbol_imports_or_template (const char *scope, + const char *name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *function = BLOCK_FUNCTION (block); + + if (function != NULL && SYMBOL_LANGUAGE (function) == language_cplus) + { + int i; + struct cplus_specific *cps + = function->ginfo.language_specific.cplus_specific; + + /* Search the function's template parameters. */ + if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (function)) + { + struct template_symbol *templ + = (struct template_symbol *) function; + struct symbol *result; + + result = search_symbol_list (name, + templ->n_template_arguments, + templ->template_arguments); + if (result != NULL) + return result; + } + + /* Search the template parameters of the function's defining + context. */ + if (SYMBOL_NATURAL_NAME (function)) + { + struct type *context; + char *name_copy = xstrdup (SYMBOL_NATURAL_NAME (function)); + struct cleanup *cleanups = make_cleanup (xfree, name_copy); + const struct language_defn *lang = language_def (language_cplus); + struct gdbarch *arch = SYMBOL_SYMTAB (function)->objfile->gdbarch; + const struct block *parent = BLOCK_SUPERBLOCK (block); + + while (1) + { + struct symbol *result; + unsigned int prefix_len = cp_entire_prefix_len (name_copy); + + if (prefix_len == 0) + context = NULL; + else + { + name_copy[prefix_len] = '\0'; + context = lookup_typename (lang, arch, + name_copy, + parent, 1); + } + + if (context == NULL) + break; + + result + = search_symbol_list (name, + TYPE_N_TEMPLATE_ARGUMENTS (context), + TYPE_TEMPLATE_ARGUMENTS (context)); + if (result != NULL) + return result; + } + + do_cleanups (cleanups); + } + } + + return cp_lookup_symbol_imports (scope, name, block, domain, 1, 1); +} + + /* Searches for NAME in the current namespace, and by applying + relevant import statements belonging to BLOCK and its parents. + SCOPE is the namespace scope of the context in which the search is + being evaluated. */ struct symbol* cp_lookup_symbol_namespace (const char *scope, @@ -425,14 +525,17 @@ cp_lookup_symbol_namespace (const char *scope, struct symbol *sym; /* First, try to find the symbol in the given namespace. */ - sym = cp_lookup_symbol_in_namespace (scope, name, block, domain); + sym = cp_lookup_symbol_in_namespace (scope, name, + block, domain); if (sym != NULL) return sym; - /* Search for name in namespaces imported to this and parent blocks. */ + /* Search for name in namespaces imported to this and parent + blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope, name, block, domain, 0, 1); + sym = cp_lookup_symbol_imports (scope, name, block, + domain, 0, 1); if (sym) return sym; @@ -481,7 +584,8 @@ lookup_namespace_scope (const char *name, new_scope_len += 2; } new_scope_len += cp_find_first_component (scope + new_scope_len); - sym = lookup_namespace_scope (name, block, domain, scope, new_scope_len); + sym = lookup_namespace_scope (name, block, domain, + scope, new_scope_len); if (sym != NULL) return sym; } @@ -492,7 +596,8 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_in_namespace (namespace, name, block, domain); + return cp_lookup_symbol_in_namespace (namespace, name, + block, domain); } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -574,24 +679,26 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, - nested_name, - block, - VAR_DOMAIN); + struct symbol *sym + = cp_lookup_symbol_in_namespace (parent_name, nested_name, + block, VAR_DOMAIN); char *concatenated_name; if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF) return SYMBOL_TYPE (sym); - /* Now search all static file-level symbols. Not strictly correct, - but more useful than an error. We do not try to guess any imported - namespace as even the fully specified namespace seach is is already - not C++ compliant and more assumptions could make it too magic. */ + /* Now search all static file-level symbols. Not strictly + correct, but more useful than an error. We do not try to + guess any imported namespace as even the fully specified + namespace seach is is already not C++ compliant and more + assumptions could make it too magic. */ concatenated_name = alloca (strlen (parent_name) + 2 + strlen (nested_name) + 1); - sprintf (concatenated_name, "%s::%s", parent_name, nested_name); - sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN); + sprintf (concatenated_name, "%s::%s", + parent_name, nested_name); + sym = lookup_static_symbol_aux (concatenated_name, + VAR_DOMAIN); if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF) return SYMBOL_TYPE (sym); @@ -599,7 +706,8 @@ cp_lookup_nested_type (struct type *parent_type, } default: internal_error (__FILE__, __LINE__, - _("cp_lookup_nested_type called on a non-aggregate type.")); + _("cp_lookup_nested_type called " + "on a non-aggregate type.")); } } @@ -608,7 +716,7 @@ cp_lookup_nested_type (struct type *parent_type, /* FIXME: carlton/2004-01-16: The problem that this is trying to address is that, unfortunately, sometimes NAME is wrong: it may not include the name of namespaces enclosing the type in question. - lookup_transparent_type gets called when the the type in question + lookup_transparent_type gets called when the type in question is a declaration, and we're trying to find its definition; but, for declarations, our type name deduction mechanism doesn't work. There's nothing we can do to fix this in general, I think, in the @@ -641,13 +749,13 @@ cp_lookup_transparent_type (const char *name) return cp_lookup_transparent_type_loop (name, scope, 0); } -/* Lookup the the type definition associated to NAME in - namespaces/classes containing SCOPE whose name is strictly longer - than LENGTH. LENGTH must be the index of the start of a - component of SCOPE. */ +/* Lookup the type definition associated to NAME in namespaces/classes + containing SCOPE whose name is strictly longer than LENGTH. LENGTH + must be the index of the start of a component of SCOPE. */ static struct type * -cp_lookup_transparent_type_loop (const char *name, const char *scope, +cp_lookup_transparent_type_loop (const char *name, + const char *scope, int length) { int scope_length = length + cp_find_first_component (scope + length); @@ -658,7 +766,8 @@ cp_lookup_transparent_type_loop (const char *name, const char *scope, if (scope[scope_length] == ':') { struct type *retval - = cp_lookup_transparent_type_loop (name, scope, scope_length + 2); + = cp_lookup_transparent_type_loop (name, scope, + scope_length + 2); if (retval != NULL) return retval; @@ -709,7 +818,7 @@ initialize_namespace_symtab (struct objfile *objfile) BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1; BLOCKVECTOR (namespace_symtab) = bv; - /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ bl = allocate_block (&objfile->objfile_obstack); BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack, @@ -775,7 +884,8 @@ free_namespace_block (struct symtab *symtab) it shouldn't consist solely of namespaces. */ void -cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile) +cp_check_possible_namespace_symbols (const char *name, + struct objfile *objfile) { check_possible_namespace_symbols_loop (name, cp_find_first_component (name), @@ -814,7 +924,8 @@ check_possible_namespace_symbols_loop (const char *name, int len, objfile); if (!done) - done = check_one_possible_namespace_symbol (name, len, objfile); + done = check_one_possible_namespace_symbol (name, len, + objfile); return done; } @@ -842,13 +953,15 @@ check_one_possible_namespace_symbol (const char *name, int len, { struct type *type; - type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile); + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + name_copy, objfile); TYPE_TAG_NAME (type) = TYPE_NAME (type); - sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol)); + sym = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct symbol)); memset (sym, 0, sizeof (struct symbol)); - SYMBOL_LANGUAGE (sym) = language_cplus; + SYMBOL_SET_LANGUAGE (sym, language_cplus); /* Note that init_type copied the name to the objfile's obstack. */ SYMBOL_SET_NAMES (sym, TYPE_NAME (type), len, 0, objfile); @@ -899,7 +1012,8 @@ maintenance_cplus_namespace (char *args, int from_tty) struct dict_iterator iter; struct symbol *sym; - ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym) + ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), + iter, sym) { printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); } @@ -912,7 +1026,8 @@ extern initialize_file_ftype _initialize_cp_namespace; void _initialize_cp_namespace (void) { - add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace, + add_cmd ("namespace", class_maintenance, + maintenance_cplus_namespace, _("Print the list of possible C++ namespaces."), &maint_cplus_cmd_list); } diff --git a/contrib/gdb-7/gdb/cp-support.c b/contrib/gdb-7/gdb/cp-support.c index ad1fb06bf0..a479067189 100644 --- a/contrib/gdb-7/gdb/cp-support.c +++ b/contrib/gdb-7/gdb/cp-support.c @@ -1,5 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -74,14 +74,15 @@ static void maint_cplus_command (char *arg, int from_tty); static void first_component_command (char *arg, int from_tty); /* Operator validation. - NOTE: Multi-byte operators (usually the assignment variety operator) - must appear before the single byte version, i.e., "+=" before "+". */ + NOTE: Multi-byte operators (usually the assignment variety + operator) must appear before the single byte version, i.e., "+=" + before "+". */ static const char *operator_tokens[] = { - "++", "+=", "+", "->*", "->", "--", "-=", "-", "*=", "*", "/=", "/", - "%=", "%", "!=", "==", "!", "&&", "<<=", "<<", ">>=", ">>", - "<=", "<", ">=", ">", "~", "&=", "&", "|=", "||", "|", "^=", "^", - "=", "()", "[]", ",", "new", "delete" + "++", "+=", "+", "->*", "->", "--", "-=", "-", "*=", "*", + "/=", "/", "%=", "%", "!=", "==", "!", "&&", "<<=", "<<", + ">>=", ">>", "<=", "<", ">=", ">", "~", "&=", "&", "|=", + "||", "|", "^=", "^", "=", "()", "[]", ",", "new", "delete" /* new[] and delete[] require special whitespace handling */ }; @@ -146,11 +147,11 @@ cp_canonicalize_string (const char *string) return ret; } -/* Convert a mangled name to a demangle_component tree. *MEMORY is set to the - block of used memory that should be freed when finished with the tree. - DEMANGLED_P is set to the char * that should be freed when finished with - the tree, or NULL if none was needed. OPTIONS will be passed to the - demangler. */ +/* Convert a mangled name to a demangle_component tree. *MEMORY is + set to the block of used memory that should be freed when finished + with the tree. DEMANGLED_P is set to the char * that should be + freed when finished with the tree, or NULL if none was needed. + OPTIONS will be passed to the demangler. */ static struct demangle_component * mangled_name_to_comp (const char *mangled_name, int options, @@ -163,7 +164,8 @@ mangled_name_to_comp (const char *mangled_name, int options, to trees. */ if (mangled_name[0] == '_' && mangled_name[1] == 'Z') { - ret = cplus_demangle_v3_components (mangled_name, options, memory); + ret = cplus_demangle_v3_components (mangled_name, + options, memory); if (ret) { *demangled_p = NULL; @@ -171,12 +173,14 @@ mangled_name_to_comp (const char *mangled_name, int options, } } - /* If it doesn't, or if that failed, then try to demangle the name. */ + /* If it doesn't, or if that failed, then try to demangle the + name. */ demangled_name = cplus_demangle (mangled_name, options); if (demangled_name == NULL) return NULL; - /* If we could demangle the name, parse it to build the component tree. */ + /* If we could demangle the name, parse it to build the component + tree. */ ret = cp_demangled_name_to_comp (demangled_name, NULL); if (ret == NULL) @@ -199,14 +203,15 @@ cp_class_name_from_physname (const char *physname) struct demangle_component *ret_comp, *prev_comp, *cur_comp; int done; - ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage, - &demangled_name); + ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, + &storage, &demangled_name); if (ret_comp == NULL) return NULL; done = 0; - /* First strip off any qualifiers, if we have a function or method. */ + /* First strip off any qualifiers, if we have a function or + method. */ while (!done) switch (ret_comp->type) { @@ -233,9 +238,9 @@ cp_class_name_from_physname (const char *physname) if (ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE) ret_comp = d_left (ret_comp); - /* What we have now should be a name, possibly qualified. Additional - qualifiers could live in the left subtree or the right subtree. Find - the last piece. */ + /* What we have now should be a name, possibly qualified. + Additional qualifiers could live in the left subtree or the right + subtree. Find the last piece. */ done = 0; prev_comp = NULL; cur_comp = ret_comp; @@ -266,7 +271,8 @@ cp_class_name_from_physname (const char *physname) { /* We want to discard the rightmost child of PREV_COMP. */ *prev_comp = *d_left (prev_comp); - /* The ten is completely arbitrary; we don't have a good estimate. */ + /* The ten is completely arbitrary; we don't have a good + estimate. */ ret = cp_comp_to_string (ret_comp, 10); } @@ -276,9 +282,10 @@ cp_class_name_from_physname (const char *physname) return ret; } -/* Return the child of COMP which is the basename of a method, variable, - et cetera. All scope qualifiers are discarded, but template arguments - will be included. The component tree may be modified. */ +/* Return the child of COMP which is the basename of a method, + variable, et cetera. All scope qualifiers are discarded, but + template arguments will be included. The component tree may be + modified. */ static struct demangle_component * unqualified_name_from_comp (struct demangle_component *comp) @@ -342,8 +349,8 @@ method_name_from_physname (const char *physname) char *demangled_name = NULL, *ret; struct demangle_component *ret_comp; - ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage, - &demangled_name); + ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, + &storage, &demangled_name); if (ret_comp == NULL) return NULL; @@ -351,7 +358,8 @@ method_name_from_physname (const char *physname) ret = NULL; if (ret_comp != NULL) - /* The ten is completely arbitrary; we don't have a good estimate. */ + /* The ten is completely arbitrary; we don't have a good + estimate. */ ret = cp_comp_to_string (ret_comp, 10); xfree (storage); @@ -551,7 +559,8 @@ cp_find_first_component_aux (const char *name, int permissive) case 'o': /* Operator names can screw up the recursion. */ if (operator_possible - && strncmp (name + index, "operator", LENGTH_OF_OPERATOR) == 0) + && strncmp (name + index, "operator", + LENGTH_OF_OPERATOR) == 0) { index += LENGTH_OF_OPERATOR; while (ISSPACE(name[index])) @@ -641,20 +650,22 @@ cp_entire_prefix_len (const char *name) /* Test to see if SYM is a symbol that we haven't seen corresponding to a function named OLOAD_NAME. If so, add it to the current - completion list. */ + completion list. */ static void -overload_list_add_symbol (struct symbol *sym, const char *oload_name) +overload_list_add_symbol (struct symbol *sym, + const char *oload_name) { int newsize; int i; char *sym_name; - /* If there is no type information, we can't do anything, so skip */ + /* If there is no type information, we can't do anything, so + skip. */ if (SYMBOL_TYPE (sym) == NULL) return; - /* skip any symbols that we've already considered. */ + /* skip any symbols that we've already considered. */ for (i = 0; i < sym_return_val_index; ++i) if (strcmp (SYMBOL_LINKAGE_NAME (sym), SYMBOL_LINKAGE_NAME (sym_return_val[i])) == 0) @@ -674,12 +685,13 @@ overload_list_add_symbol (struct symbol *sym, const char *oload_name) xfree (sym_name); - /* We have a match for an overload instance, so add SYM to the current list - * of overload instances */ + /* We have a match for an overload instance, so add SYM to the + current list of overload instances */ if (sym_return_val_index + 3 > sym_return_val_size) { newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *); - sym_return_val = (struct symbol **) xrealloc ((char *) sym_return_val, newsize); + sym_return_val = (struct symbol **) + xrealloc ((char *) sym_return_val, newsize); } sym_return_val[sym_return_val_index++] = sym; sym_return_val[sym_return_val_index] = NULL; @@ -766,16 +778,18 @@ make_symbol_overload_list_namespace (const char *func_name, /* Look in the static block. */ block = block_static_block (get_selected_block (0)); - make_symbol_overload_list_block (name, block); + if (block) + make_symbol_overload_list_block (name, block); /* Look in the global block. */ block = block_global_block (block); - make_symbol_overload_list_block (name, block); + if (block) + make_symbol_overload_list_block (name, block); } -/* Search the namespace of the given type and namespace of and public base - types. */ +/* Search the namespace of the given type and namespace of and public + base types. */ static void make_symbol_overload_list_adl_namespace (struct type *type, @@ -785,7 +799,8 @@ make_symbol_overload_list_adl_namespace (struct type *type, char *type_name; int i, prefix_len; - while (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF + while (TYPE_CODE (type) == TYPE_CODE_PTR + || TYPE_CODE (type) == TYPE_CODE_REF || TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_CODE (type) == TYPE_CODE_TYPEDEF) { @@ -816,13 +831,14 @@ make_symbol_overload_list_adl_namespace (struct type *type, for (i = 0; i < TYPE_N_BASECLASSES (type); i++) { if (BASETYPE_VIA_PUBLIC (type, i)) - make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i), + make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, + i), func_name); } } -/* Adds the the overload list overload candidates for FUNC_NAME found through - argument dependent lookup. */ +/* Adds the overload list overload candidates for FUNC_NAME found + through argument dependent lookup. */ struct symbol ** make_symbol_overload_list_adl (struct type **arg_types, int nargs, @@ -833,12 +849,14 @@ make_symbol_overload_list_adl (struct type **arg_types, int nargs, gdb_assert (sym_return_val_size != -1); for (i = 1; i <= nargs; i++) - make_symbol_overload_list_adl_namespace (arg_types[i - 1], func_name); + make_symbol_overload_list_adl_namespace (arg_types[i - 1], + func_name); return sym_return_val; } -/* Used for cleanups to reset the "searched" flag in case of an error. */ +/* Used for cleanups to reset the "searched" flag in case of an + error. */ static void reset_directive_searched (void *data) @@ -874,19 +892,22 @@ make_symbol_overload_list_using (const char *func_name, if (current->searched) continue; - /* If this is a namespace alias or imported declaration ignore it. */ + /* If this is a namespace alias or imported declaration ignore + it. */ if (current->alias != NULL || current->declaration != NULL) continue; if (strcmp (namespace, current->import_dest) == 0) { - /* Mark this import as searched so that the recursive call does - not search it again. */ + /* Mark this import as searched so that the recursive call + does not search it again. */ struct cleanup *old_chain; current->searched = 1; - old_chain = make_cleanup (reset_directive_searched, current); + old_chain = make_cleanup (reset_directive_searched, + current); - make_symbol_overload_list_using (func_name, current->import_src); + make_symbol_overload_list_using (func_name, + current->import_src); current->searched = 0; discard_cleanups (old_chain); @@ -911,8 +932,8 @@ make_symbol_overload_list_qualified (const char *func_name) struct dict_iterator iter; const struct dictionary *dict; - /* Look through the partial symtabs for all symbols which begin - by matching FUNC_NAME. Make sure we read that symbol table in. */ + /* Look through the partial symtabs for all symbols which begin by + matching FUNC_NAME. Make sure we read that symbol table in. */ ALL_OBJFILES (objfile) { @@ -949,7 +970,7 @@ make_symbol_overload_list_qualified (const char *func_name) } } -/* Lookup the rtti type for a class name. */ +/* Lookup the rtti type for a class name. */ struct type * cp_lookup_rtti_type (const char *name, struct block *block) @@ -997,8 +1018,11 @@ cp_lookup_rtti_type (const char *name, struct block *block) static void maint_cplus_command (char *arg, int from_tty) { - printf_unfiltered (_("\"maintenance cplus\" must be followed by the name of a command.\n")); - help_list (maint_cplus_cmd_list, "maintenance cplus ", -1, gdb_stdout); + printf_unfiltered (_("\"maintenance cplus\" must be followed " + "by the name of a command.\n")); + help_list (maint_cplus_cmd_list, + "maintenance cplus ", + -1, gdb_stdout); } /* This is a front end for cp_find_first_component, for unit testing. @@ -1034,7 +1058,8 @@ extern initialize_file_ftype _initialize_cp_support; /* -Wmissing-prototypes */ while (0) /* Returns the length of the operator name or 0 if INPUT does not - point to a valid C++ operator. INPUT should start with "operator". */ + point to a valid C++ operator. INPUT should start with + "operator". */ int cp_validate_operator (const char *input) { @@ -1053,13 +1078,15 @@ cp_validate_operator (const char *input) p += 8; SKIP_SPACE (p); - for (i = 0; i < sizeof (operator_tokens) / sizeof (operator_tokens[0]); + for (i = 0; + i < sizeof (operator_tokens) / sizeof (operator_tokens[0]); ++i) { int length = strlen (operator_tokens[i]); - /* By using strncmp here, we MUST have operator_tokens ordered! - See additional notes where operator_tokens is defined above. */ + /* By using strncmp here, we MUST have operator_tokens + ordered! See additional notes where operator_tokens is + defined above. */ if (strncmp (p, operator_tokens[i], length) == 0) { const char *op = p; @@ -1071,8 +1098,8 @@ cp_validate_operator (const char *input) || strncmp (op, "delete", 6) == 0) { - /* Special case: new[] and delete[]. We must be careful - to swallow whitespace before/in "[]". */ + /* Special case: new[] and delete[]. We must be + careful to swallow whitespace before/in "[]". */ SKIP_SPACE (p); if (*p == '[') @@ -1093,12 +1120,12 @@ cp_validate_operator (const char *input) /* Check input for a conversion operator. */ - /* Skip past base typename */ + /* Skip past base typename. */ while (*p != '*' && *p != '&' && *p != 0 && *p != ' ') ++p; SKIP_SPACE (p); - /* Add modifiers '*'/'&' */ + /* Add modifiers '*' / '&'. */ while (*p == '*' || *p == '&') { ++p; @@ -1130,12 +1157,19 @@ cp_validate_operator (const char *input) void _initialize_cp_support (void) { - add_prefix_cmd ("cplus", class_maintenance, maint_cplus_command, - _("C++ maintenance commands."), &maint_cplus_cmd_list, - "maintenance cplus ", 0, &maintenancelist); - add_alias_cmd ("cp", "cplus", class_maintenance, 1, &maintenancelist); - - add_cmd ("first_component", class_maintenance, first_component_command, + add_prefix_cmd ("cplus", class_maintenance, + maint_cplus_command, + _("C++ maintenance commands."), + &maint_cplus_cmd_list, + "maintenance cplus ", + 0, &maintenancelist); + add_alias_cmd ("cp", "cplus", + class_maintenance, 1, + &maintenancelist); + + add_cmd ("first_component", + class_maintenance, + first_component_command, _("Print the first class/namespace component of NAME."), &maint_cplus_cmd_list); } diff --git a/contrib/gdb-7/gdb/cp-support.h b/contrib/gdb-7/gdb/cp-support.h index ddc4c9377c..bb0ba398f0 100644 --- a/contrib/gdb-7/gdb/cp-support.h +++ b/contrib/gdb-7/gdb/cp-support.h @@ -1,5 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -36,14 +36,23 @@ struct objfile; struct type; struct demangle_component; +/* A string representing the name of the anonymous namespace used in GDB. */ + +#define CP_ANONYMOUS_NAMESPACE_STR "(anonymous namespace)" + +/* The length of the string representing the anonymous namespace. */ + +#define CP_ANONYMOUS_NAMESPACE_LEN 21 + /* This struct is designed to store data from using directives. It - says that names from namespace IMPORT_SRC should be visible within namespace - IMPORT_DEST. These form a linked list; NEXT is the next element of the - list. If the imported namespace or declaration has been aliased within the - IMPORT_DEST namespace, ALIAS is set to a string representing the alias. - Otherwise, ALIAS is NULL. DECLARATION is the name of the imported - declaration, if this import statement represents one. Otherwise DECLARATION - is NULL and this import statement represents a namespace. + says that names from namespace IMPORT_SRC should be visible within + namespace IMPORT_DEST. These form a linked list; NEXT is the next + element of the list. If the imported namespace or declaration has + been aliased within the IMPORT_DEST namespace, ALIAS is set to a + string representing the alias. Otherwise, ALIAS is NULL. + DECLARATION is the name of the imported declaration, if this import + statement represents one. Otherwise DECLARATION is NULL and this + import statement represents a namespace. C++: using namespace A; Fortran: use A @@ -66,15 +75,18 @@ struct demangle_component; import_dest = local scope of the import statement even such as "" alias = "LOCALNS" declaration = NULL - The namespace will get imported as the import_dest::LOCALNS namespace. + The namespace will get imported as the import_dest::LOCALNS + namespace. - C++ cannot express it, it would be something like: using localname = A::x; + C++ cannot express it, it would be something like: using localname + = A::x; Fortran: use A, only localname => x import_src = "A" import_dest = local scope of the import statement even such as "" alias = "localname" declaration = "x" - The declaration will get imported as localname or `import_dest`localname. */ + The declaration will get imported as localname or + `import_dest`localname. */ struct using_direct { @@ -86,7 +98,8 @@ struct using_direct struct using_direct *next; - /* Used during import search to temporarily mark this node as searched. */ + /* Used during import search to temporarily mark this node as + searched. */ int searched; }; @@ -158,6 +171,12 @@ extern struct symbol *cp_lookup_symbol_imports (const char *scope, const int declaration_only, const int search_parents); +extern struct symbol *cp_lookup_symbol_imports_or_template + (const char *scope, + const char *name, + const struct block *block, + const domain_enum domain); + extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, const struct block *block); diff --git a/contrib/gdb-7/gdb/cp-valprint.c b/contrib/gdb-7/gdb/cp-valprint.c index 5f47ec4d91..255e9ce223 100644 --- a/contrib/gdb-7/gdb/cp-valprint.c +++ b/contrib/gdb-7/gdb/cp-valprint.c @@ -1,7 +1,7 @@ /* Support for printing C++ values for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -37,8 +37,9 @@ #include "cp-support.h" #include "language.h" #include "python/python.h" +#include "exceptions.h" -/* Controls printing of vtbl's */ +/* Controls printing of vtbl's. */ static void show_vtblprint (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -62,9 +63,11 @@ Printing of object's derived type based on vtable info is %s.\n"), static void show_static_field_print (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) + struct cmd_list_element *c, + const char *value) { - fprintf_filtered (file, _("Printing of C++ static members is %s.\n"), + fprintf_filtered (file, + _("Printing of C++ static members is %s.\n"), value); } @@ -79,10 +82,12 @@ static void cp_print_static_field (struct type *, struct value *, struct ui_file *, int, const struct value_print_options *); -static void cp_print_value (struct type *, struct type *, const gdb_byte *, - int, CORE_ADDR, struct ui_file *, int, - const struct value *, - const struct value_print_options *, struct type **); +static void cp_print_value (struct type *, struct type *, + const gdb_byte *, int, + CORE_ADDR, struct ui_file *, + int, const struct value *, + const struct value_print_options *, + struct type **); /* GCC versions after 2.4.5 use this. */ @@ -105,19 +110,19 @@ cp_is_vtbl_ptr_type (struct type *type) int cp_is_vtbl_member (struct type *type) { - /* With older versions of g++, the vtbl field pointed to an array - of structures. Nowadays it points directly to the structure. */ + /* With older versions of g++, the vtbl field pointed to an array of + structures. Nowadays it points directly to the structure. */ if (TYPE_CODE (type) == TYPE_CODE_PTR) { type = TYPE_TARGET_TYPE (type); if (TYPE_CODE (type) == TYPE_CODE_ARRAY) { type = TYPE_TARGET_TYPE (type); - if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* if not using thunks */ - || TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* if not using thunks */ + || TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */ { /* Virtual functions tables are full of pointers - to virtual functions. */ + to virtual functions. */ return cp_is_vtbl_ptr_type (type); } } @@ -127,9 +132,10 @@ cp_is_vtbl_member (struct type *type) } else if (TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */ { - /* The type name of the thunk pointer is NULL when using dwarf2. - We could test for a pointer to a function, but there is - no type info for the virtual table either, so it wont help. */ + /* The type name of the thunk pointer is NULL when using + dwarf2. We could test for a pointer to a function, but + there is no type info for the virtual table either, so it + wont help. */ return cp_is_vtbl_ptr_type (type); } } @@ -137,24 +143,26 @@ cp_is_vtbl_member (struct type *type) } /* Mutually recursive subroutines of cp_print_value and c_val_print to - print out a structure's fields: cp_print_value_fields and cp_print_value. + print out a structure's fields: cp_print_value_fields and + cp_print_value. - TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and OPTIONS have the - same meanings as in cp_print_value and c_val_print. + TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and OPTIONS have the same + meanings as in cp_print_value and c_val_print. - 2nd argument REAL_TYPE is used to carry over the type of the derived - class across the recursion to base classes. + 2nd argument REAL_TYPE is used to carry over the type of the + derived class across the recursion to base classes. - DONT_PRINT is an array of baseclass types that we - should not print, or zero if called from top level. */ + DONT_PRINT is an array of baseclass types that we should not print, + or zero if called from top level. */ void cp_print_value_fields (struct type *type, struct type *real_type, - const gdb_byte *valaddr, int offset, CORE_ADDR address, - struct ui_file *stream, int recurse, - const struct value *val, + const gdb_byte *valaddr, int offset, + CORE_ADDR address, struct ui_file *stream, + int recurse, const struct value *val, const struct value_print_options *options, - struct type **dont_print_vb, int dont_print_statmem) + struct type **dont_print_vb, + int dont_print_statmem) { int i, len, n_baseclasses; int fields_seen = 0; @@ -164,12 +172,14 @@ cp_print_value_fields (struct type *type, struct type *real_type, if (recurse == 0) { - /* Any object can be left on obstacks only during an unexpected error. */ + /* Any object can be left on obstacks only during an unexpected + error. */ if (obstack_object_size (&dont_print_statmem_obstack) > 0) { obstack_free (&dont_print_statmem_obstack, NULL); - obstack_begin (&dont_print_statmem_obstack, 32 * sizeof (CORE_ADDR)); + obstack_begin (&dont_print_statmem_obstack, + 32 * sizeof (CORE_ADDR)); } if (obstack_object_size (&dont_print_stat_array_obstack) > 0) { @@ -187,8 +197,10 @@ cp_print_value_fields (struct type *type, struct type *real_type, duplicates of virtual baseclasses. */ if (n_baseclasses > 0) - cp_print_value (type, real_type, valaddr, offset, address, stream, - recurse + 1, val, options, dont_print_vb); + cp_print_value (type, real_type, valaddr, + offset, address, stream, + recurse + 1, val, options, + dont_print_vb); /* Second, print out data fields */ @@ -253,11 +265,13 @@ cp_print_value_fields (struct type *type, struct type *real_type, fputs_filtered ("\"( nodef \"", stream); if (field_is_static (&TYPE_FIELD (type, i))) fputs_filtered ("static ", stream); - fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), + fprintf_symbol_filtered (stream, + TYPE_FIELD_NAME (type, i), current_language->la_language, DMGL_PARAMS | DMGL_ANSI); fputs_filtered ("\" \"", stream); - fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), + fprintf_symbol_filtered (stream, + TYPE_FIELD_NAME (type, i), current_language->la_language, DMGL_PARAMS | DMGL_ANSI); fputs_filtered ("\") \"", stream); @@ -268,11 +282,13 @@ cp_print_value_fields (struct type *type, struct type *real_type, if (field_is_static (&TYPE_FIELD (type, i))) fputs_filtered ("static ", stream); - fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), + fprintf_symbol_filtered (stream, + TYPE_FIELD_NAME (type, i), current_language->la_language, DMGL_PARAMS | DMGL_ANSI); annotate_field_name_end (); - /* do not print leading '=' in case of anonymous unions */ + /* Do not print leading '=' in case of anonymous + unions. */ if (strcmp (TYPE_FIELD_NAME (type, i), "")) fputs_filtered (" = ", stream); annotate_field_value (); @@ -283,25 +299,33 @@ cp_print_value_fields (struct type *type, struct type *real_type, { struct value *v; - /* Bitfields require special handling, especially due to byte - order problems. */ + /* Bitfields require special handling, especially due to + byte order problems. */ if (TYPE_FIELD_IGNORE (type, i)) { fputs_filtered ("", stream); } - else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i), + else if (value_bits_synthetic_pointer (val, + TYPE_FIELD_BITPOS (type, + i), + TYPE_FIELD_BITSIZE (type, + i))) + { + fputs_filtered (_(""), stream); + } + else if (!value_bits_valid (val, + TYPE_FIELD_BITPOS (type, i), TYPE_FIELD_BITSIZE (type, i))) { - fputs_filtered (_(""), stream); + val_print_optimized_out (stream); } else { struct value_print_options opts = *options; opts.deref_ref = 0; - v = value_from_longest - (TYPE_FIELD_TYPE (type, i), - unpack_field_as_long (type, valaddr + offset, i)); + + v = value_field_bitfield (type, i, valaddr, offset, val); common_val_print (v, stream, recurse + 1, &opts, current_language); @@ -311,17 +335,19 @@ cp_print_value_fields (struct type *type, struct type *real_type, { if (TYPE_FIELD_IGNORE (type, i)) { - fputs_filtered ("", stream); + fputs_filtered ("", + stream); } else if (field_is_static (&TYPE_FIELD (type, i))) { struct value *v = value_static_field (type, i); if (v == NULL) - fputs_filtered ("", stream); + val_print_optimized_out (stream); else - cp_print_static_field (TYPE_FIELD_TYPE (type, i), v, - stream, recurse + 1, options); + cp_print_static_field (TYPE_FIELD_TYPE (type, i), + v, stream, recurse + 1, + options); } else { @@ -329,7 +355,8 @@ cp_print_value_fields (struct type *type, struct type *real_type, opts.deref_ref = 0; val_print (TYPE_FIELD_TYPE (type, i), - valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8, + valaddr, + offset + TYPE_FIELD_BITPOS (type, i) / 8, address, stream, recurse + 1, val, &opts, current_language); @@ -343,16 +370,17 @@ cp_print_value_fields (struct type *type, struct type *real_type, int obstack_final_size = obstack_object_size (&dont_print_statmem_obstack); - if (obstack_final_size > statmem_obstack_initial_size) { - /* In effect, a pop of the printed-statics stack. */ + if (obstack_final_size > statmem_obstack_initial_size) + { + /* In effect, a pop of the printed-statics stack. */ - void *free_to_ptr = - obstack_next_free (&dont_print_statmem_obstack) - - (obstack_final_size - statmem_obstack_initial_size); + void *free_to_ptr = + obstack_next_free (&dont_print_statmem_obstack) - + (obstack_final_size - statmem_obstack_initial_size); - obstack_free (&dont_print_statmem_obstack, - free_to_ptr); - } + obstack_free (&dont_print_statmem_obstack, + free_to_ptr); + } if (last_set_recurse != recurse) { @@ -362,8 +390,9 @@ cp_print_value_fields (struct type *type, struct type *real_type, if (obstack_final_size > stat_array_obstack_initial_size) { void *free_to_ptr = - obstack_next_free (&dont_print_stat_array_obstack) - - (obstack_final_size - stat_array_obstack_initial_size); + obstack_next_free (&dont_print_stat_array_obstack) + - (obstack_final_size + - stat_array_obstack_initial_size); obstack_free (&dont_print_stat_array_obstack, free_to_ptr); @@ -411,9 +440,9 @@ cp_print_value_fields_rtti (struct type *type, /* Ugh, we have to convert back to a value here. */ value = value_from_contents_and_address (type, valaddr + offset, address + offset); - /* We don't actually care about most of the result here -- just the - type. We already have the correct offset, due to how val_print - was initially called. */ + /* We don't actually care about most of the result here -- just + the type. We already have the correct offset, due to how + val_print was initially called. */ real_type = value_rtti_type (value, &full, &top, &using_enc); } @@ -425,14 +454,14 @@ cp_print_value_fields_rtti (struct type *type, dont_print_vb, dont_print_statmem); } -/* Special val_print routine to avoid printing multiple copies of virtual - baseclasses. */ +/* Special val_print routine to avoid printing multiple copies of + virtual baseclasses. */ static void cp_print_value (struct type *type, struct type *real_type, - const gdb_byte *valaddr, int offset, CORE_ADDR address, - struct ui_file *stream, int recurse, - const struct value *val, + const gdb_byte *valaddr, int offset, + CORE_ADDR address, struct ui_file *stream, + int recurse, const struct value *val, const struct value_print_options *options, struct type **dont_print_vb) { @@ -445,28 +474,30 @@ cp_print_value (struct type *type, struct type *real_type, if (dont_print_vb == 0) { - /* If we're at top level, carve out a completely fresh - chunk of the obstack and use that until this particular - invocation returns. */ + /* If we're at top level, carve out a completely fresh chunk of + the obstack and use that until this particular invocation + returns. */ /* Bump up the high-water mark. Now alpha is omega. */ obstack_finish (&dont_print_vb_obstack); } for (i = 0; i < n_baseclasses; i++) { - int boffset; + int boffset = 0; int skip; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); char *basename = TYPE_NAME (baseclass); - const gdb_byte *base_valaddr; + const gdb_byte *base_valaddr = NULL; + const struct value *base_val = NULL; + volatile struct gdb_exception ex; if (BASETYPE_VIA_VIRTUAL (type, i)) { struct type **first_dont_print = (struct type **) obstack_base (&dont_print_vb_obstack); - int j = (struct type **) obstack_next_free (&dont_print_vb_obstack) - - first_dont_print; + int j = (struct type **) + obstack_next_free (&dont_print_vb_obstack) - first_dont_print; while (--j >= 0) if (baseclass == first_dont_print[j]) @@ -478,52 +509,71 @@ cp_print_value (struct type *type, struct type *real_type, thisoffset = offset; thistype = real_type; - boffset = baseclass_offset (type, i, valaddr + offset, address + offset); - skip = ((boffset == -1) || (boffset + offset) < 0) ? 1 : -1; - - if (BASETYPE_VIA_VIRTUAL (type, i)) + TRY_CATCH (ex, RETURN_MASK_ERROR) { - /* The virtual base class pointer might have been - clobbered by the user program. Make sure that it - still points to a valid memory location. */ + boffset = baseclass_offset (type, i, valaddr, offset, address, val); + } + if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + skip = -1; + else if (ex.reason < 0) + skip = 1; + else + { + skip = 0; - if (boffset != -1 - && ((boffset + offset) < 0 - || (boffset + offset) >= TYPE_LENGTH (real_type))) + if (BASETYPE_VIA_VIRTUAL (type, i)) { - /* FIXME (alloca): unsafe if baseclass is really really large. */ - gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); - - base_valaddr = buf; - if (target_read_memory (address + boffset, buf, - TYPE_LENGTH (baseclass)) != 0) - skip = 1; - address = address + boffset; - thisoffset = 0; - boffset = 0; - thistype = baseclass; + /* The virtual base class pointer might have been + clobbered by the user program. Make sure that it + still points to a valid memory location. */ + + if ((boffset + offset) < 0 + || (boffset + offset) >= TYPE_LENGTH (real_type)) + { + /* FIXME (alloca): unsafe if baseclass is really + really large. */ + gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); + + if (target_read_memory (address + boffset, buf, + TYPE_LENGTH (baseclass)) != 0) + skip = 1; + base_val = value_from_contents_and_address (baseclass, + buf, + address + boffset); + thisoffset = 0; + boffset = 0; + thistype = baseclass; + base_valaddr = value_contents_for_printing_const (base_val); + } + else + { + base_valaddr = valaddr; + base_val = val; + } } else - base_valaddr = valaddr; + { + base_valaddr = valaddr; + base_val = val; + } } - else - base_valaddr = valaddr; - /* now do the printing */ + /* Now do the printing. */ if (options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } fputs_filtered ("<", stream); - /* Not sure what the best notation is in the case where there is no - baseclass name. */ + /* Not sure what the best notation is in the case where there is + no baseclass name. */ fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); - - if (skip >= 1) - fprintf_filtered (stream, ""); + if (skip < 0) + val_print_unavailable (stream); + else if (skip > 0) + val_print_invalid_address (stream); else { int result = 0; @@ -533,15 +583,17 @@ cp_print_value (struct type *type, struct type *real_type, if (!options->raw) result = apply_val_pretty_printer (baseclass, base_valaddr, thisoffset + boffset, - address, - stream, recurse, val, - options, - current_language); + value_address (base_val), + stream, recurse, base_val, + options, current_language); + + if (!result) cp_print_value_fields (baseclass, thistype, base_valaddr, - thisoffset + boffset, address, - stream, recurse, val, options, + thisoffset + boffset, + value_address (base_val), + stream, recurse, base_val, options, ((struct type **) obstack_base (&dont_print_vb_obstack)), 0); @@ -563,11 +615,10 @@ cp_print_value (struct type *type, struct type *real_type, } } -/* Print value of a static member. - To avoid infinite recursion when printing a class that contains - a static instance of the class, we keep the addresses of all printed - static member classes in an obstack and refuse to print them more - than once. +/* Print value of a static member. To avoid infinite recursion when + printing a class that contains a static instance of the class, we + keep the addresses of all printed static member classes in an + obstack and refuse to print them more than once. VAL contains the value to print, TYPE, STREAM, RECURSE, and OPTIONS have the same meanings as in c_val_print. */ @@ -610,8 +661,8 @@ cp_print_static_field (struct type *type, cp_print_value_fields (type, value_enclosing_type (val), value_contents_for_printing (val), value_embedded_offset (val), addr, - stream, recurse, - val, options, NULL, 1); + stream, recurse, val, + options, NULL, 1); return; } @@ -637,23 +688,25 @@ cp_print_static_field (struct type *type, } } - obstack_grow (&dont_print_stat_array_obstack, (char *) &target_type, + obstack_grow (&dont_print_stat_array_obstack, + (char *) &target_type, sizeof (struct type *)); } opts = *options; opts.deref_ref = 0; val_print (type, value_contents_for_printing (val), - value_embedded_offset (val), value_address (val), - stream, recurse, - val, &opts, current_language); + value_embedded_offset (val), + value_address (val), + stream, recurse, val, + &opts, current_language); } -/* Find the field in *DOMAIN, or its non-virtual base classes, with bit offset - OFFSET. Set *DOMAIN to the containing type and *FIELDNO to the containing - field number. If OFFSET is not exactly at the start of some field, set - *DOMAIN to NULL. */ +/* Find the field in *DOMAIN, or its non-virtual base classes, with + bit offset OFFSET. Set *DOMAIN to the containing type and *FIELDNO + to the containing field number. If OFFSET is not exactly at the + start of some field, set *DOMAIN to NULL. */ static void cp_find_class_member (struct type **domain_p, int *fieldno, @@ -708,7 +761,9 @@ cp_print_class_member (const gdb_byte *valaddr, struct type *type, LONGEST val; unsigned int fieldno; - val = extract_signed_integer (valaddr, TYPE_LENGTH (type), byte_order); + val = extract_signed_integer (valaddr, + TYPE_LENGTH (type), + byte_order); /* Pointers to data members are usually byte offsets into an object. Because a data member can have offset zero, and a NULL pointer to @@ -773,7 +828,10 @@ Show printing of object's derived type based on vtable info."), NULL, show_objectprint, &setprintlist, &showprintlist); - obstack_begin (&dont_print_stat_array_obstack, 32 * sizeof (struct type *)); - obstack_begin (&dont_print_statmem_obstack, 32 * sizeof (CORE_ADDR)); - obstack_begin (&dont_print_vb_obstack, 32 * sizeof (struct type *)); + obstack_begin (&dont_print_stat_array_obstack, + 32 * sizeof (struct type *)); + obstack_begin (&dont_print_statmem_obstack, + 32 * sizeof (CORE_ADDR)); + obstack_begin (&dont_print_vb_obstack, + 32 * sizeof (struct type *)); } diff --git a/contrib/gdb-7/gdb/d-lang.c b/contrib/gdb-7/gdb/d-lang.c index 8ef47c7cec..c0599a5aa7 100644 --- a/contrib/gdb-7/gdb/d-lang.c +++ b/contrib/gdb-7/gdb/d-lang.c @@ -1,6 +1,7 @@ /* D language support routines for GDB, the GNU debugger. - Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -252,7 +253,8 @@ static const struct language_defn d_language_defn = c_printstr, /* Function to print string constant. */ c_emit_char, /* Print a single char. */ c_print_type, /* Print a type using appropriate syntax. */ - c_print_typedef, /* Print a typedef using appropriate syntax. */ + c_print_typedef, /* Print a typedef using appropriate + syntax. */ d_val_print, /* Print a value using appropriate syntax. */ c_value_print, /* Print a top-level value. */ NULL, /* Language specific skip_trampoline. */ @@ -260,7 +262,8 @@ static const struct language_defn d_language_defn = basic_lookup_symbol_nonlocal, basic_lookup_transparent_type, d_demangle, /* Language specific symbol demangler. */ - NULL, /* Language specific class_name_from_physname. */ + NULL, /* Language specific + class_name_from_physname. */ d_op_print_tab, /* Expression operators for printing. */ 1, /* C-style arrays. */ 0, /* String lower bound. */ diff --git a/contrib/gdb-7/gdb/d-lang.h b/contrib/gdb-7/gdb/d-lang.h index c2ec728514..69883ecae3 100644 --- a/contrib/gdb-7/gdb/d-lang.h +++ b/contrib/gdb-7/gdb/d-lang.h @@ -1,6 +1,7 @@ /* D language support definitions for GDB, the GNU debugger. - Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/d-valprint.c b/contrib/gdb-7/gdb/d-valprint.c index 87edddb3cd..e8430995e9 100644 --- a/contrib/gdb-7/gdb/d-valprint.c +++ b/contrib/gdb-7/gdb/d-valprint.c @@ -1,6 +1,6 @@ /* Support for printing D values for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -45,8 +45,7 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr, struct type *elttype; struct type *true_type; struct type *ptr_type; - const gdb_byte *ptraddr; - struct value *val; + struct value *ival; int length; length = unpack_field_as_long (type, valaddr + embedded_offset, 0); @@ -59,11 +58,12 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr, true_type = check_typedef (elttype); true_type = lookup_array_range_type (true_type, 0, length - 1); - val = value_at (true_type, addr); - ptraddr = value_contents (val); + ival = value_at (true_type, addr); - return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1, - NULL, options); + return d_val_print (true_type, + value_contents_for_printing (ival), + value_embedded_offset (ival), addr, + stream, recurse + 1, ival, options); } return -1; } diff --git a/contrib/gdb-7/gdb/data-directory/Makefile.in b/contrib/gdb-7/gdb/data-directory/Makefile.in new file mode 100644 index 0000000000..11cf2e6736 --- /dev/null +++ b/contrib/gdb-7/gdb/data-directory/Makefile.in @@ -0,0 +1,219 @@ +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# Makefile for building a staged copy of the data-directory. +# This file is part of GDB. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +srcdir = @srcdir@ +SYSCALLS_SRCDIR = $(srcdir)/../syscalls +PYTHON_SRCDIR = $(srcdir)/../python/lib +VPATH = $(srcdir):$(SYSCALLS_SRCDIR):$(PYTHON_SRCDIR) + +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +datarootdir = @datarootdir@ +datadir = @datadir@ + +SHELL = @SHELL@ + +LN_S = @LN_S@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_DIR = $(SHELL) $(srcdir)/../../mkinstalldirs + +GDB_DATADIR = @GDB_DATADIR@ + +SYSCALLS_DIR = syscalls +SYSCALLS_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(SYSCALLS_DIR) +SYSCALLS_FILES = \ + gdb-syscalls.dtd \ + ppc-linux.xml ppc64-linux.xml \ + i386-linux.xml amd64-linux.xml \ + sparc-linux.xml sparc64-linux.xml \ + mips-o32-linux.xml mips-n32-linux.xml mips-n64-linux.xml + +PYTHON_DIR = python +PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR) +PYTHON_FILES = \ + gdb/__init__.py \ + gdb/types.py \ + gdb/printing.py \ + gdb/command/__init__.py \ + gdb/command/pretty_printers.py + +FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "infodir=$(infodir)" \ + "datarootdir=$(datarootdir)" \ + "docdir=$(docdir)" \ + "htmldir=$(htmldir)" \ + "pdfdir=$(pdfdir)" \ + "libdir=$(libdir)" \ + "mandir=$(mandir)" \ + "datadir=$(datadir)" \ + "includedir=$(includedir)" \ + "against=$(against)" \ + "DESTDIR=$(DESTDIR)" \ + "AR=$(AR)" \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "CXX=$(CXX)" \ + "CXXFLAGS=$(CXXFLAGS)" \ + "DLLTOOL=$(DLLTOOL)" \ + "LDFLAGS=$(LDFLAGS)" \ + "RANLIB=$(RANLIB)" \ + "MAKEINFO=$(MAKEINFO)" \ + "MAKEHTML=$(MAKEHTML)" \ + "MAKEHTMLFLAGS=$(MAKEHTMLFLAGS)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "RUNTEST=$(RUNTEST)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" + +.PHONY: all +all: stamp-syscalls stamp-python + +# For portability's sake, we need to handle systems that don't have +# symbolic links. +stamp-syscalls: Makefile $(SYSCALLS_FILES) + rm -rf ./$(SYSCALLS_DIR) + mkdir ./$(SYSCALLS_DIR) + files='$(SYSCALLS_FILES)' ; \ + for file in $$files ; do \ + f=$(SYSCALLS_SRCDIR)/$$file ; \ + if test -f $$f ; then \ + $(INSTALL_DATA) $$f ./$(SYSCALLS_DIR) ; \ + fi ; \ + done + touch $@ + +.PHONY: clean-syscalls +clean-syscalls: + rm -rf $(SYSCALLS_DIR) + rm -f stamp-syscalls + +# This target is responsible for properly installing the syscalls' +# XML files in the system. +.PHONY: install-syscalls +install-syscalls: + $(INSTALL_DIR) $(SYSCALLS_INSTALL_DIR) + files='$(SYSCALLS_FILES)' ; \ + for file in $$files; do \ + f=$(SYSCALLS_SRCDIR)/$$file ; \ + if test -f $$f ; then \ + $(INSTALL_DATA) $$f $(SYSCALLS_INSTALL_DIR) ; \ + fi ; \ + done + +.PHONY: uninstall-syscalls +uninstall-syscalls: + files='$(SYSCALLS_FILES)' ; \ + for file in $$files ; do \ + slashdir=`echo "/$$file" | sed 's,/[^/]*$$,,'` ; \ + rm -f $(SYSCALLS_INSTALL_DIR)/$$file ; \ + while test "x$$file" != "x$$slashdir" ; do \ + rmdir 2>/dev/null "$(SYSCALLS_INSTALL_DIR)$$slashdir" ; \ + file="$$slashdir" ; \ + slashdir=`echo "$$file" | sed 's,/[^/]*$$,,'` ; \ + done \ + done + +stamp-python: Makefile $(PYTHON_FILES) + rm -rf ./$(PYTHON_DIR) + files='$(PYTHON_FILES)' ; \ + for file in $$files ; do \ + dir=`echo "$$file" | sed 's,/[^/]*$$,,'` ; \ + $(INSTALL_DIR) ./$(PYTHON_DIR)/$$dir ; \ + $(INSTALL_DATA) $(PYTHON_SRCDIR)/$$file ./$(PYTHON_DIR)/$$dir ; \ + done + touch $@ + +.PHONY: clean-python +clean-python: + rm -rf $(PYTHON_DIR) + rm -f stamp-python + +.PHONY: install-python +install-python: + files='$(PYTHON_FILES)' ; \ + for file in $$files ; do \ + dir=`echo "$$file" | sed 's,/[^/]*$$,,'` ; \ + $(INSTALL_DIR) $(PYTHON_INSTALL_DIR)/$$dir ; \ + $(INSTALL_DATA) ./$(PYTHON_DIR)/$$file $(PYTHON_INSTALL_DIR)/$$dir ; \ + done + +.PHONY: uninstall-python +uninstall-python: + files='$(PYTHON_FILES)' ; \ + for file in $$files ; do \ + slashdir=`echo "/$$file" | sed 's,/[^/]*$$,,'` ; \ + rm -f $(PYTHON_INSTALL_DIR)/$$file ; \ + while test "x$$file" != "x$$slashdir" ; do \ + rmdir 2>/dev/null "$(PYTHON_INSTALL_DIR)$$slashdir" ; \ + file="$$slashdir" ; \ + slashdir=`echo "$$file" | sed 's,/[^/]*$$,,'` ; \ + done \ + done + +# Traditionally "install" depends on "all". But it may be useful +# not to; for example, if the user has made some trivial change to a +# source file and doesn't care about rebuilding or just wants to save the +# time it takes for make to check that all is up to date. +# install-only is intended to address that need. +.PHONY: install +install: all + @$(MAKE) $(FLAGS_TO_PASS) install-only + +.PHONY: install-only +install-only: install-syscalls install-python + +.PHONY: uninstall +uninstall: uninstall-syscalls uninstall-python + +.PHONY: clean +clean: clean-syscalls clean-python + +.PHONY: maintainer-clean realclean distclean +maintainer-clean realclean distclean: clean + rm -f Makefile + +.PHONY: check installcheck info dvi pdf html +.PHONY: install-info install-pdf install-html clean-info +check installcheck: +info dvi pdf html: +install-info install-pdf install-html: +clean-info: + +# GNU Make has an annoying habit of putting *all* the Makefile variables +# into the environment, unless you include this target as a circumvention. +# Rumor is that this will be fixed (and this target can be removed) +# in GNU Make 4.0. +.NOEXPORT: + +# GNU Make 3.63 has a different problem: it keeps tacking command line +# overrides onto the definition of $(MAKE). This variable setting +# will remove them. +MAKEOVERRIDES= + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(MAKE) data-directory/Makefile diff --git a/contrib/gdb-7/gdb/dbxread.c b/contrib/gdb-7/gdb/dbxread.c index 25bf07b5af..51ddd9da87 100644 --- a/contrib/gdb-7/gdb/dbxread.c +++ b/contrib/gdb-7/gdb/dbxread.c @@ -47,6 +47,7 @@ #include "target.h" #include "gdbcore.h" /* for bfd stuff */ #include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */ +#include "filenames.h" #include "objfiles.h" #include "buildsym.h" #include "stabsread.h" @@ -61,7 +62,8 @@ #include "gdb_string.h" #include "aout/aout64.h" -#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */ +#include "aout/stab_gnu.h" /* We always use GNU stabs, not + native, now. */ /* We put a pointer to this structure in the read_symtab_private field @@ -103,7 +105,7 @@ struct symloc #define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset) -/* Remember what we deduced to be the source language of this psymtab. */ +/* Remember what we deduced to be the source language of this psymtab. */ static enum language psymtab_language = language_unknown; @@ -117,11 +119,11 @@ static bfd *symfile_bfd; static unsigned symbol_size; -/* This is the offset of the symbol table in the executable file. */ +/* This is the offset of the symbol table in the executable file. */ static unsigned symbol_table_offset; -/* This is the offset of the string table in the executable file. */ +/* This is the offset of the string table in the executable file. */ static unsigned string_table_offset; @@ -129,14 +131,14 @@ static unsigned string_table_offset; into the string table. Instead, each .o file has a base offset in the string table, and the associated symbols contain offsets from this base. The following two variables contain the base offset for - the current and next .o files. */ + the current and next .o files. */ static unsigned int file_string_table_offset; static unsigned int next_file_string_table_offset; /* .o and NLM files contain unrelocated addresses which are based at 0. When non-zero, this flag disables some of the special cases for - Solaris elf+stab text addresses at location 0. */ + Solaris elf+stab text addresses at location 0. */ static int symfile_relocatable = 0; @@ -177,8 +179,8 @@ static void repeated_header_complaint (const char *arg1, int arg2) { complaint (&symfile_complaints, - _("\"repeated\" header file %s not previously seen, at symtab \ -pos %d"), + _("\"repeated\" header file %s not " + "previously seen, at symtab pos %d"), arg1, arg2); } @@ -233,21 +235,21 @@ find_text_range (bfd * sym_bfd, struct objfile *objfile) /* During initial symbol readin, we need to have a structure to keep track of which psymtabs have which bincls in them. This structure is used during readin to setup the list of dependencies within each - partial symbol table. */ + partial symbol table. */ struct header_file_location { char *name; /* Name of header file */ int instance; /* See above */ struct partial_symtab *pst; /* Partial symtab that has the - BINCL/EINCL defs for this file */ + BINCL/EINCL defs for this file. */ }; -/* The actual list and controling variables */ +/* The actual list and controling variables. */ static struct header_file_location *bincl_list, *next_bincl; static int bincls_allocated; -/* Local function prototypes */ +/* Local function prototypes. */ extern void _initialize_dbxread (void); @@ -294,7 +296,7 @@ static struct partial_symtab *start_psymtab (struct objfile *, char *, struct partial_symbol **, struct partial_symbol **); -/* Free up old header file tables */ +/* Free up old header file tables. */ void free_header_files (void) @@ -307,7 +309,7 @@ free_header_files (void) n_allocated_this_object_header_files = 0; } -/* Allocate new header file tables */ +/* Allocate new header file tables. */ void init_header_files (void) @@ -345,7 +347,7 @@ add_old_header_file (char *name, int instance) int i; for (i = 0; i < N_HEADER_FILES (current_objfile); i++) - if (strcmp (p[i].name, name) == 0 && instance == p[i].instance) + if (filename_cmp (p[i].name, name) == 0 && instance == p[i].instance) { add_this_object_header_file (i); return; @@ -568,7 +570,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags) init_minimal_symbol_collection (); make_cleanup_discard_minimal_symbols (); - /* Read stabs data from executable file and define symbols. */ + /* Read stabs data from executable file and define symbols. */ read_dbx_symtab (objfile); @@ -577,7 +579,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags) read_dbx_dynamic_symtab (objfile); /* Install any minimal symbols that have been collected as the current - minimal symbols for this objfile. */ + minimal symbols for this objfile. */ install_minimal_symbols (objfile); @@ -607,7 +609,7 @@ dbx_new_init (struct objfile *ignore) Since BFD doesn't know how to read debug symbols in a format-independent way (and may never do so...), we have to do it ourselves. We will never - be called unless this is an a.out (or very similar) file. + be called unless this is an a.out (or very similar) file. FIXME, there should be a cleaner peephole into the BFD environment here. */ #define DBX_STRINGTAB_SIZE_SIZE sizeof(long) /* FIXME */ @@ -621,7 +623,7 @@ dbx_symfile_init (struct objfile *objfile) asection *text_sect; unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE]; - /* Allocate struct to keep track of the symfile */ + /* Allocate struct to keep track of the symfile. */ objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *) xmalloc (sizeof (struct dbx_symfile_info)); memset (objfile->deprecated_sym_stab_info, 0, @@ -631,11 +633,11 @@ dbx_symfile_init (struct objfile *objfile) DBX_DATA_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".data"); DBX_BSS_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".bss"); - /* FIXME POKING INSIDE BFD DATA STRUCTURES */ + /* FIXME POKING INSIDE BFD DATA STRUCTURES. */ #define STRING_TABLE_OFFSET (sym_bfd->origin + obj_str_filepos (sym_bfd)) #define SYMBOL_TABLE_OFFSET (sym_bfd->origin + obj_sym_filepos (sym_bfd)) - /* FIXME POKING INSIDE BFD DATA STRUCTURES */ + /* FIXME POKING INSIDE BFD DATA STRUCTURES. */ DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL; @@ -660,13 +662,13 @@ dbx_symfile_init (struct objfile *objfile) however at least check to see if the size is less than the size of the size field itself, or larger than the size of the entire file. Note that all valid string tables have a size greater than zero, since - the bytes used to hold the size are included in the count. */ + the bytes used to hold the size are included in the count. */ if (STRING_TABLE_OFFSET == 0) { /* It appears that with the existing bfd code, STRING_TABLE_OFFSET will never be zero, even when there is no string table. This - would appear to be a bug in bfd. */ + would appear to be a bug in bfd. */ DBX_STRINGTAB_SIZE (objfile) = 0; DBX_STRINGTAB (objfile) = NULL; } @@ -686,7 +688,7 @@ dbx_symfile_init (struct objfile *objfile) { /* With the existing bfd code, STRING_TABLE_OFFSET will be set to EOF if there is no string table, and attempting to read the size - from EOF will read zero bytes. */ + from EOF will read zero bytes. */ DBX_STRINGTAB_SIZE (objfile) = 0; DBX_STRINGTAB (objfile) = NULL; } @@ -698,7 +700,7 @@ dbx_symfile_init (struct objfile *objfile) the minimum is DBX_STRINGTAB_SIZE_SIZE. If we just read some random data that happened to be at STRING_TABLE_OFFSET, because bfd can't tell us there is no string table, the sanity checks may - or may not catch this. */ + or may not catch this. */ DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp); if (DBX_STRINGTAB_SIZE (objfile) < sizeof (size_temp) @@ -728,7 +730,7 @@ dbx_symfile_init (struct objfile *objfile) /* Perform any local cleanups required when we are done with a particular objfile. I.E, we are in the process of discarding all symbol information for an objfile, freeing up all memory held for it, and unlinking the - objfile struct from the global list of known objfiles. */ + objfile struct from the global list of known objfiles. */ static void dbx_symfile_finish (struct objfile *objfile) @@ -968,7 +970,8 @@ set_namestring (struct objfile *objfile, const struct internal_nlist *nlist) >= DBX_STRINGTAB_SIZE (objfile) || nlist->n_strx + file_string_table_offset < nlist->n_strx) { - complaint (&symfile_complaints, _("bad string table offset in symbol %d"), + complaint (&symfile_complaints, + _("bad string table offset in symbol %d"), symnum); namestring = ""; } @@ -1125,7 +1128,7 @@ read_dbx_dynamic_symtab (struct objfile *objfile) } static CORE_ADDR -find_stab_function_addr (char *namestring, char *filename, +find_stab_function_addr (char *namestring, const char *filename, struct objfile *objfile) { struct minimal_symbol *msym; @@ -1153,13 +1156,13 @@ find_stab_function_addr (char *namestring, char *filename, if (msym == NULL && filename != NULL) { - /* Try again without the filename. */ + /* Try again without the filename. */ p[n] = 0; msym = lookup_minimal_symbol (p, NULL, objfile); } if (msym == NULL && filename != NULL) { - /* And try again for Sun Fortran, but without the filename. */ + /* And try again for Sun Fortran, but without the filename. */ p[n] = '_'; p[n + 1] = 0; msym = lookup_minimal_symbol (p, NULL, objfile); @@ -1172,19 +1175,19 @@ static void function_outside_compilation_unit_complaint (const char *arg1) { complaint (&symfile_complaints, - _("function `%s' appears to be defined outside of all compilation \ -units"), + _("function `%s' appears to be defined " + "outside of all compilation units"), arg1); } /* Setup partial_symtab's describing each source file for which - debugging information is available. */ + debugging information is available. */ static void read_dbx_symtab (struct objfile *objfile) { struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch */ + struct external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch. */ struct internal_nlist nlist; CORE_ADDR text_addr; int text_size; @@ -1201,15 +1204,15 @@ read_dbx_symtab (struct objfile *objfile) int textlow_not_set; int data_sect_index; - /* Current partial symtab */ + /* Current partial symtab. */ struct partial_symtab *pst; - /* List of current psymtab's include files */ + /* List of current psymtab's include files. */ char **psymtab_include_list; int includes_allocated; int includes_used; - /* Index within current psymtab dependency list */ + /* Index within current psymtab dependency list. */ struct partial_symtab **dependency_list; int dependencies_used, dependencies_allocated; @@ -1244,7 +1247,7 @@ read_dbx_symtab (struct objfile *objfile) lowest_text_address = (CORE_ADDR) -1; - symfile_bfd = objfile->obfd; /* For next_text_symbol */ + symfile_bfd = objfile->obfd; /* For next_text_symbol. */ abfd = objfile->obfd; symbuf_end = symbuf_idx = 0; next_symbol_text_func = dbx_next_symbol_text; @@ -1285,8 +1288,8 @@ read_dbx_symtab (struct objfile *objfile) for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++) { - /* Get the symbol for this run and pull out some info */ - QUIT; /* allow this to be interruptable */ + /* Get the symbol for this run and pull out some info. */ + QUIT; /* Allow this to be interruptable. */ if (symbuf_idx == symbuf_end) fill_symbuf (abfd); bufp = &symbuf[symbuf_idx++]; @@ -1310,10 +1313,9 @@ read_dbx_symtab (struct objfile *objfile) *) The assignment to namestring. *) The call to strchr. - *) The addition of a partial symbol the the two partial + *) The addition of a partial symbol the two partial symbol lists. This last is a large section of code, so - I've imbedded it in the following macro. - */ + I've imbedded it in the following macro. */ switch (nlist.n_type) { @@ -1350,7 +1352,7 @@ read_dbx_symtab (struct objfile *objfile) nlist.n_type, objfile); /* Always */ continue; - /* Standard, local, non-debugger, symbols */ + /* Standard, local, non-debugger, symbols. */ case N_NBTEXT: @@ -1400,23 +1402,16 @@ read_dbx_symtab (struct objfile *objfile) goto record_it; case N_UNDF | N_EXT: - if (nlist.n_value != 0) - { - /* This is a "Fortran COMMON" symbol. See if the target - environment knows where it has been relocated to. */ - - CORE_ADDR reladdr; - - namestring = set_namestring (objfile, &nlist); - if (target_lookup_symbol (namestring, &reladdr)) - { - continue; /* Error in lookup; ignore symbol for now. */ - } - nlist.n_type ^= (N_BSS ^ N_UNDF); /* Define it as a bss-symbol */ - nlist.n_value = reladdr; - goto bss_ext_symbol; - } - continue; /* Just undefined, not COMMON */ + /* The case (nlist.n_value != 0) is a "Fortran COMMON" symbol. + We used to rely on the target to tell us whether it knows + where the symbol has been relocated to, but none of the + target implementations actually provided that operation. + So we just ignore the symbol, the same way we would do if + we had a target-side symbol lookup which returned no match. + + All other symbols (with nlist.n_value == 0), are really + undefined, and so we ignore them too. */ + continue; case N_UNDF: if (processing_acc_compilation && nlist.n_strx == 1) @@ -1444,7 +1439,7 @@ read_dbx_symtab (struct objfile *objfile) case N_NBBSS: continue; - /* Keep going . . . */ + /* Keep going . . . */ /* * Special symbol types for GNU @@ -1471,7 +1466,7 @@ read_dbx_symtab (struct objfile *objfile) CORE_ADDR valu; static int prev_so_symnum = -10; static int first_so_symnum; - char *p; + const char *p; static char *dirname_nso; int prev_textlow_not_set; @@ -1481,7 +1476,7 @@ read_dbx_symtab (struct objfile *objfile) prev_textlow_not_set = textlow_not_set; /* A zero value is probably an indication for the SunPRO 3.0 - compiler. end_psymtab explicitly tests for zero, so + compiler. end_psymtab explicitly tests for zero, so don't relocate it. */ if (nlist.n_value == 0 @@ -1496,7 +1491,7 @@ read_dbx_symtab (struct objfile *objfile) past_first_source_file = 1; if (prev_so_symnum != symnum - 1) - { /* Here if prev stab wasn't N_SO */ + { /* Here if prev stab wasn't N_SO. */ first_so_symnum = symnum; if (pst) @@ -1515,24 +1510,24 @@ read_dbx_symtab (struct objfile *objfile) prev_so_symnum = symnum; - /* End the current partial symtab and start a new one */ + /* End the current partial symtab and start a new one. */ namestring = set_namestring (objfile, &nlist); - /* Null name means end of .o file. Don't start a new one. */ + /* Null name means end of .o file. Don't start a new one. */ if (*namestring == '\000') continue; /* Some compilers (including gcc) emit a pair of initial N_SOs. The first one is a directory name; the second the file name. If pst exists, is empty, and has a filename ending in '/', - we assume the previous N_SO was a directory name. */ + we assume the previous N_SO was a directory name. */ - p = strrchr (namestring, '/'); - if (p && *(p + 1) == '\000') + p = lbasename (namestring); + if (p != namestring && *p == '\000') { /* Save the directory name SOs locally, then save it into - the psymtab when it's created below. */ + the psymtab when it's created below. */ dirname_nso = namestring; continue; } @@ -1560,7 +1555,7 @@ read_dbx_symtab (struct objfile *objfile) /* Add this bincl to the bincl_list for future EXCLs. No need to save the string; it'll be around until - read_dbx_symtab function returns */ + read_dbx_symtab function returns. */ namestring = set_namestring (objfile, &nlist); tmp_language = deduce_language_from_filename (namestring); @@ -1579,14 +1574,14 @@ read_dbx_symtab (struct objfile *objfile) /* FIXME: we should not get here without a PST to work on. Attempt to recover. */ complaint (&symfile_complaints, - _("N_BINCL %s not in entries for any file, at symtab \ -pos %d"), + _("N_BINCL %s not in entries for " + "any file, at symtab pos %d"), namestring, symnum); continue; } add_bincl_to_list (pst, namestring, nlist.n_value); - /* Mark down an include file in the current psymtab */ + /* Mark down an include file in the current psymtab. */ goto record_include_file; } @@ -1595,7 +1590,7 @@ pos %d"), { enum language tmp_language; - /* Mark down an include file in the current psymtab */ + /* Mark down an include file in the current psymtab. */ namestring = set_namestring (objfile, &nlist); tmp_language = deduce_language_from_filename (namestring); @@ -1610,7 +1605,7 @@ pos %d"), /* In C++, one may expect the same filename to come round many times, when code is coming alternately from the main file - and from inline functions in other files. So I check to see + and from inline functions in other files. So I check to see if this is a file we've seen before -- either the main source file, or a previously included file. @@ -1618,13 +1613,13 @@ pos %d"), things like "break c-exp.y:435" need to work (I suppose the psymtab_include_list could be hashed or put in a binary tree, if profiling shows this is a major hog). */ - if (pst && strcmp (namestring, pst->filename) == 0) + if (pst && filename_cmp (namestring, pst->filename) == 0) continue; { int i; for (i = 0; i < includes_used; i++) - if (strcmp (namestring, psymtab_include_list[i]) == 0) + if (filename_cmp (namestring, psymtab_include_list[i]) == 0) { i = -1; break; @@ -1647,8 +1642,8 @@ pos %d"), } continue; } - case N_LSYM: /* Typedef or automatic variable. */ - case N_STSYM: /* Data seg var -- static */ + case N_LSYM: /* Typedef or automatic variable. */ + case N_STSYM: /* Data seg var -- static. */ case N_LCSYM: /* BSS " */ case N_ROSYM: /* Read-only data seg var -- static. */ case N_NBSTS: /* Gould nobase. */ @@ -1662,7 +1657,7 @@ pos %d"), case N_PC: /* I may or may not need this; I suspect not. */ - case N_M2C: /* I suspect that I can ignore this here. */ + case N_M2C: /* I suspect that I can ignore this here. */ case N_SCOPE: /* Same. */ { char *p; @@ -1685,7 +1680,7 @@ pos %d"), p = (char *) strchr (namestring, ':'); if (!p) - continue; /* Not a debugging symbol. */ + continue; /* Not a debugging symbol. */ sym_len = 0; sym_name = NULL; /* pacify "gcc -Werror" */ @@ -1726,8 +1721,7 @@ pos %d"), data_sect_index); if (gdbarch_static_transform_name_p (gdbarch)) - namestring = gdbarch_static_transform_name (gdbarch, - namestring); + gdbarch_static_transform_name (gdbarch, namestring); add_psymbol_to_list (sym_name, sym_len, 1, VAR_DOMAIN, LOC_STATIC, @@ -1740,7 +1734,7 @@ pos %d"), nlist.n_value += ANOFFSET (objfile->section_offsets, data_sect_index); /* The addresses in these entries are reported to be - wrong. See the code that reads 'G's for symtabs. */ + wrong. See the code that reads 'G's for symtabs. */ add_psymbol_to_list (sym_name, sym_len, 1, VAR_DOMAIN, LOC_STATIC, &objfile->global_psymbols, @@ -1778,7 +1772,7 @@ pos %d"), goto check_enum; case 't': - if (p != namestring) /* a name is there, not just :T... */ + if (p != namestring) /* a name is there, not just :T... */ { add_psymbol_to_list (sym_name, sym_len, 1, VAR_DOMAIN, LOC_TYPEDEF, @@ -1879,10 +1873,10 @@ pos %d"), } nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - /* Kludges for ELF/STABS with Sun ACC */ + /* Kludges for ELF/STABS with Sun ACC. */ last_function_name = namestring; /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit - value for the bottom of the text seg in those cases. */ + value for the bottom of the text seg in those cases. */ if (nlist.n_value == ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)) && gdbarch_sofun_address_maybe_missing (gdbarch)) @@ -1896,7 +1890,7 @@ pos %d"), symbol wasn't found. (Unfortunately, this might also be a valid address.) Anyway, if it *does* return 0, it is likely that the value was set correctly to begin - with... */ + with... */ if (minsym_valu != 0) nlist.n_value = minsym_valu; } @@ -1949,10 +1943,10 @@ pos %d"), } nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - /* Kludges for ELF/STABS with Sun ACC */ + /* Kludges for ELF/STABS with Sun ACC. */ last_function_name = namestring; /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit - value for the bottom of the text seg in those cases. */ + value for the bottom of the text seg in those cases. */ if (nlist.n_value == ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)) && gdbarch_sofun_address_maybe_missing (gdbarch)) @@ -1966,7 +1960,7 @@ pos %d"), symbol wasn't found. (Unfortunately, this might also be a valid address.) Anyway, if it *does* return 0, it is likely that the value was set correctly to begin - with... */ + with... */ if (minsym_valu != 0) nlist.n_value = minsym_valu; } @@ -2019,7 +2013,7 @@ pos %d"), case '8': case '9': case '-': - case '#': /* for symbol identification (used in live ranges) */ + case '#': /* For symbol identification (used in live ranges). */ continue; case ':': @@ -2040,7 +2034,8 @@ pos %d"), time searching to the end of every string looking for a backslash. */ - complaint (&symfile_complaints, _("unknown symbol descriptor `%c'"), + complaint (&symfile_complaints, + _("unknown symbol descriptor `%c'"), p[1]); /* Ignore it; perhaps it is an extension that we don't @@ -2054,7 +2049,7 @@ pos %d"), namestring = set_namestring (objfile, &nlist); /* Find the corresponding bincl and mark that psymtab on the - psymtab dependency list */ + psymtab dependency list. */ { struct partial_symtab *needed_pst = find_corresponding_bincl_psymtab (namestring, nlist.n_value); @@ -2094,7 +2089,8 @@ pos %d"), * sizeof (struct partial_symtab *))); #ifdef DEBUG_INFO fprintf_unfiltered (gdb_stderr, - "Had to reallocate dependency list.\n"); + "Had to reallocate " + "dependency list.\n"); fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n", dependencies_allocated); @@ -2113,8 +2109,8 @@ pos %d"), { end_psymtab (pst, psymtab_include_list, includes_used, symnum * symbol_size, - (CORE_ADDR) 0, - dependency_list, dependencies_used, textlow_not_set); + (CORE_ADDR) 0, dependency_list, + dependencies_used, textlow_not_set); pst = (struct partial_symtab *) 0; includes_used = 0; dependencies_used = 0; @@ -2132,10 +2128,10 @@ pos %d"), case N_BSLINE: case N_SSYM: /* Claim: Structure or union element. Hopefully, I can ignore this. */ - case N_ENTRY: /* Alternate entry point; can ignore. */ + case N_ENTRY: /* Alternate entry point; can ignore. */ case N_MAIN: /* Can definitely ignore this. */ case N_CATCH: /* These are GNU C++ extensions */ - case N_EHDECL: /* that can safely be ignored here. */ + case N_EHDECL: /* that can safely be ignored here. */ case N_LENG: case N_BCOMM: case N_ECOMM: @@ -2149,11 +2145,10 @@ pos %d"), case N_DEFD: /* GNU Modula-2 */ case N_ALIAS: /* SunPro F77: alias name, ignore for now. */ - case N_OBJ: /* useless types from Solaris */ + case N_OBJ: /* Useless types from Solaris. */ case N_OPT: case N_PATCH: - /* These symbols aren't interesting; don't worry about them */ - + /* These symbols aren't interesting; don't worry about them. */ continue; default: @@ -2189,7 +2184,7 @@ pos %d"), SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR is the address relative to which its symbols are (incremental) or 0 - (normal). */ + (normal). */ static struct partial_symtab * start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow, @@ -2217,13 +2212,13 @@ start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow, elfstab_offset_sections (objfile, result); #endif - /* Deduce the source language from the filename for this psymtab. */ + /* Deduce the source language from the filename for this psymtab. */ psymtab_language = deduce_language_from_filename (filename); return result; } -/* Close off the current usage of PST. +/* Close off the current usage of PST. Returns PST or NULL if the partial symtab was empty and thrown away. FIXME: List variables and peculiarities of same. */ @@ -2291,7 +2286,7 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes, if (!gdbarch_sofun_address_maybe_missing (gdbarch)) ; - /* this test will be true if the last .o file is only data */ + /* This test will be true if the last .o file is only data. */ else if (textlow_not_set) pst->textlow = pst->texthigh; else @@ -2309,7 +2304,8 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes, if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst) { p1->texthigh = pst->textlow; - /* if this file has only data, then make textlow match texthigh */ + /* If this file has only data, then make textlow match + texthigh. */ if (p1->textlow == 0) p1->textlow = p1->texthigh; } @@ -2342,7 +2338,7 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes, struct partial_symtab *subpst = allocate_psymtab (include_list[i], objfile); - /* Copy the sesction_offsets array from the main psymtab. */ + /* Copy the sesction_offsets array from the main psymtab. */ subpst->section_offsets = pst->section_offsets; subpst->read_symtab_private = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symloc)); @@ -2404,13 +2400,13 @@ dbx_psymtab_to_symtab_1 (struct partial_symtab *pst) if (pst->readin) { - fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. \ -Shouldn't happen.\n", + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. " + "Shouldn't happen.\n", pst->filename); return; } - /* Read in all partial symtabs on which this one is dependent */ + /* Read in all partial symtabs on which this one is dependent. */ for (i = 0; i < pst->number_of_dependencies; i++) if (!pst->dependencies[i]->readin) { @@ -2422,13 +2418,13 @@ Shouldn't happen.\n", fputs_filtered ("and ", gdb_stdout); wrap_here (""); printf_filtered ("%s...", pst->dependencies[i]->filename); - wrap_here (""); /* Flush output */ + wrap_here (""); /* Flush output. */ gdb_flush (gdb_stdout); } dbx_psymtab_to_symtab_1 (pst->dependencies[i]); } - if (LDSYMLEN (pst)) /* Otherwise it's a dummy */ + if (LDSYMLEN (pst)) /* Otherwise it's a dummy. */ { /* Init stuff necessary for reading in symbols */ stabsread_init (); @@ -2437,7 +2433,7 @@ Shouldn't happen.\n", file_string_table_offset = FILE_STRING_OFFSET (pst); symbol_size = SYMBOL_SIZE (pst); - /* Read in this file's symbols */ + /* Read in this file's symbols. */ bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET); read_ofile_symtab (pst); @@ -2461,8 +2457,8 @@ dbx_psymtab_to_symtab (struct partial_symtab *pst) if (pst->readin) { - fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. \ -Shouldn't happen.\n", + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. " + "Shouldn't happen.\n", pst->filename); return; } @@ -2508,7 +2504,7 @@ Shouldn't happen.\n", } } -/* Read in a defined section of a specific object file's symbols. */ +/* Read in a defined section of a specific object file's symbols. */ static void read_ofile_symtab (struct partial_symtab *pst) @@ -2534,7 +2530,7 @@ read_ofile_symtab (struct partial_symtab *pst) /* This cannot be simply objfile->section_offsets because of elfstab_offset_sections() which initializes the psymtab section offsets information in a special way, and that is different from - objfile->section_offsets. */ + objfile->section_offsets. */ section_offsets = pst->section_offsets; current_objfile = objfile; @@ -2544,7 +2540,7 @@ read_ofile_symtab (struct partial_symtab *pst) last_source_file = NULL; abfd = objfile->obfd; - symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol */ + symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol. */ symbuf_end = symbuf_idx = 0; symbuf_read = 0; symbuf_left = sym_offset + sym_size; @@ -2581,7 +2577,7 @@ read_ofile_symtab (struct partial_symtab *pst) } /* Try to select a C++ demangling based on the compilation unit - producer. */ + producer. */ #if 0 /* For now, stay with AUTO_DEMANGLING for g++ output, as we don't @@ -2616,7 +2612,7 @@ read_ofile_symtab (struct partial_symtab *pst) symnum < max_symnum; symnum++) { - QUIT; /* Allow this to be interruptable */ + QUIT; /* Allow this to be interruptable. */ if (symbuf_idx == symbuf_end) fill_symbuf (abfd); bufp = &symbuf[symbuf_idx++]; @@ -2646,7 +2642,7 @@ read_ofile_symtab (struct partial_symtab *pst) namestring, section_offsets, objfile); } /* We skip checking for a new .o or -l file; that should never - happen in this routine. */ + happen in this routine. */ else if (type == N_TEXT) { /* I don't think this code will ever be executed, because @@ -2676,18 +2672,18 @@ read_ofile_symtab (struct partial_symtab *pst) a corresponding symbol. If so, store the value. Remove syms from the chain when their values are stored, but search the whole chain, as there may be several syms from - different files with the same name. */ + different files with the same name. */ /* This is probably not true. Since the files will be read in one at a time, each reference to a global symbol will - be satisfied in each file as it appears. So we skip this - section. */ + be satisfied in each file as it appears. So we skip this + section. */ ; } } /* In a Solaris elf file, this variable, which comes from the value of the N_SO symbol, will still be 0. Luckily, text_offset, - which comes from pst->textlow is correct. */ + which comes from pst->textlow is correct. */ if (last_source_start_addr == 0) last_source_start_addr = text_offset; @@ -2743,7 +2739,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, /* If this is nonzero, we've seen an N_SLINE since the start of the current function. We use this to tell us to move the first sline to the beginning of the function regardless of what its given - value is. */ + value is. */ static int sline_found_in_function = 1; /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this @@ -2849,7 +2845,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, N_SO, the linker did not relocate them (sigh). */ valu += last_source_start_addr; - new = push_context (desc, valu); + push_context (desc, valu); break; case N_RBRAC: @@ -2884,9 +2880,9 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, 2000 would output N_LSYM entries after N_LBRAC entries. As a consequence, these symbols are simply discarded. Complain if this is the case. */ - complaint (&symfile_complaints, _("\ -misplaced N_LBRAC entry; discarding local symbols which have \ -no enclosing block")); + complaint (&symfile_complaints, + _("misplaced N_LBRAC entry; discarding local " + "symbols which have no enclosing block")); } local_symbols = new->locals; @@ -2946,11 +2942,11 @@ no enclosing block")); /* Check if previous symbol was also an N_SO (with some sanity checks). If so, that one was actually the directory name, and the current one is the real file - name. Patch things up. */ + name. Patch things up. */ if (previous_stab_code == (unsigned char) N_SO) { patch_subfile_names (current_subfile, name); - break; /* Ignore repeated SOs */ + break; /* Ignore repeated SOs. */ } end_symtab (valu, objfile, SECT_OFF_TEXT (objfile)); end_stabs (); @@ -3265,7 +3261,7 @@ no enclosing block")); objfile it is in; If there is more than one N_MAIN, choose the one in the symfile_objfile; If there is more than one N_MAIN within a given objfile, complain() and choose - arbitrarily. (kingdon) */ + arbitrarily. (kingdon) */ if (name != NULL) set_main_name (name); break; @@ -3286,6 +3282,7 @@ no enclosing block")); Generally this is used so that an alias can refer to its main symbol. */ + gdb_assert (name); if (name[0] == '#') { /* Initialize symbol reference names and determine if this is a @@ -3331,7 +3328,7 @@ no enclosing block")); .stabstr section exists. This routine is mostly copied from dbx_symfile_init and dbx_symfile_read, - adjusted for coff details. */ + adjusted for coff details. */ void coffstab_build_psymtabs (struct objfile *objfile, @@ -3380,7 +3377,7 @@ coffstab_build_psymtabs (struct objfile *objfile, /* In a coff file, we've already installed the minimal symbols that came from the coff (non-stab) symbol table, so always act like an - incremental load here. */ + incremental load here. */ if (stabsects->next == NULL) { stabsize = bfd_section_size (sym_bfd, stabsects->section); @@ -3422,7 +3419,7 @@ coffstab_build_psymtabs (struct objfile *objfile, .stabstr section exists. This routine is mostly copied from dbx_symfile_init and dbx_symfile_read, - adjusted for elf details. */ + adjusted for elf details. */ void elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, @@ -3503,7 +3500,8 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, STAB_NAME is the name of the section that contains the stabs. STABSTR_NAME is the name of the section that contains the stab strings. - This routine is mostly copied from dbx_symfile_init and dbx_symfile_read. */ + This routine is mostly copied from dbx_symfile_init and + dbx_symfile_read. */ void stabsect_build_psymtabs (struct objfile *objfile, char *stab_name, @@ -3523,8 +3521,8 @@ stabsect_build_psymtabs (struct objfile *objfile, char *stab_name, return; if (!stabstrsect) - error (_("stabsect_build_psymtabs: Found stabs (%s), but not string \ -section (%s)"), + error (_("stabsect_build_psymtabs: Found stabs (%s), " + "but not string section (%s)"), stab_name, stabstr_name); objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *) @@ -3542,13 +3540,16 @@ section (%s)"), DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect) / DBX_SYMBOL_SIZE (objfile); DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect); - DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; /* XXX - FIXME: POKING INSIDE BFD DATA STRUCTURES */ + DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; /* XXX - FIXME: POKING + INSIDE BFD DATA + STRUCTURES */ if (DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd)) error (_("ridiculous string table size: %d bytes"), DBX_STRINGTAB_SIZE (objfile)); DBX_STRINGTAB (objfile) = (char *) - obstack_alloc (&objfile->objfile_obstack, DBX_STRINGTAB_SIZE (objfile) + 1); + obstack_alloc (&objfile->objfile_obstack, + DBX_STRINGTAB_SIZE (objfile) + 1); OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1); /* Now read in the string table in one big gulp. */ @@ -3556,8 +3557,9 @@ section (%s)"), val = bfd_get_section_contents (sym_bfd, /* bfd */ stabstrsect, /* bfd section */ DBX_STRINGTAB (objfile), /* input buffer */ - 0, /* offset into section */ - DBX_STRINGTAB_SIZE (objfile)); /* amount to read */ + 0, /* offset into section */ + DBX_STRINGTAB_SIZE (objfile)); /* amount to + read */ if (!val) perror_with_name (name); @@ -3567,27 +3569,25 @@ section (%s)"), free_header_files (); init_header_files (); - /* Now, do an incremental load */ + /* Now, do an incremental load. */ processing_acc_compilation = 1; dbx_symfile_read (objfile, 0); } -static struct sym_fns aout_sym_fns = +static const struct sym_fns aout_sym_fns = { bfd_target_aout_flavour, - dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ - dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - dbx_symfile_read, /* sym_read: read a symbol file into symtab */ - dbx_symfile_finish, /* sym_finish: finished with file, cleanup */ - default_symfile_offsets, /* sym_offsets: parse user's offsets to - internal form */ - default_symfile_segments, /* sym_segments: Get segment information from - a file. */ - NULL, /* sym_read_linetable */ - default_symfile_relocate, /* sym_relocate: Relocate a debug section. */ - &psym_functions, - NULL /* next: pointer to next struct sym_fns */ + dbx_new_init, /* init anything gbl to entire symtab */ + dbx_symfile_init, /* read initial info, setup for sym_read() */ + dbx_symfile_read, /* read a symbol file into symtab */ + NULL, /* sym_read_psymbols */ + dbx_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* parse user's offsets to internal form */ + default_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &psym_functions }; void diff --git a/contrib/gdb-7/gdb/dcache.c b/contrib/gdb-7/gdb/dcache.c index d684d74563..0f034705a0 100644 --- a/contrib/gdb-7/gdb/dcache.c +++ b/contrib/gdb-7/gdb/dcache.c @@ -1,7 +1,7 @@ /* Caching code for GDB, the GNU debugger. Copyright (C) 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -88,7 +88,7 @@ struct dcache_block { - /* for least-recently-allocated and free lists */ + /* For least-recently-allocated and free lists. */ struct dcache_block *prev; struct dcache_block *next; @@ -100,7 +100,7 @@ struct dcache_block struct dcache_struct { splay_tree tree; - struct dcache_block *oldest; /* least-recently-allocated list */ + struct dcache_block *oldest; /* least-recently-allocated list. */ /* The free list is maintained identically to OLDEST to simplify the code: we only need one set of accessors. */ @@ -134,7 +134,7 @@ show_dcache_enabled_p (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Deprecated remotecache flag is %s.\n"), value); } -static DCACHE *last_cache; /* Used by info dcache */ +static DCACHE *last_cache; /* Used by info dcache. */ /* Add BLOCK to circular block list BLIST, behind the block at *BLIST. *BLIST is not updated (unless it was previously NULL of course). @@ -575,7 +575,7 @@ dcache_print_line (int index) { printf_filtered ("%02x ", db->data[j]); - /* Print a newline every 16 bytes (48 characters) */ + /* Print a newline every 16 bytes (48 characters). */ if ((j % 16 == 15) && (j != LINE_SIZE - 1)) printf_filtered ("\n"); } diff --git a/contrib/gdb-7/gdb/dcache.h b/contrib/gdb-7/gdb/dcache.h index c8825f16b6..fb581066f2 100644 --- a/contrib/gdb-7/gdb/dcache.h +++ b/contrib/gdb-7/gdb/dcache.h @@ -1,8 +1,8 @@ /* Declarations for caching. Typically used by remote back ends for caching remote memory. - Copyright (C) 1992, 1993, 1995, 1999, 2000, 2001, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1995, 1999, 2000, 2001, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -24,16 +24,16 @@ typedef struct dcache_struct DCACHE; -/* Invalidate DCACHE. */ +/* Invalidate DCACHE. */ void dcache_invalidate (DCACHE *dcache); -/* Initialize DCACHE. */ +/* Initialize DCACHE. */ DCACHE *dcache_init (void); -/* Free a DCACHE */ +/* Free a DCACHE. */ void dcache_free (DCACHE *); -/* Simple to call from _xfer_memory */ +/* Simple to call from _xfer_memory. */ int dcache_xfer_memory (struct target_ops *ops, DCACHE *cache, CORE_ADDR mem, gdb_byte *my, int len, int should_write); diff --git a/contrib/gdb-7/gdb/defs.h b/contrib/gdb-7/gdb/defs.h index 266c009c52..9531c5adad 100644 --- a/contrib/gdb-7/gdb/defs.h +++ b/contrib/gdb-7/gdb/defs.h @@ -3,7 +3,7 @@ /* Basic, host-specific, and target-specific definitions for GDB. Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -78,9 +78,9 @@ /* The O_BINARY flag is defined in fcntl.h on some non-Posix platforms. It is used as an access modifier in calls to open(), where it acts - similarly to the "b" character in fopen()'s MODE argument. On Posix - platforms it should be a no-op, so it is defined as 0 here. This - ensures that the symbol may be used freely elsewhere in gdb. */ + similarly to the "b" character in fopen()'s MODE argument. On Posix + platforms it should be a no-op, so it is defined as 0 here. This + ensures that the symbol may be used freely elsewhere in gdb. */ #ifndef O_BINARY #define O_BINARY 0 @@ -145,10 +145,10 @@ typedef bfd_vma CORE_ADDR; /* Check if a character is one of the commonly used C++ marker characters. */ extern int is_cplus_marker (int); -/* enable xdb commands if set */ +/* Enable xdb commands if set. */ extern int xdb_commands; -/* enable dbx commands if set */ +/* Enable dbx commands if set. */ extern int dbx_commands; /* System root path, used to find libraries etc. */ @@ -175,7 +175,7 @@ extern void quit (void); marginal. If the overhead of a QUIT function call is proving significant then its calling frequency should probably be reduced [kingdon]. A profile analyzing the current situtation is - needed. */ + needed. */ #define QUIT { \ if (quit_flag) quit (); \ @@ -185,7 +185,7 @@ extern void quit (void); /* Languages represented in the symbol table and elsewhere. This should probably be in language.h, but since enum's can't be forward declared to satisfy opaque references before their - actual definition, needs to be here. */ + actual definition, needs to be here. */ enum language { @@ -201,7 +201,7 @@ enum language language_asm, /* Assembly language */ language_pascal, /* Pascal */ language_ada, /* Ada */ - language_scm, /* Guile Scheme */ + language_opencl, /* OpenCL */ language_minimal, /* All other languages, minimal support only */ nr_languages }; @@ -256,7 +256,7 @@ enum return_value_convention Use make_cleanup to add an element to the cleanup chain. Use do_cleanups to do all cleanup actions back to a given point in the chain. Use discard_cleanups to remove cleanups - from the chain back to a given point, not doing them. + from the chain back to a given point, not doing them. If the argument is pointer to allocated memory, then you need to to additionally set the 'free_arg' member to a function that will @@ -321,10 +321,10 @@ extern void discard_final_cleanups (struct cleanup *); extern void discard_my_cleanups (struct cleanup **, struct cleanup *); /* NOTE: cagney/2000-03-04: This typedef is strictly for the - make_cleanup function declarations below. Do not use this typedef + make_cleanup function declarations below. Do not use this typedef as a cast when passing functions into the make_cleanup() code. Instead either use a bounce function or add a wrapper function. - Calling a f(char*) function with f(void*) is non-portable. */ + Calling a f(char*) function with f(void*) is non-portable. */ typedef void (make_cleanup_ftype) (void *); extern struct cleanup *make_cleanup (make_cleanup_ftype *, void *); @@ -337,6 +337,10 @@ extern struct cleanup *make_cleanup_freeargv (char **); struct ui_file; extern struct cleanup *make_cleanup_ui_file_delete (struct ui_file *); +struct ui_out; +extern struct cleanup * + make_cleanup_ui_out_redirect_pop (struct ui_out *uiout); + struct section_addr_info; extern struct cleanup *(make_cleanup_free_section_addr_info (struct section_addr_info *)); @@ -353,6 +357,9 @@ extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack); extern struct cleanup *make_cleanup_restore_integer (int *variable); extern struct cleanup *make_cleanup_restore_uinteger (unsigned int *variable); +struct target_ops; +extern struct cleanup *make_cleanup_unpush_target (struct target_ops *ops); + extern struct cleanup * make_cleanup_restore_ui_file (struct ui_file **variable); @@ -437,13 +444,13 @@ extern struct ui_file *gdb_stdin; extern struct ui_file *gdb_stderr; /* Log/debug/trace messages that should bypass normal stdout/stderr filtering. For moment, always call this stream using - *_unfiltered. In the very near future that restriction shall be - removed - either call shall be unfiltered. (cagney 1999-06-13). */ + *_unfiltered. In the very near future that restriction shall be + removed - either call shall be unfiltered. (cagney 1999-06-13). */ extern struct ui_file *gdb_stdlog; /* Target output that should bypass normal stdout/stderr filtering. - For moment, always call this stream using *_unfiltered. In the + For moment, always call this stream using *_unfiltered. In the very near future that restriction shall be removed - either call - shall be unfiltered. (cagney 1999-07-02). */ + shall be unfiltered. (cagney 1999-07-02). */ extern struct ui_file *gdb_stdtarg; extern struct ui_file *gdb_stdtargerr; extern struct ui_file *gdb_stdtargin; @@ -475,11 +482,14 @@ extern void puts_debug (char *prefix, char *string, char *suffix); extern void vprintf_filtered (const char *, va_list) ATTRIBUTE_PRINTF (1, 0); -extern void vfprintf_filtered (struct ui_file *, const char *, va_list) ATTRIBUTE_PRINTF (2, 0); +extern void vfprintf_filtered (struct ui_file *, const char *, va_list) + ATTRIBUTE_PRINTF (2, 0); -extern void fprintf_filtered (struct ui_file *, const char *, ...) ATTRIBUTE_PRINTF (2, 3); +extern void fprintf_filtered (struct ui_file *, const char *, ...) + ATTRIBUTE_PRINTF (2, 3); -extern void fprintfi_filtered (int, struct ui_file *, const char *, ...) ATTRIBUTE_PRINTF (3, 4); +extern void fprintfi_filtered (int, struct ui_file *, const char *, ...) + ATTRIBUTE_PRINTF (3, 4); extern void printf_filtered (const char *, ...) ATTRIBUTE_PRINTF (1, 2); @@ -487,9 +497,11 @@ extern void printfi_filtered (int, const char *, ...) ATTRIBUTE_PRINTF (2, 3); extern void vprintf_unfiltered (const char *, va_list) ATTRIBUTE_PRINTF (1, 0); -extern void vfprintf_unfiltered (struct ui_file *, const char *, va_list) ATTRIBUTE_PRINTF (2, 0); +extern void vfprintf_unfiltered (struct ui_file *, const char *, va_list) + ATTRIBUTE_PRINTF (2, 0); -extern void fprintf_unfiltered (struct ui_file *, const char *, ...) ATTRIBUTE_PRINTF (2, 3); +extern void fprintf_unfiltered (struct ui_file *, const char *, ...) + ATTRIBUTE_PRINTF (2, 3); extern void printf_unfiltered (const char *, ...) ATTRIBUTE_PRINTF (1, 2); @@ -499,15 +511,19 @@ extern void print_spaces_filtered (int, struct ui_file *); extern char *n_spaces (int); -extern void fputstr_filtered (const char *str, int quotr, struct ui_file * stream); +extern void fputstr_filtered (const char *str, int quotr, + struct ui_file * stream); -extern void fputstr_unfiltered (const char *str, int quotr, struct ui_file * stream); +extern void fputstr_unfiltered (const char *str, int quotr, + struct ui_file * stream); -extern void fputstrn_filtered (const char *str, int n, int quotr, struct ui_file * stream); +extern void fputstrn_filtered (const char *str, int n, int quotr, + struct ui_file * stream); -extern void fputstrn_unfiltered (const char *str, int n, int quotr, struct ui_file * stream); +extern void fputstrn_unfiltered (const char *str, int n, int quotr, + struct ui_file * stream); -/* Display the host ADDR on STREAM formatted as ``0x%x''. */ +/* Display the host ADDR on STREAM formatted as ``0x%x''. */ extern void gdb_print_host_address (const void *addr, struct ui_file *stream); extern const char *host_address_to_string (const void *addr); @@ -516,6 +532,12 @@ extern const char *host_address_to_string (const void *addr); This is usually formatted similar to 0x%lx. */ extern const char *paddress (struct gdbarch *gdbarch, CORE_ADDR addr); +/* Return a string representation in hexadecimal notation of ADDRESS, + which is suitable for printing. */ + +extern const char *print_core_address (struct gdbarch *gdbarch, + CORE_ADDR address); + /* %d for LONGEST */ extern char *plongest (LONGEST l); /* %u for ULONGEST */ @@ -558,7 +580,7 @@ extern void symbol_file_command (char *, int); extern void generic_load (char *name, int from_tty); /* Report on STREAM the performance of memory transfer operation, - such as 'load'. + such as 'load'. DATA_COUNT is the number of bytes transferred. WRITE_COUNT is the number of separate write operations, or 0, if that information is not available. @@ -631,19 +653,20 @@ extern void init_source_path (void); /* From exec.c */ -/* Take over the 'find_mapped_memory' vector from exec.c. */ -extern void exec_set_find_memory_regions (int (*) (int (*) (CORE_ADDR, - unsigned long, - int, int, int, - void *), - void *)); +typedef int (*find_memory_region_ftype) (CORE_ADDR addr, unsigned long size, + int read, int write, int exec, + void *data); + +/* Take over the 'find_mapped_memory' vector from exec.c. */ +extern void exec_set_find_memory_regions + (int (*func) (find_memory_region_ftype func, void *data)); /* Possible lvalue types. Like enum language, this should be in - value.h, but needs to be here for the same reason. */ + value.h, but needs to be here for the same reason. */ enum lval_type { - /* Not an lval. */ + /* Not an lval. */ not_lval, /* In memory. */ lval_memory, @@ -691,10 +714,9 @@ struct command_line enum command_control_type control_type; /* The number of elements in body_list. */ int body_count; - /* For composite commands, the nested lists of - commands. For example, for "if" command this - will contain the then branch and the else - branch, if that is available. */ + /* For composite commands, the nested lists of commands. For + example, for "if" command this will contain the then branch and + the else branch, if that is available. */ struct command_line **body_list; }; @@ -707,11 +729,11 @@ extern struct command_line *read_command_lines_1 (char * (*) (void), int, extern void free_command_lines (struct command_line **); -/* To continue the execution commands when running gdb asynchronously. +/* To continue the execution commands when running gdb asynchronously. A continuation structure contains a pointer to a function to be called - to finish the command, once the target has stopped. Such mechanism is + to finish the command, once the target has stopped. Such mechanism is used by the finish and until commands, and in the remote protocol - when opening an extended-remote connection. */ + when opening an extended-remote connection. */ struct continuation; struct thread_info; @@ -757,7 +779,7 @@ extern unsigned output_radix; things. Like enum language, this should be in value.h, but needs to be here for the same reason. FIXME: If we can eliminate this as an arg to LA_VAL_PRINT, then we can probably move it back to - value.h. */ + value.h. */ enum val_prettyprint { @@ -824,26 +846,26 @@ typedef struct ptid ptid_t; #endif /* Defaults for system-wide constants (if not defined by xm.h, we fake it). - FIXME: Assumes 2's complement arithmetic */ + FIXME: Assumes 2's complement arithmetic. */ #if !defined (UINT_MAX) -#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */ +#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */ #endif #if !defined (INT_MAX) -#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ +#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ #endif #if !defined (INT_MIN) -#define INT_MIN ((int)((int) ~0 ^ INT_MAX)) /* 0x80000000 for 32-bits */ +#define INT_MIN ((int)((int) ~0 ^ INT_MAX)) /* 0x80000000 for 32-bits */ #endif #if !defined (ULONG_MAX) -#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */ +#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */ #endif #if !defined (LONG_MAX) -#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ +#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ #endif #if !defined (ULONGEST_MAX) @@ -866,7 +888,7 @@ extern int longest_to_int (LONGEST); extern char *savestring (const char *, size_t); /* xmalloc(), xrealloc() and xcalloc() have already been declared in - "libiberty.h". */ + "libiberty.h". */ extern void xfree (void *); /* Like xmalloc, but zero the memory. */ @@ -880,8 +902,9 @@ extern void *xzalloc (size_t); #define XCALLOC(NMEMB, TYPE) ((TYPE*) xcalloc ((NMEMB), sizeof (TYPE))) /* Like asprintf/vasprintf but get an internal_error if the call - fails. */ -extern void xasprintf (char **ret, const char *format, ...) ATTRIBUTE_PRINTF (2, 3); + fails. */ +extern void xasprintf (char **ret, const char *format, ...) + ATTRIBUTE_PRINTF (2, 3); extern void xvasprintf (char **ret, const char *format, va_list ap) ATTRIBUTE_PRINTF (2, 0); @@ -1023,15 +1046,15 @@ extern void *alloca (); #endif /* Not GNU C */ #endif /* alloca not defined */ -/* Dynamic target-system-dependent parameters for GDB. */ +/* Dynamic target-system-dependent parameters for GDB. */ #include "gdbarch.h" /* Maximum size of a register. Something small, but large enough for all known ISAs. If it turns out to be too small, make it bigger. */ -enum { MAX_REGISTER_SIZE = 32 }; +enum { MAX_REGISTER_SIZE = 64 }; -/* Static target-system-dependent parameters for GDB. */ +/* Static target-system-dependent parameters for GDB. */ /* Number of bits in a char or unsigned char for the target machine. Just like CHAR_BIT in but describes the target machine. */ @@ -1042,7 +1065,7 @@ enum { MAX_REGISTER_SIZE = 32 }; /* If we picked up a copy of CHAR_BIT from a configuration file (which may get it by including ) then use it to set the number of bits in a host char. If not, use the same size - as the target. */ + as the target. */ #if defined (CHAR_BIT) #define HOST_CHAR_BIT CHAR_BIT @@ -1080,14 +1103,14 @@ extern int watchdog; /* Hooks for alternate command interfaces. */ -/* The name of the interpreter if specified on the command line. */ +/* The name of the interpreter if specified on the command line. */ extern char *interpreter_p; /* If a given interpreter matches INTERPRETER_P then it should update deprecated_command_loop_hook and deprecated_init_ui_hook with the per-interpreter implementation. */ /* FIXME: deprecated_command_loop_hook and deprecated_init_ui_hook - should be moved here. */ + should be moved here. */ struct target_waitstatus; struct cmd_list_element; @@ -1104,7 +1127,8 @@ extern void (*deprecated_show_load_progress) (const char *section, unsigned long total_sent, unsigned long total_size); extern void (*deprecated_print_frame_info_listing_hook) (struct symtab * s, - int line, int stopline, + int line, + int stopline, int noerror); extern int (*deprecated_query_hook) (const char *, va_list) ATTRIBUTE_FPTR_PRINTF(1,0); @@ -1135,7 +1159,7 @@ extern int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num); -/* Inhibit window interface if non-zero. */ +/* Inhibit window interface if non-zero. */ extern int use_windows; diff --git a/contrib/gdb-7/gdb/demangle.c b/contrib/gdb-7/gdb/demangle.c index af306a5ea9..5600692aab 100644 --- a/contrib/gdb-7/gdb/demangle.c +++ b/contrib/gdb-7/gdb/demangle.c @@ -1,7 +1,7 @@ /* Basic C++ demangling support for GDB. Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, - 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -22,7 +22,7 @@ /* This file contains support code for C++ demangling that is common - to a styles of demangling, and GDB specific. */ + to a styles of demangling, and GDB specific. */ #include "defs.h" #include "command.h" @@ -36,7 +36,7 @@ "lucid", "arm", "hp", etc.) in which case gdb will never attempt to do auto selection of the style unless you do an explicit "set demangle auto". To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in - the appropriate target configuration file. */ + the appropriate target configuration file. */ #ifndef DEFAULT_DEMANGLING_STYLE #define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING @@ -46,7 +46,7 @@ extern void _initialize_demangler (void); /* String name for the current demangling style. Set by the "set demangle-style" command, printed as part of the output by the - "show demangle-style" command. */ + "show demangle-style" command. */ static char *current_demangling_style_string; @@ -79,7 +79,7 @@ static void set_demangling_command (char *, int, struct cmd_list_element *); enum value. Note: Assumes that current_demangling_style_string always points to - a malloc'd string, even if it is a null-string. */ + a malloc'd string, even if it is a null-string. */ static void set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) @@ -89,7 +89,7 @@ set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) /* First just try to match whatever style name the user supplied with one of the known ones. Don't bother special casing for an empty name, we just treat it as any other style name that doesn't match. - If we match, update the current demangling style enum. */ + If we match, update the current demangling style enum. */ for (dem = libiberty_demanglers; dem->demangling_style != unknown_demangling; @@ -104,8 +104,8 @@ set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) } /* Check to see if we found a match. If not, gripe about any non-empty - style name and supply a list of valid ones. FIXME: This should - probably be done with some sort of completion and with help. */ + style name and supply a list of valid ones. FIXME: This should + probably be done with some sort of completion and with help. */ if (dem->demangling_style == unknown_demangling) { @@ -132,7 +132,7 @@ set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) { /* This can happen during initialization if gdb is compiled with a DEMANGLING_STYLE value that is unknown, so pick the first - one as the default. */ + one as the default. */ current_demangling_style = libiberty_demanglers[0].demangling_style; current_demangling_style_string = xstrdup (libiberty_demanglers[0].demangling_style_name); @@ -142,7 +142,7 @@ set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) } } -/* Fake a "set demangle-style" command. */ +/* Fake a "set demangle-style" command. */ void set_demangling_style (char *style) @@ -205,6 +205,6 @@ Use `set demangle-style' without arguments for a list of demangling styles."), show_demangling_style_names, &setlist, &showlist); - /* Set the default demangling style chosen at compilation time. */ + /* Set the default demangling style chosen at compilation time. */ set_demangling_style (DEFAULT_DEMANGLING_STYLE); } diff --git a/contrib/gdb-7/gdb/dfp.c b/contrib/gdb-7/gdb/dfp.c index 42e21e09ad..0ca1ed3c4a 100644 --- a/contrib/gdb-7/gdb/dfp.c +++ b/contrib/gdb-7/gdb/dfp.c @@ -1,6 +1,6 @@ /* Decimal floating point support for GDB. - Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -89,7 +89,8 @@ decimal_check_errors (decContext *ctx) { /* Leave only the error bits in the status flags. */ ctx->status &= DEC_IEEE_854_Invalid_operation; - error (_("Cannot perform operation: %s"), decContextStatusToString (ctx)); + error (_("Cannot perform operation: %s"), + decContextStatusToString (ctx)); } } @@ -133,7 +134,7 @@ decimal_to_number (const gdb_byte *from, int len, decNumber *to) decimal128ToNumber ((decimal128 *) from, to); break; default: - error (_("Unknown decimal floating point type.\n")); + error (_("Unknown decimal floating point type.")); break; } } @@ -217,7 +218,8 @@ decimal_from_integral (struct value *from, if (TYPE_LENGTH (type) > 4) /* libdecnumber can convert only 32-bit integers. */ - error (_("Conversion of large integer to a decimal floating type is not supported.")); + error (_("Conversion of large integer to a " + "decimal floating type is not supported.")); l = value_as_long (from); diff --git a/contrib/gdb-7/gdb/dfp.h b/contrib/gdb-7/gdb/dfp.h index c798956987..9c6ce20553 100644 --- a/contrib/gdb-7/gdb/dfp.h +++ b/contrib/gdb-7/gdb/dfp.h @@ -1,6 +1,6 @@ /* Decimal floating point support for GDB. - Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -30,7 +30,8 @@ #define MAX_DECIMAL_STRING 43 extern void decimal_to_string (const gdb_byte *, int, enum bfd_endian, char *); -extern int decimal_from_string (gdb_byte *, int, enum bfd_endian, const char *); +extern int decimal_from_string (gdb_byte *, int, enum bfd_endian, + const char *); extern void decimal_from_integral (struct value *from, gdb_byte *to, int len, enum bfd_endian byte_order); extern void decimal_from_floating (struct value *from, gdb_byte *to, diff --git a/contrib/gdb-7/gdb/dictionary.c b/contrib/gdb-7/gdb/dictionary.c index e1c2010bc1..29816921d9 100644 --- a/contrib/gdb-7/gdb/dictionary.c +++ b/contrib/gdb-7/gdb/dictionary.c @@ -1,6 +1,7 @@ /* Routines for name->symbol lookups in GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -21,6 +22,7 @@ along with this program. If not, see . */ #include "defs.h" +#include #include "gdb_obstack.h" #include "symtab.h" #include "buildsym.h" @@ -81,9 +83,7 @@ * Define a function dict_ that looks up in the dict_vector and calls the appropriate function. Add a declaration for - dict_ to dictionary.h. - -*/ + dict_ to dictionary.h. */ /* An enum representing the various implementations of dictionaries. Used only for debugging. */ @@ -116,11 +116,13 @@ struct dict_vector struct dict_iterator *iterator); struct symbol *(*iterator_next) (struct dict_iterator *iterator); /* Functions to iterate over symbols with a given name. */ - struct symbol *(*iter_name_first) (const struct dictionary *dict, - const char *name, + struct symbol *(*iter_match_first) (const struct dictionary *dict, + const char *name, + symbol_compare_ftype *equiv, + struct dict_iterator *iterator); + struct symbol *(*iter_match_next) (const char *name, + symbol_compare_ftype *equiv, struct dict_iterator *iterator); - struct symbol *(*iter_name_next) (const char *name, - struct dict_iterator *iterator); /* A size function, for maint print symtabs. */ int (*size) (const struct dictionary *dict); }; @@ -236,12 +238,16 @@ static struct symbol *iterator_first_hashed (const struct dictionary *dict, static struct symbol *iterator_next_hashed (struct dict_iterator *iterator); -static struct symbol *iter_name_first_hashed (const struct dictionary *dict, - const char *name, +static struct symbol *iter_match_first_hashed (const struct dictionary *dict, + const char *name, + symbol_compare_ftype *compare, struct dict_iterator *iterator); -static struct symbol *iter_name_next_hashed (const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_next_hashed (const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator); + +static unsigned int dict_hash (const char *string); /* Functions only for DICT_HASHED. */ @@ -264,12 +270,14 @@ static struct symbol *iterator_first_linear (const struct dictionary *dict, static struct symbol *iterator_next_linear (struct dict_iterator *iterator); -static struct symbol *iter_name_first_linear (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_first_linear (const struct dictionary *dict, + const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator); -static struct symbol *iter_name_next_linear (const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_next_linear (const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator); static int size_linear (const struct dictionary *dict); @@ -289,8 +297,8 @@ static const struct dict_vector dict_hashed_vector = add_symbol_nonexpandable, /* add_symbol */ iterator_first_hashed, /* iterator_first */ iterator_next_hashed, /* iterator_next */ - iter_name_first_hashed, /* iter_name_first */ - iter_name_next_hashed, /* iter_name_next */ + iter_match_first_hashed, /* iter_name_first */ + iter_match_next_hashed, /* iter_name_next */ size_hashed, /* size */ }; @@ -301,8 +309,8 @@ static const struct dict_vector dict_hashed_expandable_vector = add_symbol_hashed_expandable, /* add_symbol */ iterator_first_hashed, /* iterator_first */ iterator_next_hashed, /* iterator_next */ - iter_name_first_hashed, /* iter_name_first */ - iter_name_next_hashed, /* iter_name_next */ + iter_match_first_hashed, /* iter_name_first */ + iter_match_next_hashed, /* iter_name_next */ size_hashed_expandable, /* size */ }; @@ -313,8 +321,8 @@ static const struct dict_vector dict_linear_vector = add_symbol_nonexpandable, /* add_symbol */ iterator_first_linear, /* iterator_first */ iterator_next_linear, /* iterator_next */ - iter_name_first_linear, /* iter_name_first */ - iter_name_next_linear, /* iter_name_next */ + iter_match_first_linear, /* iter_name_first */ + iter_match_next_linear, /* iter_name_next */ size_linear, /* size */ }; @@ -325,8 +333,8 @@ static const struct dict_vector dict_linear_expandable_vector = add_symbol_linear_expandable, /* add_symbol */ iterator_first_linear, /* iterator_first */ iterator_next_linear, /* iterator_next */ - iter_name_first_linear, /* iter_name_first */ - iter_name_next_linear, /* iter_name_next */ + iter_match_first_linear, /* iter_name_first */ + iter_match_next_linear, /* iter_name_next */ size_linear, /* size */ }; @@ -516,14 +524,30 @@ dict_iter_name_first (const struct dictionary *dict, const char *name, struct dict_iterator *iterator) { - return (DICT_VECTOR (dict))->iter_name_first (dict, name, iterator); + return dict_iter_match_first (dict, name, strcmp_iw, iterator); } struct symbol * dict_iter_name_next (const char *name, struct dict_iterator *iterator) +{ + return dict_iter_match_next (name, strcmp_iw, iterator); +} + +struct symbol * +dict_iter_match_first (const struct dictionary *dict, + const char *name, symbol_compare_ftype *compare, + struct dict_iterator *iterator) +{ + return (DICT_VECTOR (dict))->iter_match_first (dict, name, + compare, iterator); +} + +struct symbol * +dict_iter_match_next (const char *name, symbol_compare_ftype *compare, + struct dict_iterator *iterator) { return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator))) - ->iter_name_next (name, iterator); + ->iter_match_next (name, compare, iterator); } int @@ -614,12 +638,11 @@ iterator_hashed_advance (struct dict_iterator *iterator) } static struct symbol * -iter_name_first_hashed (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator) +iter_match_first_hashed (const struct dictionary *dict, const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator) { - unsigned int hash_index - = msymbol_hash_iw (name) % DICT_HASHED_NBUCKETS (dict); + unsigned int hash_index = dict_hash (name) % DICT_HASHED_NBUCKETS (dict); struct symbol *sym; DICT_ITERATOR_DICT (iterator) = dict; @@ -632,8 +655,8 @@ iter_name_first_hashed (const struct dictionary *dict, sym != NULL; sym = sym->hash_next) { - /* Warning: the order of arguments to strcmp_iw matters! */ - if (strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) + /* Warning: the order of arguments to compare matters! */ + if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0) { break; } @@ -645,7 +668,8 @@ iter_name_first_hashed (const struct dictionary *dict, } static struct symbol * -iter_name_next_hashed (const char *name, struct dict_iterator *iterator) +iter_match_next_hashed (const char *name, symbol_compare_ftype *compare, + struct dict_iterator *iterator) { struct symbol *next; @@ -653,7 +677,7 @@ iter_name_next_hashed (const char *name, struct dict_iterator *iterator) next != NULL; next = next->hash_next) { - if (strcmp_iw (SYMBOL_SEARCH_NAME (next), name) == 0) + if (compare (SYMBOL_SEARCH_NAME (next), name) == 0) break; } @@ -671,8 +695,8 @@ insert_symbol_hashed (struct dictionary *dict, unsigned int hash_index; struct symbol **buckets = DICT_HASHED_BUCKETS (dict); - hash_index = (msymbol_hash_iw (SYMBOL_SEARCH_NAME (sym)) - % DICT_HASHED_NBUCKETS (dict)); + hash_index = + dict_hash (SYMBOL_SEARCH_NAME (sym)) % DICT_HASHED_NBUCKETS (dict); sym->hash_next = buckets[hash_index]; buckets[hash_index] = sym; } @@ -746,6 +770,70 @@ expand_hashtable (struct dictionary *dict) xfree (old_buckets); } +/* Produce an unsigned hash value from STRING0 that is consistent + with strcmp_iw, strcmp, and, at least on Ada symbols, wild_match. + That is, two identifiers equivalent according to any of those three + comparison operators hash to the same value. */ + +static unsigned int +dict_hash (const char *string0) +{ + /* The Ada-encoded version of a name P1.P2...Pn has either the form + P1__P2__...Pn or _ada_P1__P2__...Pn (where the Pi + are lower-cased identifiers). The (which can be empty) + encodes additional information about the denoted entity. This + routine hashes such names to msymbol_hash_iw(Pn). It actually + does this for a superset of both valid Pi and of , but + in other cases it simply returns msymbol_hash_iw(STRING0). */ + + const char *string; + unsigned int hash; + + string = string0; + if (*string == '_') + { + if (strncmp (string, "_ada_", 5) == 0) + string += 5; + else + return msymbol_hash_iw (string0); + } + + hash = 0; + while (*string) + { + switch (*string) + { + case '$': + case '.': + case 'X': + if (string0 == string) + return msymbol_hash_iw (string0); + else + return hash; + case ' ': + case '(': + return msymbol_hash_iw (string0); + case '_': + if (string[1] == '_' && string != string0) + { + int c = string[2]; + + if ((c < 'a' || c > 'z') && c != 'O') + return hash; + hash = 0; + string += 2; + break; + } + /* FALL THROUGH */ + default: + hash = hash * 67 + *string - 113; + string += 1; + break; + } + } + return hash; +} + /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE. */ static struct symbol * @@ -769,18 +857,19 @@ iterator_next_linear (struct dict_iterator *iterator) } static struct symbol * -iter_name_first_linear (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator) +iter_match_first_linear (const struct dictionary *dict, + const char *name, symbol_compare_ftype *compare, + struct dict_iterator *iterator) { DICT_ITERATOR_DICT (iterator) = dict; DICT_ITERATOR_INDEX (iterator) = -1; - return iter_name_next_linear (name, iterator); + return iter_match_next_linear (name, compare, iterator); } static struct symbol * -iter_name_next_linear (const char *name, struct dict_iterator *iterator) +iter_match_next_linear (const char *name, symbol_compare_ftype *compare, + struct dict_iterator *iterator) { const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); int i, nsyms = DICT_LINEAR_NSYMS (dict); @@ -789,7 +878,7 @@ iter_name_next_linear (const char *name, struct dict_iterator *iterator) for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nsyms; ++i) { sym = DICT_LINEAR_SYM (dict, i); - if (strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) + if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0) { retval = sym; break; diff --git a/contrib/gdb-7/gdb/dictionary.h b/contrib/gdb-7/gdb/dictionary.h index 2242a791a1..944a5a11e2 100644 --- a/contrib/gdb-7/gdb/dictionary.h +++ b/contrib/gdb-7/gdb/dictionary.h @@ -1,6 +1,7 @@ /* Routines for name->symbol lookups in GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -23,6 +24,8 @@ #ifndef DICTIONARY_H #define DICTIONARY_H +#include "symfile.h" + /* An opaque type for dictionaries; only dictionary.c should know about its innards. */ @@ -134,6 +137,29 @@ extern struct symbol *dict_iter_name_first (const struct dictionary *dict, extern struct symbol *dict_iter_name_next (const char *name, struct dict_iterator *iterator); +/* Initialize ITERATOR to point at the first symbol in DICT whose + SYMBOL_SEARCH_NAME is NAME, as tested using COMPARE (which must use + the same conventions as strcmp_iw and be compatible with any + dictionary hashing function), and return that first symbol, or NULL + if there are no such symbols. */ + +extern struct symbol *dict_iter_match_first (const struct dictionary *dict, + const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator); + +/* Advance ITERATOR to point at the next symbol in DICT whose + SYMBOL_SEARCH_NAME is NAME, as tested using COMPARE (see + dict_iter_match_first), or NULL if there are no more such symbols. + Don't call this if you've previously received NULL from + dict_iterator_match_first or dict_iterator_match_next on this + iteration. And don't call it unless ITERATOR was created by a + previous call to dict_iter_match_first with the same NAME and COMPARE. */ + +extern struct symbol *dict_iter_match_next (const char *name, + symbol_compare_ftype *compare, + struct dict_iterator *iterator); + /* Return some notion of the size of the dictionary: the number of symbols if we have that, the number of hash buckets otherwise. */ diff --git a/contrib/gdb-7/gdb/disasm.c b/contrib/gdb-7/gdb/disasm.c index c51f0bf5cc..ee19f70c03 100644 --- a/contrib/gdb-7/gdb/disasm.c +++ b/contrib/gdb-7/gdb/disasm.c @@ -1,7 +1,7 @@ /* Disassemble support for GDB. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -29,7 +29,7 @@ /* Disassemble functions. FIXME: We should get rid of all the duplicate code in gdb that does - the same thing: disassemble_command() and the gdbtk variation. */ + the same thing: disassemble_command() and the gdbtk variation. */ /* This Structure is used to store line number information. We need a different sort of line table from the normal one cuz we can't @@ -77,12 +77,21 @@ compare_lines (const void *mle1p, const void *mle2p) mle1 = (struct dis_line_entry *) mle1p; mle2 = (struct dis_line_entry *) mle2p; - val = mle1->line - mle2->line; - - if (val != 0) - return val; - - return mle1->start_pc - mle2->start_pc; + /* End of sequence markers have a line number of 0 but don't want to + be sorted to the head of the list, instead sort by PC. */ + if (mle1->line == 0 || mle2->line == 0) + { + val = mle1->start_pc - mle2->start_pc; + if (val == 0) + val = mle1->line - mle2->line; + } + else + { + val = mle1->line - mle2->line; + if (val == 0) + val = mle1->start_pc - mle2->start_pc; + } + return val; } static int @@ -121,7 +130,7 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, &line, &unmapped)) { /* We don't care now about line, filename and - unmapped. But we might in the future. */ + unmapped. But we might in the future. */ ui_out_text (uiout, " <"); if ((flags & DISASSEMBLY_OMIT_FNAME) == 0) ui_out_field_string (uiout, "func-name", name); @@ -143,6 +152,13 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, CORE_ADDR old_pc = pc; bfd_byte data; int status; + const char *spacer = ""; + + /* Build the opcodes using a temporary stream so we can + write them out in a single go for the MI. */ + struct ui_stream *opcode_stream = ui_out_stream_new (uiout); + struct cleanup *cleanups = + make_cleanup_ui_out_stream_delete (opcode_stream); pc += gdbarch_print_insn (gdbarch, pc, di); for (;old_pc < pc; old_pc++) @@ -150,9 +166,14 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, status = (*di->read_memory_func) (old_pc, &data, 1, di); if (status != 0) (*di->memory_error_func) (status, old_pc, di); - ui_out_message (uiout, 0, " %02x", (unsigned)data); + fprintf_filtered (opcode_stream->stream, "%s%02x", + spacer, (unsigned) data); + spacer = " "; } + ui_out_field_stream (uiout, "opcodes", opcode_stream); ui_out_text (uiout, "\t"); + + do_cleanups (cleanups); } else pc += gdbarch_print_insn (gdbarch, pc, di); @@ -168,6 +189,7 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, function to the user. This means that things are presented in source order, with (possibly) out of order assembly immediately following. */ + static void do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, struct disassemble_info *di, int nlines, @@ -203,7 +225,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, for (; i < nlines - 1 && le[i].pc < high; i++) { if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) - continue; /* Ignore duplicates */ + continue; /* Ignore duplicates. */ /* Skip any end-of-function markers. */ if (le[i].line == 0) @@ -230,7 +252,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, } /* Now, sort mle by line #s (and, then by addresses within - lines). */ + lines). */ if (out_of_order) qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); @@ -248,7 +270,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, { if (next_line != 0) { - /* Just one line to print. */ + /* Just one line to print. */ if (next_line == mle[i].line) { ui_out_tuple_chain @@ -258,7 +280,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, } else { - /* Several source lines w/o asm instructions associated. */ + /* Several source lines w/o asm instructions associated. */ for (; next_line < mle[i].line; next_line++) { struct cleanup *ui_out_list_chain_line; @@ -276,7 +298,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, do_cleanups (ui_out_tuple_chain_line); } /* Print the last line and leave list open for - asm instructions to be added. */ + asm instructions to be added. */ ui_out_tuple_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); @@ -286,7 +308,8 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, else { ui_out_tuple_chain - = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); + = make_cleanup_ui_out_tuple_begin_end (uiout, + "src_and_asm_line"); print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); } @@ -383,12 +406,12 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout, struct ui_stream *stb = ui_out_stream_new (uiout); struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream); - /* To collect the instruction outputted from opcodes. */ + /* To collect the instruction outputted from opcodes. */ struct symtab *symtab = NULL; struct linetable_entry *le = NULL; int nlines = -1; - /* Assume symtab is valid for whole PC range */ + /* Assume symtab is valid for whole PC range. */ symtab = find_pc_symtab (low); if (symtab != NULL && symtab->linetable != NULL) diff --git a/contrib/gdb-7/gdb/disasm.h b/contrib/gdb-7/gdb/disasm.h index e308985992..32ffd0b71f 100644 --- a/contrib/gdb-7/gdb/disasm.h +++ b/contrib/gdb-7/gdb/disasm.h @@ -1,5 +1,6 @@ /* Disassemble support for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/doc/LRS b/contrib/gdb-7/gdb/doc/LRS new file mode 100644 index 0000000000..7e25d432a3 --- /dev/null +++ b/contrib/gdb-7/gdb/doc/LRS @@ -0,0 +1,197 @@ +What's LRS? +=========== + +LRS, or Live Range Splitting is an optimization technique which allows +a user variable to reside in different locations during different parts +of a function. + +For example, a variable might reside in the stack for part of a function +and in a register during a loop and in a different register during +another loop. + +Clearly, if a variable may reside in different locations, then the +compiler must describe to the debugger where the variable resides for +any given part of the function. + +This document describes the debug format for encoding these extensions +in stabs. + +Since these extensions are gcc specific, these additional symbols and +stabs can be disabled by the gcc command option -gstabs. + + +GNU extensions for LRS under stabs: +=================================== + + +range symbols: +------------- + + A range symbol will be used to mark the beginning or end of a + live range (the range which describes where a symbol is active, + or live). These symbols will later be referenced in the stabs for + debug purposes. For simplicity, we'll use the terms "range_start" + and "range_end" to identify the range symbols which mark the beginning + and end of a live range respectively. + + Any text symbol which would normally appear in the symbol table + (eg. a function name) can be used as range symbol. If an address + is needed to delimit a live range and does not match any of the + values of symbols which would normally appear in the symbol table, + a new symbol will be added to the table whose value is that address. + + The three new symbol types described below have been added for this + purpose. + + For efficiency, the compiler should use existing symbols as range + symbols whenever possible; this reduces the number of additional + symbols which need to be added to the symbol table. + + +New debug symbol type for defining ranges: +------------------------------------------ + + range_off - contains PC function offset for start/end of a live range. + Its location is relative to the function start and therefore + eliminates the need for additional relocation. + + This symbol has a values in the text section, and does not have a name. + + NOTE: the following may not be needed but are included here just + in case. + range - contains PC value of beginning or end of a live range + (relocs required). + + NOTE: the following will be required if we desire LRS debugging + to work with old style a.out stabs. + range_abs - contains absolute PC value of start/end of a live + range. The range_abs debug symbol is provided for + completeness, in case there is a need to describe addresses + in ROM, etc. + + +Live range: +----------- + + The compiler and debugger view a variable with multiple homes as + a primary symbol and aliases for that symbol. The primary symbol + describes the default home of the variable while aliases describe + alternate homes for the variable. + + A live range defines the interval of instructions beginning with + range_start and ending at range_end-1, and is used to specify a + range of instructions where an alias is active or "live". So, + the actual end of the range will be one less than the value of the + range_end symbol. + + Ranges do not have to be nested. Eg. Two ranges may intersect while + each range contains subranges which are not in the other range. + + There does not have to be a 1-1 mapping from range_start to + range_end symbols. Eg. Two range_starts can share the same + range_end, while one symbol's range_start can be another symbol's + range_end. + + When a variable's storage class changes (eg. from stack to register, + or from one register to another), a new symbol entry will be + added to the symbol table with stabs describing the new type, + and appropriate live ranges refering to the variable's initial + symbol index. + + For variables which are defined in the source but optimized away, + a symbol should be emitted with the live range l(0,0). + + Live ranges for aliases of a particular variable should always + be disjoint. Overlapping ranges for aliases of the same variable + will be treated as an error by the debugger, and the overlapping + range will be ignored. + + If no live range information is given, the live range will be assumed to + span the symbol's entire lexical scope. + + +New stabs string identifiers: +----------------------------- + + "id" in "#id" in the following section refers to a numeric value. + + New stab syntax for live range: l(,) + + - "#id" where #id identifies the text symbol (range symbol) to + use as the start of live range (range_start). The value for + the referenced text symbol is the starting address of the + live range. + + - "#id" where #id identifies the text symbol (range symbol) to + use as the end of live range (range_end). The value for + the referenced text symbol is ONE BYTE PAST the ending + address of the live range. + + + New stab syntax for identifying symbols. + + - "#id=" + + Uses: + :... + When used in front of a symbol name, "#id=" defines a + unique reference number for this symbol. The reference + number can be used later when defining aliases for this + symbol. + + When used as the entire stab string, "#id=" identifies this + nameless symbol as being the symbol for which "#id" refers to. + + + - "#id" where "#id" refers to the symbol for which the string + "#id=" identifies. + Uses: + :;;... + Defines an alias for the symbol identified by the reference + number ID. + l(,) + When used within a live range, "#id" refers to the text + symbol identified by "#id=" to use as the range symbol. + + - "l(,)" - specifies a live range for a + symbol. Multiple "l" specifiers can be combined to represent + mutiple live ranges, separated by semicolons. + + + + +Example: +======== + +Consider a program of the form: + + void foo(){ + int a = ...; + ... + while (b--) + c += a; + .. + d = a; + .. + } + +Assume that "a" lives in the stack at offset -8, except for inside the +loop where "a" resides in register "r5". + +The way to describe this is to create a stab for the variable "a" which +describes "a" as living in the stack and an alias for the variable "a" +which describes it as living in register "r5" in the loop. + +Let's assume that "#1" and "#2" are symbols which bound the area where +"a" lives in a register. + +The stabs to describe "a" and its alias would look like this: + + .stabs "#3=a:1",128,0,8,-8 + .stabs "#3:r1;l(#1,#2)",64,0,0,5 + + +This design implies that the debugger will keep a chain of aliases for +any given variable with aliases and that chain will be searched first +to find out if an alias is active. If no alias is active, then the +debugger will assume that the main variable is active. diff --git a/contrib/gdb-7/gdb/doc/a4rc.sed b/contrib/gdb-7/gdb/doc/a4rc.sed new file mode 100644 index 0000000000..22922904ef --- /dev/null +++ b/contrib/gdb-7/gdb/doc/a4rc.sed @@ -0,0 +1,11 @@ +/--- Papersize params:/,/--- end papersize params/c\ +%------- Papersize params:\ +%% A4 paper (297x210mm)\ +%%\ +\\totalwidth=297mm % total width of paper\ +\\totalheight=210mm % total height of paper\ +\\hmargin=5mm % horizontal margin width\ +\\vmargin=10mm % vertical margin width\ +\\secskip=.6pc % space between refcard secs\ +\\lskip=1pt % extra skip between \\sec entries\ +%------- end papersize params diff --git a/contrib/gdb-7/gdb/doc/agentexpr.texi b/contrib/gdb-7/gdb/doc/agentexpr.texi index 985954ceab..f2d51b7405 100644 --- a/contrib/gdb-7/gdb/doc/agentexpr.texi +++ b/contrib/gdb-7/gdb/doc/agentexpr.texi @@ -7,8 +7,8 @@ @c This file is part of the GDB manual. @c -@c Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010 -@c Free Software Foundation, Inc. +@c Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011 +@c Free Software Foundation, Inc. @c @c See the file gdb.texinfo for copying conditions. @@ -391,6 +391,16 @@ Exchange the top two items on the stack. @item @code{pop} (0x29): @var{a} => Discard the top value on the stack. +@item @code{pick} (0x32) @var{n}: @var{a} @dots{} @var{b} => @var{a} @dots{} @var{b} @var{a} +Duplicate an item from the stack and push it on the top of the stack. +@var{n}, a single byte, indicates the stack item to copy. If @var{n} +is zero, this is the same as @code{dup}; if @var{n} is one, it copies +the item under the top item, etc. If @var{n} exceeds the number of +items on the stack, terminate with an error. + +@item @code{rot} (0x33): @var{a} @var{b} @var{c} => @var{c} @var{b} @var{a} +Rotate the top three items on the stack. + @item @code{if_goto} (0x20) @var{offset}: @var{a} @result{} Pop an integer off the stack; if it is non-zero, branch to the given offset in the bytecode string. Otherwise, continue to the next diff --git a/contrib/gdb-7/gdb/doc/all-cfg.texi b/contrib/gdb-7/gdb/doc/all-cfg.texi index 0e96cb60b5..d469fa47a9 100644 --- a/contrib/gdb-7/gdb/doc/all-cfg.texi +++ b/contrib/gdb-7/gdb/doc/all-cfg.texi @@ -1,6 +1,6 @@ @c GDB MANUAL configuration file. @c -@c Copyright (C) 1993, 1995, 1999, 2002 Free Software Foundation, Inc. +@c Copyright (C) 1993, 1995, 1999, 2002, 2011 Free Software Foundation, Inc. @c @c NOTE: While the GDB manual is configurable (by changing these @c switches), its configuration is ***NOT*** automatically tied in to diff --git a/contrib/gdb-7/gdb/doc/annotate.texinfo b/contrib/gdb-7/gdb/doc/annotate.texinfo index 11298d9fc8..01928b7ec0 100644 --- a/contrib/gdb-7/gdb/doc/annotate.texinfo +++ b/contrib/gdb-7/gdb/doc/annotate.texinfo @@ -28,7 +28,7 @@ @copying Copyright @copyright{} 1994, 1995, 2000, 2001, 2003, 2004, 2005, 2007, -2008, 2009, 2010 Free Software Foundation, Inc. +2008, 2009, 2010, 2011 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or diff --git a/contrib/gdb-7/gdb/doc/gdb.texinfo b/contrib/gdb-7/gdb/doc/gdb.texinfo index 65d4899fd5..b6bec6a13a 100644 --- a/contrib/gdb-7/gdb/doc/gdb.texinfo +++ b/contrib/gdb-7/gdb/doc/gdb.texinfo @@ -1,7 +1,7 @@ \input texinfo @c -*-texinfo-*- -@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, -@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 -@c Free Software Foundation, Inc. +@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, +@c 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +@c 2010, 2011 Free Software Foundation, Inc. @c @c %**start of header @c makeinfo ignores cmds prev to setfilename, so its arg cannot make use @@ -101,9 +101,8 @@ ISBN 1-882114-77-9 @* @insertcopying @page -This edition of the GDB manual is dedicated to the memory of Fred -Fish. Fred was a long-standing contributor to GDB and to Free -software in general. We will miss him. +@value{GDBN} version 7.3 is dedicated to the memory of long-standing +contributor Michael Snyder. @end titlepage @page @@ -163,8 +162,15 @@ software in general. We will miss him. * GDB Bugs:: Reporting bugs in @value{GDBN} +@ifset SYSTEM_READLINE +* Command Line Editing: (rluserman). Command Line Editing +* Using History Interactively: (history). Using History Interactively +@end ifset +@ifclear SYSTEM_READLINE * Command Line Editing:: Command Line Editing * Using History Interactively:: Using History Interactively +@end ifclear +* In Memoriam:: In Memoriam * Formatting Documentation:: How to format and print @value{GDBN} documentation * Installing GDB:: Installing GDB * Maintenance Commands:: Maintenance Commands @@ -221,6 +227,9 @@ Support for D is partial. For information on D, see Support for Modula-2 is partial. For information on Modula-2, see @ref{Modula-2,,Modula-2}. +Support for OpenCL C is partial. For information on OpenCL C, see +@ref{OpenCL C,,OpenCL C}. + @cindex Pascal Debugging Pascal programs which use sets, subranges, file variables, or nested functions does not currently work. @value{GDBN} does not support @@ -1102,6 +1111,12 @@ used if possible. Run @value{GDBN} using @var{directory} as its working directory, instead of the current directory. +@item -data-directory @var{directory} +@cindex @code{--data-directory} +Run @value{GDBN} using @var{directory} as its data directory. +The data directory is where @value{GDBN} searches for its +auxiliary files. @xref{Data Files}. + @item -fullname @itemx -f @cindex @code{--fullname} @@ -1247,6 +1262,25 @@ init file, one generic in your home directory, and another, specific to the program you are debugging, in the directory where you invoke @value{GDBN}. +@item +If the command line specified a program to debug, or a process to +attach to, or a core file, @value{GDBN} loads any auto-loaded +scripts provided for the program or for its loaded shared libraries. +@xref{Auto-loading}. + +If you wish to disable the auto-loading during startup, +you must do something like the following: + +@smallexample +$ gdb -ex "set auto-load-scripts off" -ex "file myprogram" +@end smallexample + +The following does not work because the auto-loading is turned off too late: + +@smallexample +$ gdb -ex "set auto-load-scripts off" myprogram +@end smallexample + @item Reads command files specified by the @samp{-x} option. @xref{Command Files}, for more details about @value{GDBN} command files. @@ -2431,7 +2465,7 @@ You can get multiple executables into a debugging session via the systems @value{GDBN} can add inferiors to the debug session automatically by following calls to @code{fork} and @code{exec}. To remove inferiors from the debugging session use the -@w{@code{remove-inferior}} command. +@w{@code{remove-inferiors}} command. @table @code @kindex add-inferior @@ -2464,37 +2498,37 @@ Added inferior 2. You can now simply switch focus to inferior 2 and run it. -@kindex remove-inferior -@item remove-inferior @var{infno} -Removes the inferior @var{infno}. It is not possible to remove an -inferior that is running with this command. For those, use the -@code{kill} or @code{detach} command first. +@kindex remove-inferiors +@item remove-inferiors @var{infno}@dots{} +Removes the inferior or inferiors @var{infno}@dots{}. It is not +possible to remove an inferior that is running with this command. For +those, use the @code{kill} or @code{detach} command first. @end table To quit debugging one of the running inferiors that is not the current inferior, you can either detach from it by using the @w{@code{detach inferior}} command (allowing it to run independently), or kill it -using the @w{@code{kill inferior}} command: +using the @w{@code{kill inferiors}} command: @table @code -@kindex detach inferior @var{infno} -@item detach inferior @var{infno} -Detach from the inferior identified by @value{GDBN} inferior number -@var{infno}. Note that the inferior's entry still stays on the list -of inferiors shown by @code{info inferiors}, but its Description will -show @samp{}. +@kindex detach inferiors @var{infno}@dots{} +@item detach inferior @var{infno}@dots{} +Detach from the inferior or inferiors identified by @value{GDBN} +inferior number(s) @var{infno}@dots{}. Note that the inferior's entry +still stays on the list of inferiors shown by @code{info inferiors}, +but its Description will show @samp{}. -@kindex kill inferior @var{infno} -@item kill inferior @var{infno} -Kill the inferior identified by @value{GDBN} inferior number -@var{infno}. Note that the inferior's entry still stays on the list -of inferiors shown by @code{info inferiors}, but its Description will -show @samp{}. +@kindex kill inferiors @var{infno}@dots{} +@item kill inferiors @var{infno}@dots{} +Kill the inferior or inferiors identified by @value{GDBN} inferior +number(s) @var{infno}@dots{}. Note that the inferior's entry still +stays on the list of inferiors shown by @code{info inferiors}, but its +Description will show @samp{}. @end table After the successful completion of a command such as @code{detach}, -@code{detach inferior}, @code{kill} or @code{kill inferior}, or after +@code{detach inferiors}, @code{kill} or @code{kill inferiors}, or after a normal process exit, the inferior is still valid and listed with @code{info inferiors}, ready to be restarted. @@ -2649,7 +2683,7 @@ whose form varies depending on the particular system. For example, on @sc{gnu}/Linux, you might see @smallexample -[New Thread 46912507313328 (LWP 25582)] +[New Thread 0x41e02940 (LWP 25582)] @end smallexample @noindent @@ -2672,9 +2706,11 @@ number---always a single integer---with each thread in your program. @table @code @kindex info threads -@item info threads -Display a summary of all threads currently in your -program. @value{GDBN} displays for each thread (in this order): +@item info threads @r{[}@var{id}@dots{}@r{]} +Display a summary of all threads currently in your program. Optional +argument @var{id}@dots{} is one or more thread ids separated by spaces, and +means to print information only about the specified thread or threads. +@value{GDBN} displays for each thread (in this order): @enumerate @item @@ -2683,6 +2719,11 @@ the thread number assigned by @value{GDBN} @item the target system's thread identifier (@var{systag}) +@item +the thread's name, if one is known. A thread can either be named by +the user (see @code{thread name}, below), or, in some cases, by the +program itself. + @item the current stack frame summary for that thread @end enumerate @@ -2697,70 +2738,13 @@ For example, @smallexample (@value{GDBP}) info threads - 3 process 35 thread 27 0x34e5 in sigpause () - 2 process 35 thread 23 0x34e5 in sigpause () -* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8) + Id Target Id Frame + 3 process 35 thread 27 0x34e5 in sigpause () + 2 process 35 thread 23 0x34e5 in sigpause () +* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8) at threadtest.c:68 @end smallexample -On HP-UX systems: - -@cindex debugging multithreaded programs (on HP-UX) -@cindex thread identifier (GDB), on HP-UX -For debugging purposes, @value{GDBN} associates its own thread -number---a small integer assigned in thread-creation order---with each -thread in your program. - -@cindex @code{New} @var{systag} message, on HP-UX -@cindex thread identifier (system), on HP-UX -@c FIXME-implementors!! It would be more helpful if the [New...] message -@c included GDB's numeric thread handle, so you could just go to that -@c thread without first checking `info threads'. -Whenever @value{GDBN} detects a new thread in your program, it displays -both @value{GDBN}'s thread number and the target system's identification for the thread with a message in the -form @samp{[New @var{systag}]}. @var{systag} is a thread identifier -whose form varies depending on the particular system. For example, on -HP-UX, you see - -@smallexample -[New thread 2 (system thread 26594)] -@end smallexample - -@noindent -when @value{GDBN} notices a new thread. - -@table @code -@kindex info threads (HP-UX) -@item info threads -Display a summary of all threads currently in your -program. @value{GDBN} displays for each thread (in this order): - -@enumerate -@item the thread number assigned by @value{GDBN} - -@item the target system's thread identifier (@var{systag}) - -@item the current stack frame summary for that thread -@end enumerate - -@noindent -An asterisk @samp{*} to the left of the @value{GDBN} thread number -indicates the current thread. - -For example, -@end table -@c end table here to get a little more width for example - -@smallexample -(@value{GDBP}) info threads - * 3 system thread 26607 worker (wptr=0x7b09c318 "@@") \@* - at quicksort.c:137 - 2 system thread 26606 0x7b0030d8 in __ksleep () \@* - from /usr/lib/libc.2 - 1 system thread 27905 0x7b003498 in _brk () \@* - from /usr/lib/libc.2 -@end smallexample - On Solaris, you can display more information about user threads with a Solaris-specific command: @@ -2781,10 +2765,10 @@ shown in the first field of the @samp{info threads} display. you selected, and its current stack frame summary: @smallexample -@c FIXME!! This example made up; find a @value{GDBN} w/threads and get real one (@value{GDBP}) thread 2 -[Switching to process 35 thread 23] -0x34e5 in sigpause () +[Switching to thread 2 (Thread 0xb7fdab70 (LWP 12747))] +#0 some_function (ignore=0x0) at example.c:8 +8 printf ("hello\n"); @end smallexample @noindent @@ -2801,7 +2785,7 @@ information on convenience variables. @kindex thread apply @cindex apply command to several threads -@item thread apply [@var{threadno}] [@var{all}] @var{command} +@item thread apply [@var{threadno} | all] @var{command} The @code{thread apply} command allows you to apply the named @var{command} to one or more threads. Specify the numbers of the threads that you want affected with the command argument @@ -2810,6 +2794,38 @@ shown in the first field of the @samp{info threads} display; or it could be a range of thread numbers, as in @code{2-4}. To apply a command to all threads, type @kbd{thread apply all @var{command}}. +@kindex thread name +@cindex name a thread +@item thread name [@var{name}] +This command assigns a name to the current thread. If no argument is +given, any existing user-specified name is removed. The thread name +appears in the @samp{info threads} display. + +On some systems, such as @sc{gnu}/Linux, @value{GDBN} is able to +determine the name of the thread as given by the OS. On these +systems, a name specified with @samp{thread name} will override the +system-give name, and removing the user-specified name will cause +@value{GDBN} to once again display the system-specified name. + +@kindex thread find +@cindex search for a thread +@item thread find [@var{regexp}] +Search for and display thread ids whose name or @var{systag} +matches the supplied regular expression. + +As well as being the complement to the @samp{thread name} command, +this command also allows you to identify a thread by its target +@var{systag}. For instance, on @sc{gnu}/Linux, the target @var{systag} +is the LWP id. + +@smallexample +(@value{GDBN}) thread find 26688 +Thread 4 has target id 'Thread 0x41e02940 (LWP 26688)' +(@value{GDBN}) info thread 4 + Id Target Id Frame + 4 Thread 0x41e02940 (LWP 26688) 0x00000031ca6cd372 in select () +@end smallexample + @kindex set print thread-events @cindex print messages on thread start and exit @item set print thread-events @@ -2864,6 +2880,14 @@ only on some platforms. @kindex show libthread-db-search-path @item show libthread-db-search-path Display current libthread_db search path. + +@kindex set debug libthread-db +@kindex show debug libthread-db +@cindex debugging @code{libthread_db} +@item set debug libthread-db +@itemx show debug libthread-db +Turns on or off display of @code{libthread_db}-related events. +Use @code{1} to enable, @code{0} to disable. @end table @node Forks @@ -2962,8 +2986,8 @@ to another by using the @code{inferior} command (@pxref{Inferiors and Programs, ,Debugging Multiple Inferiors and Programs}). To quit debugging one of the forked processes, you can either detach -from it by using the @w{@code{detach inferior}} command (allowing it -to run independently), or kill it using the @w{@code{kill inferior}} +from it by using the @w{@code{detach inferiors}} command (allowing it +to run independently), or kill it using the @w{@code{kill inferiors}} command. @xref{Inferiors and Programs, ,Debugging Multiple Inferiors and Programs}. @@ -3414,12 +3438,12 @@ optionally be surrounded by spaces. @kindex info breakpoints @cindex @code{$_} and @code{info breakpoints} -@item info breakpoints @r{[}@var{n}@r{]} -@itemx info break @r{[}@var{n}@r{]} +@item info breakpoints @r{[}@var{n}@dots{}@r{]} +@itemx info break @r{[}@var{n}@dots{}@r{]} Print a table of all breakpoints, watchpoints, and catchpoints set and not deleted. Optional argument @var{n} means print information only -about the specified breakpoint (or watchpoint or catchpoint). For -each breakpoint, following columns are printed: +about the specified breakpoint(s) (or watchpoint(s) or catchpoint(s)). +For each breakpoint, following columns are printed: @table @emph @item Breakpoint Numbers @@ -3703,7 +3727,7 @@ watchpoints, which do not slow down the running of your program. @table @code @kindex watch -@item watch @var{expr} @r{[}thread @var{threadnum}@r{]} +@item watch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} Set a watchpoint for an expression. @value{GDBN} will break when the expression @var{expr} is written into by the program and its value changes. The simplest (and the most popular) use of this command is @@ -3720,18 +3744,27 @@ change the value of @var{expr}, @value{GDBN} will not break. Note that watchpoints restricted to a single thread in this way only work with Hardware Watchpoints. +Ordinarily a watchpoint respects the scope of variables in @var{expr} +(see below). The @code{-location} argument tells @value{GDBN} to +instead watch the memory referred to by @var{expr}. In this case, +@value{GDBN} will evaluate @var{expr}, take the address of the result, +and watch the memory at that address. The type of the result is used +to determine the size of the watched memory. If the expression's +result does not have an address, then @value{GDBN} will print an +error. + @kindex rwatch -@item rwatch @var{expr} @r{[}thread @var{threadnum}@r{]} +@item rwatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} Set a watchpoint that will break when the value of @var{expr} is read by the program. @kindex awatch -@item awatch @var{expr} @r{[}thread @var{threadnum}@r{]} +@item awatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} Set a watchpoint that will break when @var{expr} is either read from or written into by the program. -@kindex info watchpoints @r{[}@var{n}@r{]} -@item info watchpoints +@kindex info watchpoints @r{[}@var{n}@dots{}@r{]} +@item info watchpoints @r{[}@var{n}@dots{}@r{]} This command prints a list of watchpoints, using the same format as @code{info break} (@pxref{Set Breaks}). @end table @@ -5939,7 +5972,7 @@ only if it is a scalar (integer, pointer, enumeration, etc). See command @kbd{set print frame-arguments} in @ref{Print Settings} for more details on how to configure the way function parameter values are printed. -@cindex value optimized out, in backtrace +@cindex optimized out, in backtrace @cindex function call arguments, optimized out If your program was compiled with optimizations, some compilers will optimize away arguments passed to functions if those arguments are @@ -5953,8 +5986,8 @@ such a backtrace might look like: @group #0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8) at builtin.c:993 -#1 0x6e38 in expand_macro (sym=) at macro.c:242 -#2 0x6840 in expand_token (obs=0x0, t=, td=0xf7fffb08) +#1 0x6e38 in expand_macro (sym=) at macro.c:242 +#2 0x6840 in expand_token (obs=0x0, t=, td=0xf7fffb08) at macro.c:71 (More stack frames follow...) @end group @@ -5962,7 +5995,7 @@ such a backtrace might look like: @noindent The values of arguments that were not saved in their stack frames are -shown as @samp{}. +shown as @samp{}. If you need to display the values of such optimized-out arguments, either deduce that from other variables whose values depend on the one @@ -6328,12 +6361,22 @@ Specifies the line @var{linenum} in the source file @var{filename}. Specifies the line that begins the body of the function @var{function}. For example, in C, this is the line with the open brace. +@item @var{function}:@var{label} +Specifies the line where @var{label} appears in @var{function}. + @item @var{filename}:@var{function} Specifies the line that begins the body of the function @var{function} in the file @var{filename}. You only need the file name with a function name to avoid ambiguity when there are identically named functions in different source files. +@item @var{label} +Specifies the line at which the label named @var{label} appears. +@value{GDBN} searches for the label in the function corresponding to +the currently selected stack frame. If there is no current selected +stack frame (for instance, if the inferior is not running), then +@value{GDBN} will not search for a label. + @item *@var{address} Specifies the program address @var{address}. For line-oriented commands, such as @code{list} and @code{edit}, this specifies a source @@ -6596,6 +6639,11 @@ Reset the source path to its default value (@samp{$cdir:$cwd} on Unix systems). @c RET-repeat for @code{directory} is explicitly disabled, but since @c repeating it would be a no-op we do not say that. (thanks to RMS) +@item set directories @var{path-list} +@kindex set directories +Set the source path to @var{path-list}. +@samp{$cdir:$cwd} are added if missing. + @item show directories @kindex show directories Print the source path: show which directories it contains. @@ -7602,7 +7650,11 @@ is a common name for the program counter; @pxref{Registers, ,Registers}). @kindex undisplay @item undisplay @var{dnums}@dots{} @itemx delete display @var{dnums}@dots{} -Remove item numbers @var{dnums} from the list of expressions to display. +Remove items from the list of expressions to display. Specify the +numbers of the displays that you want affected with the command +argument @var{dnums}. It can be a single display number, one of the +numbers shown in the first field of the @samp{info display} display; +or it could be a range of display numbers, as in @code{2-4}. @code{undisplay} does not repeat if you press @key{RET} after using it. (Otherwise you would just get the error @samp{No display number @dots{}}.) @@ -7611,12 +7663,20 @@ Remove item numbers @var{dnums} from the list of expressions to display. @item disable display @var{dnums}@dots{} Disable the display of item numbers @var{dnums}. A disabled display item is not printed automatically, but is not forgotten. It may be -enabled again later. +enabled again later. Specify the numbers of the displays that you +want affected with the command argument @var{dnums}. It can be a +single display number, one of the numbers shown in the first field of +the @samp{info display} display; or it could be a range of display +numbers, as in @code{2-4}. @kindex enable display @item enable display @var{dnums}@dots{} Enable display of item numbers @var{dnums}. It becomes effective once again in auto display of its expression, until you specify otherwise. +Specify the numbers of the displays that you want affected with the +command argument @var{dnums}. It can be a single display number, one +of the numbers shown in the first field of the @samp{info display} +display; or it could be a range of display numbers, as in @code{2-4}. @item display Display the current values of the expressions on the list, just as is @@ -8103,8 +8163,60 @@ Show whether C@t{++} virtual function tables are pretty printed, or not. Python code. It greatly simplifies the display of complex objects. This mechanism works for both MI and the CLI. -For example, here is how a C@t{++} @code{std::string} looks without a -pretty-printer: +@menu +* Pretty-Printer Introduction:: Introduction to pretty-printers +* Pretty-Printer Example:: An example pretty-printer +* Pretty-Printer Commands:: Pretty-printer commands +@end menu + +@node Pretty-Printer Introduction +@subsection Pretty-Printer Introduction + +When @value{GDBN} prints a value, it first sees if there is a pretty-printer +registered for the value. If there is then @value{GDBN} invokes the +pretty-printer to print the value. Otherwise the value is printed normally. + +Pretty-printers are normally named. This makes them easy to manage. +The @samp{info pretty-printer} command will list all the installed +pretty-printers with their names. +If a pretty-printer can handle multiple data types, then its +@dfn{subprinters} are the printers for the individual data types. +Each such subprinter has its own name. +The format of the name is @var{printer-name};@var{subprinter-name}. + +Pretty-printers are installed by @dfn{registering} them with @value{GDBN}. +Typically they are automatically loaded and registered when the corresponding +debug information is loaded, thus making them available without having to +do anything special. + +There are three places where a pretty-printer can be registered. + +@itemize @bullet +@item +Pretty-printers registered globally are available when debugging +all inferiors. + +@item +Pretty-printers registered with a program space are available only +when debugging that program. +@xref{Progspaces In Python}, for more details on program spaces in Python. + +@item +Pretty-printers registered with an objfile are loaded and unloaded +with the corresponding objfile (e.g., shared library). +@xref{Objfiles In Python}, for more details on objfiles in Python. +@end itemize + +@xref{Selecting Pretty-Printers}, for further information on how +pretty-printers are selected, + +@xref{Writing a Pretty-Printer}, for implementing pretty printers +for new types. + +@node Pretty-Printer Example +@subsection Pretty-Printer Example + +Here is how a C@t{++} @code{std::string} looks without a pretty-printer: @smallexample (@value{GDBP}) print s @@ -8129,8 +8241,91 @@ With a pretty-printer for @code{std::string} only the contents are printed: $2 = "abcd" @end smallexample -For implementing pretty printers for new types you should read the Python API -details (@pxref{Pretty Printing API}). +@node Pretty-Printer Commands +@subsection Pretty-Printer Commands +@cindex pretty-printer commands + +@table @code +@kindex info pretty-printer +@item info pretty-printer [@var{object-regexp} [@var{name-regexp}]] +Print the list of installed pretty-printers. +This includes disabled pretty-printers, which are marked as such. + +@var{object-regexp} is a regular expression matching the objects +whose pretty-printers to list. +Objects can be @code{global}, the program space's file +(@pxref{Progspaces In Python}), +and the object files within that program space (@pxref{Objfiles In Python}). +@xref{Selecting Pretty-Printers}, for details on how @value{GDBN} +looks up a printer from these three objects. + +@var{name-regexp} is a regular expression matching the name of the printers +to list. + +@kindex disable pretty-printer +@item disable pretty-printer [@var{object-regexp} [@var{name-regexp}]] +Disable pretty-printers matching @var{object-regexp} and @var{name-regexp}. +A disabled pretty-printer is not forgotten, it may be enabled again later. + +@kindex enable pretty-printer +@item enable pretty-printer [@var{object-regexp} [@var{name-regexp}]] +Enable pretty-printers matching @var{object-regexp} and @var{name-regexp}. +@end table + +Example: + +Suppose we have three pretty-printers installed: one from library1.so +named @code{foo} that prints objects of type @code{foo}, and +another from library2.so named @code{bar} that prints two types of objects, +@code{bar1} and @code{bar2}. + +@smallexample +(gdb) info pretty-printer +library1.so: + foo +library2.so: + bar + bar1 + bar2 +(gdb) info pretty-printer library2 +library2.so: + bar + bar1 + bar2 +(gdb) disable pretty-printer library1 +1 printer disabled +2 of 3 printers enabled +(gdb) info pretty-printer +library1.so: + foo [disabled] +library2.so: + bar + bar1 + bar2 +(gdb) disable pretty-printer library2 bar:bar1 +1 printer disabled +1 of 3 printers enabled +(gdb) info pretty-printer library2 +library1.so: + foo [disabled] +library2.so: + bar + bar1 [disabled] + bar2 +(gdb) disable pretty-printer library2 bar +1 printer disabled +0 of 3 printers enabled +(gdb) info pretty-printer library2 +library1.so: + foo [disabled] +library2.so: + bar [disabled] + bar1 [disabled] + bar2 +@end smallexample + +Note that for @code{bar} the entire printer can be disabled, +as can each individual subprinter. @node Value History @section Value History @@ -8891,7 +9086,7 @@ automatically determine the appropriate host character set. In this case, @value{GDBN} uses @samp{UTF-8}. @value{GDBN} can only use certain character sets as its host character -set. If you type @kbd{@w{set target-charset @key{TAB}@key{TAB}}}, +set. If you type @kbd{@w{set host-charset @key{TAB}@key{TAB}}}, @value{GDBN} will list the host character sets it supports. @item set charset @var{charset} @@ -9637,7 +9832,7 @@ investigating what the target is actually doing. @value{GDBN}'s support for static tracing includes being able to list instrumentation points, and attach them with @value{GDBN} defined high level tracepoints that expose the whole range of convenience of -@value{GDBN}'s tracepoints support. Namelly, support for collecting +@value{GDBN}'s tracepoints support. Namely, support for collecting registers values and values of global or local (to the instrumentation point) variables; tracepoint conditions and trace state variables. The act of installing a @value{GDBN} static tracepoint on an @@ -9883,7 +10078,7 @@ just as with breakpoints. Unlike breakpoint conditions, @value{GDBN} does not actually evaluate the conditional expression itself. Instead, @value{GDBN} encodes the -expression into an agent expression (@pxref{Agent Expressions} +expression into an agent expression (@pxref{Agent Expressions}) suitable for execution on the target, independently of @value{GDBN}. Global variables become raw memory locations, locals become stack accesses, and so forth. @@ -10103,10 +10298,10 @@ tracepoint hit. @subsection Listing Tracepoints @table @code -@kindex info tracepoints -@kindex info tp +@kindex info tracepoints @r{[}@var{n}@dots{}@r{]} +@kindex info tp @r{[}@var{n}@dots{}@r{]} @cindex information about tracepoints -@item info tracepoints @r{[}@var{num}@r{]} +@item info tracepoints @r{[}@var{num}@dots{}@r{]} Display information about the tracepoint @var{num}. If you don't specify a tracepoint number, displays information about all the tracepoints defined so far. The format is similar to that used for @@ -10289,7 +10484,7 @@ frames, oldest first, until there is enough room to continue collecting. This is especially useful if your tracepoints are being hit too often, and your trace gets terminated prematurely because the buffer is full. To ask for a circular trace buffer, simply set -@samp{circular_trace_buffer} to on. You can set this at any time, +@samp{circular-trace-buffer} to on. You can set this at any time, including during tracing; if the agent can do it, it will change buffer handling on the fly, otherwise it will not take effect until the next run. @@ -11452,7 +11647,7 @@ being set automatically by @value{GDBN}. @node Supported Languages @section Supported Languages -@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal, +@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, OpenCL C, Pascal, assembly, Modula-2, and Ada. @c This is false ... Some @value{GDBN} features may be used in expressions regardless of the @@ -11473,6 +11668,7 @@ language reference or tutorial. * C:: C and C@t{++} * D:: D * Objective-C:: Objective-C +* OpenCL C:: OpenCL C * Fortran:: Fortran * Pascal:: Pascal * Modula-2:: Modula-2 @@ -12119,6 +12315,42 @@ the description of an object. However, this command may only work with certain Objective-C libraries that have a particular hook function, @code{_NSPrintForDebugger}, defined. +@node OpenCL C +@subsection OpenCL C + +@cindex OpenCL C +This section provides information about @value{GDBN}s OpenCL C support. + +@menu +* OpenCL C Datatypes:: +* OpenCL C Expressions:: +* OpenCL C Operators:: +@end menu + +@node OpenCL C Datatypes +@subsubsection OpenCL C Datatypes + +@cindex OpenCL C Datatypes +@value{GDBN} supports the builtin scalar and vector datatypes specified +by OpenCL 1.1. In addition the half- and double-precision floating point +data types of the @code{cl_khr_fp16} and @code{cl_khr_fp64} OpenCL +extensions are also known to @value{GDBN}. + +@node OpenCL C Expressions +@subsubsection OpenCL C Expressions + +@cindex OpenCL C Expressions +@value{GDBN} supports accesses to vector components including the access as +lvalue where possible. Since OpenCL C is based on C99 most C expressions +supported by @value{GDBN} can be used as well. + +@node OpenCL C Operators +@subsubsection OpenCL C Operators + +@cindex OpenCL C Operators +@value{GDBN} supports the operators specified by OpenCL 1.1 for scalar and +vector data types. + @node Fortran @subsection Fortran @cindex Fortran-specific support in @value{GDBN} @@ -12837,6 +13069,8 @@ to be difficult. * Stopping Before Main Program:: Debugging the program during elaboration. * Ada Tasks:: Listing and setting breakpoints in tasks. * Ada Tasks and Core Files:: Tasking Support when Debugging Core Files +* Ravenscar Profile:: Tasking Support when using the Ravenscar + Profile * Ada Glitches:: Known peculiarities of Ada mode. @end menu @@ -13387,6 +13621,36 @@ privileges, using the command @samp{"set write on"} (@pxref{Patching}). Under these circumstances, you should make a backup copy of the core file before inspecting it with @value{GDBN}. +@node Ravenscar Profile +@subsubsection Tasking Support when using the Ravenscar Profile +@cindex Ravenscar Profile + +The @dfn{Ravenscar Profile} is a subset of the Ada tasking features, +specifically designed for systems with safety-critical real-time +requirements. + +@table @code +@kindex set ravenscar task-switching on +@cindex task switching with program using Ravenscar Profile +@item set ravenscar task-switching on +Allows task switching when debugging a program that uses the Ravenscar +Profile. This is the default. + +@kindex set ravenscar task-switching off +@item set ravenscar task-switching off +Turn off task switching when debugging a program that uses the Ravenscar +Profile. This is mostly intended to disable the code that adds support +for the Ravenscar Profile, in case a bug in either @value{GDBN} or in +the Ravenscar runtime is preventing @value{GDBN} from working properly. +To be effective, this command should be run before the program is started. + +@kindex show ravenscar task-switching +@item show ravenscar task-switching +Show whether it is possible to switch from task to task in a program +using the Ravenscar Profile. + +@end table + @node Ada Glitches @subsubsection Known Peculiarities of Ada Mode @cindex Ada, problems @@ -13398,13 +13662,6 @@ some of which will be fixed with planned future releases of the debugger and the GNU Ada compiler. @itemize @bullet -@item -Currently, the debugger -has insufficient information to determine whether certain pointers represent -pointers to objects or the objects themselves. -Thus, the user may have to tack an extra @code{.all} after an expression -to get it printed properly. - @item Static constants that the compiler chooses not to materialize as objects in storage are invisible to the debugger. @@ -14308,6 +14565,7 @@ program. To debug a core dump of a previous run, you must also tell @menu * Files:: Commands to specify files * Separate Debug Files:: Debugging information in separate files +* Index Files:: Index files speed up GDB * Symbol Errors:: Errors reading symbol files * Data Files:: GDB data files @end menu @@ -15197,6 +15455,45 @@ gnu_debuglink_crc32 (unsigned long crc, This computation does not apply to the ``build ID'' method. +@node Index Files +@section Index Files Speed Up @value{GDBN} +@cindex index files +@cindex @samp{.gdb_index} section + +When @value{GDBN} finds a symbol file, it scans the symbols in the +file in order to construct an internal symbol table. This lets most +@value{GDBN} operations work quickly---at the cost of a delay early +on. For large programs, this delay can be quite lengthy, so +@value{GDBN} provides a way to build an index, which speeds up +startup. + +The index is stored as a section in the symbol file. @value{GDBN} can +write the index to a file, then you can put it into the symbol file +using @command{objcopy}. + +To create an index file, use the @code{save gdb-index} command: + +@table @code +@item save gdb-index @var{directory} +@kindex save gdb-index +Create an index file for each symbol file currently known by +@value{GDBN}. Each file is named after its corresponding symbol file, +with @samp{.gdb-index} appended, and is written into the given +@var{directory}. +@end table + +Once you have created an index file you can merge it into your symbol +file, here named @file{symfile}, using @command{objcopy}: + +@smallexample +$ objcopy --add-section .gdb_index=symfile.gdb-index \ + --set-section-flags .gdb_index=readonly symfile symfile +@end smallexample + +There are currently some limitation on indices. They only work when +for DWARF debugging information, not stabs. And, they do not +currently work for programs using Ada. + @node Symbol Errors @section Errors Reading Symbol Files @@ -15316,6 +15613,10 @@ You can set the default data directory by using the configure-time automatically if the installed @value{GDBN} is moved to a new location. +The data directory may also be specified with the +@code{--data-directory} command line option. +@xref{Mode Options}. + @node Targets @chapter Specifying a Debugging Target @@ -15369,33 +15670,20 @@ and @code{show architecture}. @cindex active targets @cindex multiple targets -There are three classes of targets: processes, core files, and -executable files. @value{GDBN} can work concurrently on up to three -active targets, one in each class. This allows you to (for example) -start a process and inspect its activity without abandoning your work on -a core file. - -For example, if you execute @samp{gdb a.out}, then the executable file -@code{a.out} is the only active target. If you designate a core file as -well---presumably from a prior run that crashed and coredumped---then -@value{GDBN} has two active targets and uses them in tandem, looking -first in the corefile target, then in the executable file, to satisfy -requests for memory addresses. (Typically, these two classes of target -are complementary, since core files contain only a program's -read-write memory---variables and so on---plus machine status, while -executable files contain only the program text and initialized data.) - -When you type @code{run}, your executable file becomes an active process -target as well. When a process target is active, all @value{GDBN} -commands requesting memory addresses refer to that target; addresses in -an active core file or executable file target are obscured while the -process target is active. - -Use the @code{core-file} and @code{exec-file} commands to select a new -core file or executable target (@pxref{Files, ,Commands to Specify -Files}). To specify as a target a process that is already running, use -the @code{attach} command (@pxref{Attach, ,Debugging an Already-running -Process}). +There are multiple classes of targets such as: processes, executable files or +recording sessions. Core files belong to the process class, making core file +and process mutually exclusive. Otherwise, @value{GDBN} can work concurrently +on multiple active targets, one in each class. This allows you to (for +example) start a process and inspect its activity, while still having access to +the executable file after the process finishes. Or if you start process +recording (@pxref{Reverse Execution}) and @code{reverse-step} there, you are +presented a virtual layer of the recording target, while the process target +remains stopped at the chronologically last point of the process execution. + +Use the @code{core-file} and @code{exec-file} commands to select a new core +file or executable target (@pxref{Files, ,Commands to Specify Files}). To +specify as a target a process that is already running, use the @code{attach} +command (@pxref{Attach, ,Debugging an Already-running Process}). @node Target Commands @section Commands for Managing Targets @@ -16446,6 +16734,10 @@ are: @item @code{query-attached} @tab @code{qAttached} @tab Querying remote process attach state. + +@item @code{traceframe-info} +@tab @code{qXfer:traceframe-info:read} +@tab Traceframe info @end multitable @node Remote Stub @@ -18430,13 +18722,47 @@ implement in hardware simple hardware watchpoint conditions of the form: if @var{ADDRESS|VARIABLE} == @var{CONSTANT EXPRESSION} @end smallexample -The DVC register will be automatically used whenever @value{GDBN} detects -such pattern in a condition expression. This feature is available in native -@value{GDBN} running on a Linux kernel version 2.6.34 or newer. +The DVC register will be automatically used when @value{GDBN} detects +such pattern in a condition expression, and the created watchpoint uses one +debug register (either the @code{exact-watchpoints} option is on and the +variable is scalar, or the variable has a length of one byte). This feature +is available in native @value{GDBN} running on a Linux kernel version 2.6.34 +or newer. + +When running on PowerPC embedded processors, @value{GDBN} automatically uses +ranged hardware watchpoints, unless the @code{exact-watchpoints} option is on, +in which case watchpoints using only one debug register are created when +watching variables of scalar types. + +You can create an artificial array to watch an arbitrary memory +region using one of the following commands (@pxref{Expressions}): + +@smallexample +(@value{GDBP}) watch *((char *) @var{address})@@@var{length} +(@value{GDBP}) watch @{char[@var{length}]@} @var{address} +@end smallexample + +@cindex ranged breakpoint +PowerPC embedded processors support hardware accelerated +@dfn{ranged breakpoints}. A ranged breakpoint stops execution of +the inferior whenever it executes an instruction at any address within +the range it specifies. To set a ranged breakpoint in @value{GDBN}, +use the @code{break-range} command. @value{GDBN} provides the following PowerPC-specific commands: @table @code +@kindex break-range +@item break-range @var{start-location}, @var{end-location} +Set a breakpoint for an address range. +@var{start-location} and @var{end-location} can specify a function name, +a line number, an offset of lines from the current line or from the start +location, or an address of an instruction (see @ref{Specify Location}, +for a list of all the possible ways to specify a @var{location}.) +The breakpoint will stop execution of the inferior whenever it +executes an instruction at any address within the specified range, +(including @var{start-location} and @var{end-location}.) + @kindex set powerpc @item set powerpc soft-float @itemx show powerpc soft-float @@ -18453,6 +18779,12 @@ arguments and return values. The valid options are @samp{auto}; registers. By default, @value{GDBN} selects the calling convention based on the selected architecture and the provided executable file. +@item set powerpc exact-watchpoints +@itemx show powerpc exact-watchpoints +Allow @value{GDBN} to use only one debug register when watching a variable +of scalar type, thus assuming that the variable is accessed through the +address of its first byte. + @kindex target dink32 @item target dink32 @var{dev} DINK32 ROM monitor. @@ -19151,7 +19483,13 @@ Disable command line editing. Show whether command line editing is enabled. @end table -@xref{Command Line Editing}, for more details about the Readline +@ifset SYSTEM_READLINE +@xref{Command Line Editing, , , rluserman, GNU Readline Library}, +@end ifset +@ifclear SYSTEM_READLINE +@xref{Command Line Editing}, +@end ifclear +for more details about the Readline interface. Users unfamiliar with @sc{gnu} Emacs or @code{vi} are encouraged to read that chapter. @@ -19165,8 +19503,14 @@ happened. Use these commands to manage the @value{GDBN} command history facility. @value{GDBN} uses the @sc{gnu} History library, a part of the Readline -package, to provide the history facility. @xref{Using History -Interactively}, for the detailed description of the History library. +package, to provide the history facility. +@ifset SYSTEM_READLINE +@xref{Using History Interactively, , , history, GNU History Library}, +@end ifset +@ifclear SYSTEM_READLINE +@xref{Using History Interactively}, +@end ifclear +for the detailed description of the History library. To issue a command to @value{GDBN} without affecting certain aspects of the state which is seen by users, prefix it with @samp{server } @@ -19218,7 +19562,13 @@ This defaults to the value of the environment variable @end table History expansion assigns special meaning to the character @kbd{!}. -@xref{Event Designators}, for more details. +@ifset SYSTEM_READLINE +@xref{Event Designators, , , history, GNU History Library}, +@end ifset +@ifclear SYSTEM_READLINE +@xref{Event Designators}, +@end ifclear +for more details. @cindex history expansion, turn on/off Since @kbd{!} is also the logical not operator in C, history expansion @@ -19599,6 +19949,16 @@ Display debugging messages about inner workings of the AIX thread module. @item show debug aix-thread Show the current state of AIX thread debugging info display. +@item set debug check-physname +@cindex physname +Check the results of the ``physname'' computation. When reading DWARF +debugging information for C@t{++}, @value{GDBN} attempts to compute +each entity's name. @value{GDBN} can do this computation in two +different ways, depending on exactly what information is present. +When enabled, this setting causes @value{GDBN} to compute the names +both ways and display any discrepancies. +@item show debug check-physname +Show the current state of ``physname'' checking. @item set debug dwarf2-die @cindex DWARF2 DIEs Dump DWARF2 DIEs after they are read in. @@ -19646,6 +20006,11 @@ The default is off. @file{infrun.c} contains GDB's runtime state machine used for implementing operations such as single-stepping the inferior. @item show debug infrun Displays the current state of @value{GDBN} inferior debugging. +@item set debug jit +@cindex just-in-time compilation, debugging messages +Turns on or off debugging messages from JIT debug support. +@item show debug jit +Displays the current state of @value{GDBN} JIT debugging. @item set debug lin-lwp @cindex @sc{gnu}/Linux LWP debug messages @cindex Linux lightweight processes @@ -19743,10 +20108,14 @@ Displays the current state of XML debugging messages. @table @code @kindex set interactive-mode @item set interactive-mode -If @code{on}, forces @value{GDBN} to operate interactively. -If @code{off}, forces @value{GDBN} to operate non-interactively, -If @code{auto} (the default), @value{GDBN} guesses which mode to use, -based on whether the debugger was started in a terminal or not. +If @code{on}, forces @value{GDBN} to assume that GDB was started +in a terminal. In practice, this means that @value{GDBN} should wait +for the user to answer queries generated by commands entered at +the command prompt. If @code{off}, forces @value{GDBN} to operate +in the opposite mode, and it uses the default answers to all queries. +If @code{auto} (the default), @value{GDBN} tries to determine whether +its standard input is a terminal, and works in interactive-mode if it +is, non-interactively otherwise. In the vast majority of cases, the debugger should be able to guess correctly which mode should be used. But this setting can be useful @@ -20310,7 +20679,8 @@ Python programming language}. This feature is available only if @cindex python directory Python scripts used by @value{GDBN} should be installed in @file{@var{data-directory}/python}, where @var{data-directory} is -the data directory as determined at @value{GDBN} startup (@pxref{Data Files}). This directory, known as the @dfn{python directory}, +the data directory as determined at @value{GDBN} startup (@pxref{Data Files}). +This directory, known as the @dfn{python directory}, is automatically added to the Python Search Path in order to allow the Python interpreter to locate all scripts installed at this location. @@ -20318,6 +20688,7 @@ the Python interpreter to locate all scripts installed at this location. * Python Commands:: Accessing Python from @value{GDBN}. * Python API:: Accessing @value{GDBN} from Python. * Auto-loading:: Automatically loading Python code. +* Python modules:: Python modules provided by @value{GDBN}. @end menu @node Python Commands @@ -20394,13 +20765,14 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. @menu * Basic Python:: Basic Python Functions. -* Exception Handling:: -* Values From Inferior:: +* Exception Handling:: How Python exceptions are translated. +* Values From Inferior:: Python representation of values. * Types In Python:: Python representation of types. * Pretty Printing API:: Pretty-printing values. * Selecting Pretty-Printers:: How GDB chooses a pretty-printer. -* Disabling Pretty-Printers:: Disabling broken printers. +* Writing a Pretty-Printer:: Writing a Pretty-Printer. * Inferiors In Python:: Python representation of inferiors (processes) +* Events In Python:: Listening for events from @value{GDBN}. * Threads In Python:: Accessing inferior threads from Python. * Commands In Python:: Implementing new commands in Python. * Parameters In Python:: Adding new @value{GDBN} parameters. @@ -20464,8 +20836,9 @@ spaces if the parameter has a multi-part name. For example, @samp{print object} is a valid parameter name. If the named parameter does not exist, this function throws a -@code{RuntimeError}. Otherwise, the parameter's value is converted to -a Python value of the appropriate type, and returned. +@code{gdb.error} (@pxref{Exception Handling}). Otherwise, the +parameter's value is converted to a Python value of the appropriate +type, and returned. @end defun @findex gdb.history @@ -20476,7 +20849,7 @@ If @var{number} is negative, then @value{GDBN} will take its absolute value and count backward from the last element (i.e., the most recent element) to find the value to return. If @var{number} is zero, then @value{GDBN} will return the most recent element. If the element specified by @var{number} -doesn't exist in the value history, a @code{RuntimeError} exception will be +doesn't exist in the value history, a @code{gdb.error} exception will be raised. If no exception is raised, the return value is always an instance of @@ -20496,18 +20869,103 @@ compute values, for example, it is the only way to get the value of a convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}. @end defun -@findex gdb.write -@defun write string -Print a string to @value{GDBN}'s paginated standard output stream. +@findex gdb.post_event +@defun post_event event +Put @var{event}, a callable object taking no arguments, into +@value{GDBN}'s internal event queue. This callable will be invoked at +some later point, during @value{GDBN}'s event processing. Events +posted using @code{post_event} will be run in the order in which they +were posted; however, there is no way to know when they will be +processed relative to other events inside @value{GDBN}. + +@value{GDBN} is not thread-safe. If your Python program uses multiple +threads, you must be careful to only call @value{GDBN}-specific +functions in the main @value{GDBN} thread. @code{post_event} ensures +this. For example: + +@smallexample +(@value{GDBP}) python +>import threading +> +>class Writer(): +> def __init__(self, message): +> self.message = message; +> def __call__(self): +> gdb.write(self.message) +> +>class MyThread1 (threading.Thread): +> def run (self): +> gdb.post_event(Writer("Hello ")) +> +>class MyThread2 (threading.Thread): +> def run (self): +> gdb.post_event(Writer("World\n")) +> +>MyThread1().start() +>MyThread2().start() +>end +(@value{GDBP}) Hello World +@end smallexample +@end defun + +@findex gdb.write +@defun write string @r{[}stream{]} +Print a string to @value{GDBN}'s paginated output stream. The +optional @var{stream} determines the stream to print to. The default +stream is @value{GDBN}'s standard output stream. Possible stream +values are: + +@table @code +@findex STDOUT +@findex gdb.STDOUT +@item STDOUT +@value{GDBN}'s standard output stream. + +@findex STDERR +@findex gdb.STDERR +@item STDERR +@value{GDBN}'s standard error stream. + +@findex STDLOG +@findex gdb.STDLOG +@item STDLOG +@value{GDBN}'s log stream (@pxref{Logging Output}). +@end table + Writing to @code{sys.stdout} or @code{sys.stderr} will automatically -call this function. +call this function and will automatically direct the output to the +relevant stream. @end defun @findex gdb.flush @defun flush -Flush @value{GDBN}'s paginated standard output stream. Flushing -@code{sys.stdout} or @code{sys.stderr} will automatically call this -function. +Flush the buffer of a @value{GDBN} paginated stream so that the +contents are displayed immediately. @value{GDBN} will flush the +contents of a stream automatically when it encounters a newline in the +buffer. The optional @var{stream} determines the stream to flush. The +default stream is @value{GDBN}'s standard output stream. Possible +stream values are: + +@table @code +@findex STDOUT +@findex gdb.STDOUT +@item STDOUT +@value{GDBN}'s standard output stream. + +@findex STDERR +@findex gdb.STDERR +@item STDERR +@value{GDBN}'s standard error stream. + +@findex STDLOG +@findex gdb.STDLOG +@item STDLOG +@value{GDBN}'s log stream (@pxref{Logging Output}). + +@end table + +Flushing @code{sys.stdout} or @code{sys.stderr} will automatically +call this function for the relevant stream. @end defun @findex gdb.target_charset @@ -20525,6 +20983,26 @@ Return the name of the current target wide character set never returned. @end defun +@findex gdb.solib_name +@defun solib_name address +Return the name of the shared library holding the given @var{address} +as a string, or @code{None}. +@end defun + +@findex gdb.decode_line +@defun decode_line @r{[}expression@r{]} +Return locations of the line specified by @var{expression}, or of the +current line if no argument was given. This function returns a Python +tuple containing two elements. The first element contains a string +holding any unparsed section of @var{expression} (or @code{None} if +the expression has been fully parsed). The second element contains +either @code{None} or another tuple that contains all the locations +that match the expression represented as @code{gdb.Symtab_and_line} +objects (@pxref{Symbol Tables In Python}). If @var{expression} is +provided, it is decoded the way that @value{GDBN}'s inbuilt +@code{break} or @code{edit} commands do (@pxref{Specify Location}). +@end defun + @node Exception Handling @subsubsection Exception Handling @cindex python exceptions @@ -20545,15 +21023,31 @@ Traceback (most recent call last): NameError: name 'foo' is not defined @end smallexample -@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python -code are converted to Python @code{RuntimeError} exceptions. User -interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination -prompt) is translated to a Python @code{KeyboardInterrupt} -exception. If you catch these exceptions in your Python code, your -exception handler will see @code{RuntimeError} or -@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error -message as its value, and the Python call stack backtrace at the -Python statement closest to where the @value{GDBN} error occured as the +@value{GDBN} errors that happen in @value{GDBN} commands invoked by +Python code are converted to Python exceptions. The type of the +Python exception depends on the error. + +@ftable @code +@item gdb.error +This is the base class for most exceptions generated by @value{GDBN}. +It is derived from @code{RuntimeError}, for compatibility with earlier +versions of @value{GDBN}. + +If an error occurring in @value{GDBN} does not fit into some more +specific category, then the generated exception will have this type. + +@item gdb.MemoryError +This is a subclass of @code{gdb.error} which is thrown when an +operation tried to access invalid memory in the inferior. + +@item KeyboardInterrupt +User interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination +prompt) is translated to a Python @code{KeyboardInterrupt} exception. +@end ftable + +In all cases, your exception handler will see the @value{GDBN} error +message as its value and the Python call stack backtrace at the Python +statement closest to where the @value{GDBN} error occured as the traceback. @findex gdb.GdbError @@ -20614,6 +21108,22 @@ bar = some_val['foo'] Again, @code{bar} will also be a @code{gdb.Value} object. +A @code{gdb.Value} that represents a function can be executed via +inferior function call. Any arguments provided to the call must match +the function's prototype, and must be provided in the order specified +by that prototype. + +For example, @code{some_val} is a @code{gdb.Value} instance +representing a function that takes two integers as arguments. To +execute this function, call it like so: + +@smallexample +result = some_val (10,20) +@end smallexample + +Any values returned from a function call will be stored as a +@code{gdb.Value}. + The following attributes are provided: @table @code @@ -20631,13 +21141,64 @@ this value, thus it is not available for fetching from the inferior. @defivar Value type The type of this @code{gdb.Value}. The value of this attribute is a -@code{gdb.Type} object. +@code{gdb.Type} object (@pxref{Types In Python}). +@end defivar + +@defivar Value dynamic_type +The dynamic type of this @code{gdb.Value}. This uses C@t{++} run-time +type information (@acronym{RTTI}) to determine the dynamic type of the +value. If this value is of class type, it will return the class in +which the value is embedded, if any. If this value is of pointer or +reference to a class type, it will compute the dynamic type of the +referenced object, and return a pointer or reference to that type, +respectively. In all other cases, it will return the value's static +type. + +Note that this feature will only work when debugging a C@t{++} program +that includes @acronym{RTTI} for the object in question. Otherwise, +it will just return the static type of the value as in @kbd{ptype foo} +(@pxref{Symbols, ptype}). @end defivar @end table The following methods are provided: @table @code +@defmethod Value __init__ @var{val} +Many Python values can be converted directly to a @code{gdb.Value} via +this object initializer. Specifically: + +@table @asis +@item Python boolean +A Python boolean is converted to the boolean type from the current +language. + +@item Python integer +A Python integer is converted to the C @code{long} type for the +current architecture. + +@item Python long +A Python long is converted to the C @code{long long} type for the +current architecture. + +@item Python float +A Python float is converted to the C @code{double} type for the +current architecture. + +@item Python string +A Python string is converted to a target string, using the current +target encoding. + +@item @code{gdb.Value} +If @code{val} is a @code{gdb.Value}, then a copy of the value is made. + +@item @code{gdb.LazyString} +If @code{val} is a @code{gdb.LazyString} (@pxref{Lazy Strings In +Python}), then the lazy string's @code{value} method is called, and +its result is used. +@end table +@end defmethod + @defmethod Value cast type Return a new instance of @code{gdb.Value} that is the result of casting this instance to the type described by @var{type}, which must @@ -20666,6 +21227,16 @@ The result @code{bar} will be a @code{gdb.Value} object holding the value pointed to by @code{foo}. @end defmethod +@defmethod Value dynamic_cast type +Like @code{Value.cast}, but works as if the C@t{++} @code{dynamic_cast} +operator were used. Consult a C@t{++} reference for details. +@end defmethod + +@defmethod Value reinterpret_cast type +Like @code{Value.cast}, but works as if the C@t{++} @code{reinterpret_cast} +operator were used. Consult a C@t{++} reference for details. +@end defmethod + @defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} @r{[}length@r{]} If this @code{gdb.Value} represents a string, then this method converts the contents to a Python string. Otherwise, this method will @@ -20812,6 +21383,15 @@ but it can be @code{None} in some situations. @end table @end defmethod +@defmethod Type array @var{n1} @r{[}@var{n2}@r{]} +Return a new @code{gdb.Type} object which represents an array of this +type. If one argument is given, it is the inclusive upper bound of +the array; in this case the lower bound is zero. If two arguments are +given, the first argument is the lower bound of the array, and the +second argument is the upper bound of the array. An array's length +must not be negative, but the bounds can be. +@end defmethod + @defmethod Type const Return a new @code{gdb.Type} object which represents a @code{const}-qualified variant of this type. @@ -20832,7 +21412,7 @@ variant of this type. That is, the result is neither @code{const} nor Return a Python @code{Tuple} object that contains two elements: the low bound of the argument type and the high bound of that type. If the type does not have a range, @value{GDBN} will raise a -@code{RuntimeError} exception. +@code{gdb.error} exception (@pxref{Exception Handling}). @end defmethod @defmethod Type reference @@ -21017,6 +21597,9 @@ A function internal to @value{GDBN}. This is the type used to represent convenience functions. @end table +Further support for types is provided in the @code{gdb.types} +Python module (@pxref{gdb.types}). + @node Pretty Printing API @subsubsection Pretty Printing API @@ -21116,12 +21699,13 @@ printer exists, then this returns @code{None}. The Python list @code{gdb.pretty_printers} contains an array of functions or callable objects that have been registered via addition -as a pretty-printer. +as a pretty-printer. Printers in this list are called @code{global} +printers, they're available when debugging all inferiors. Each @code{gdb.Progspace} contains a @code{pretty_printers} attribute. Each @code{gdb.Objfile} also contains a @code{pretty_printers} attribute. -A function on one of these lists is passed a single @code{gdb.Value} +Each function on these lists is passed a single @code{gdb.Value} argument and should return a pretty-printer object conforming to the interface definition above (@pxref{Pretty Printing API}). If a function cannot create a pretty-printer for the value, it should return @@ -21129,9 +21713,8 @@ cannot create a pretty-printer for the value, it should return @value{GDBN} first checks the @code{pretty_printers} attribute of each @code{gdb.Objfile} in the current program space and iteratively calls -each enabled function (@pxref{Disabling Pretty-Printers}) -in the list for that @code{gdb.Objfile} until it receives -a pretty-printer object. +each enabled lookup routine in the list for that @code{gdb.Objfile} +until it receives a pretty-printer object. If no pretty-printer is found in the objfile lists, @value{GDBN} then searches the pretty-printer list of the current program space, calling each enabled function until an object is returned. @@ -21144,20 +21727,43 @@ given list, functions are always invoked from the head of the list, and iterated over sequentially until the end of the list, or a printer object is returned. +For various reasons a pretty-printer may not work. +For example, the underlying data structure may have changed and +the pretty-printer is out of date. + +The consequences of a broken pretty-printer are severe enough that +@value{GDBN} provides support for enabling and disabling individual +printers. For example, if @code{print frame-arguments} is on, +a backtrace can become highly illegible if any argument is printed +with a broken printer. + +Pretty-printers are enabled and disabled by attaching an @code{enabled} +attribute to the registered function or callable object. If this attribute +is present and its value is @code{False}, the printer is disabled, otherwise +the printer is enabled. + +@node Writing a Pretty-Printer +@subsubsection Writing a Pretty-Printer +@cindex writing a pretty-printer + +A pretty-printer consists of two parts: a lookup function to detect +if the type is supported, and the printer itself. + Here is an example showing how a @code{std::string} printer might be -written: +written. @xref{Pretty Printing API}, for details on the API this class +must provide. @smallexample -class StdStringPrinter: +class StdStringPrinter(object): "Print a std::string" - def __init__ (self, val): + def __init__(self, val): self.val = val - def to_string (self): + def to_string(self): return self.val['_M_dataplus']['_M_p'] - def display_hint (self): + def display_hint(self): return 'string' @end smallexample @@ -21165,15 +21771,13 @@ And here is an example showing how a lookup function for the printer example above might be written. @smallexample -def str_lookup_function (val): - +def str_lookup_function(val): lookup_tag = val.type.tag - regex = re.compile ("^std::basic_string$") if lookup_tag == None: return None - if regex.match (lookup_tag): - return StdStringPrinter (val) - + regex = re.compile("^std::basic_string$") + if regex.match(lookup_tag): + return StdStringPrinter(val) return None @end smallexample @@ -21209,8 +21813,8 @@ To continue the @code{std::string} example (@pxref{Pretty Printing API}), this code might appear in @code{gdb.libstdcxx.v6}: @smallexample -def register_printers (objfile): - objfile.pretty_printers.add (str_lookup_function) +def register_printers(objfile): + objfile.pretty_printers.add(str_lookup_function) @end smallexample @noindent @@ -21218,31 +21822,96 @@ And then the corresponding contents of the auto-load file would be: @smallexample import gdb.libstdcxx.v6 -gdb.libstdcxx.v6.register_printers (gdb.current_objfile ()) +gdb.libstdcxx.v6.register_printers(gdb.current_objfile()) @end smallexample -@node Disabling Pretty-Printers -@subsubsection Disabling Pretty-Printers -@cindex disabling pretty-printers +The previous example illustrates a basic pretty-printer. +There are a few things that can be improved on. +The printer doesn't have a name, making it hard to identify in a +list of installed printers. The lookup function has a name, but +lookup functions can have arbitrary, even identical, names. -For various reasons a pretty-printer may not work. -For example, the underlying data structure may have changed and -the pretty-printer is out of date. +Second, the printer only handles one type, whereas a library typically has +several types. One could install a lookup function for each desired type +in the library, but one could also have a single lookup function recognize +several types. The latter is the conventional way this is handled. +If a pretty-printer can handle multiple data types, then its +@dfn{subprinters} are the printers for the individual data types. -The consequences of a broken pretty-printer are severe enough that -@value{GDBN} provides support for enabling and disabling individual -printers. For example, if @code{print frame-arguments} is on, -a backtrace can become highly illegible if any argument is printed -with a broken printer. +The @code{gdb.printing} module provides a formal way of solving these +problems (@pxref{gdb.printing}). +Here is another example that handles multiple types. -Pretty-printers are enabled and disabled by attaching an @code{enabled} -attribute to the registered function or callable object. If this attribute -is present and its value is @code{False}, the printer is disabled, otherwise -the printer is enabled. +These are the types we are going to pretty-print: + +@smallexample +struct foo @{ int a, b; @}; +struct bar @{ struct foo x, y; @}; +@end smallexample + +Here are the printers: + +@smallexample +class fooPrinter: + """Print a foo object.""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return ("a=<" + str(self.val["a"]) + + "> b=<" + str(self.val["b"]) + ">") + +class barPrinter: + """Print a bar object.""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return ("x=<" + str(self.val["x"]) + + "> y=<" + str(self.val["y"]) + ">") +@end smallexample + +This example doesn't need a lookup function, that is handled by the +@code{gdb.printing} module. Instead a function is provided to build up +the object that handles the lookup. + +@smallexample +import gdb.printing + +def build_pretty_printer(): + pp = gdb.printing.RegexpCollectionPrettyPrinter( + "my_library") + pp.add_printer('foo', '^foo$', fooPrinter) + pp.add_printer('bar', '^bar$', barPrinter) + return pp +@end smallexample + +And here is the autoload support: + +@smallexample +import gdb.printing +import my_library +gdb.printing.register_pretty_printer( + gdb.current_objfile(), + my_library.build_pretty_printer()) +@end smallexample + +Finally, when this printer is loaded into @value{GDBN}, here is the +corresponding output of @samp{info pretty-printer}: + +@smallexample +(gdb) info pretty-printer +my_library.so: + my_library + foo + bar +@end smallexample @node Inferiors In Python @subsubsection Inferiors In Python -@cindex inferiors in python +@cindex inferiors in Python @findex gdb.Inferior Programs which are being run under @value{GDBN} are called inferiors @@ -21278,6 +21947,14 @@ started by @value{GDBN} itself. A @code{gdb.Inferior} object has the following methods: @table @code +@defmethod Inferior is_valid +Returns @code{True} if the @code{gdb.Inferior} object is valid, +@code{False} if not. A @code{gdb.Inferior} object will become invalid +if the inferior no longer exists within @value{GDBN}. All other +@code{gdb.Inferior} methods will throw an exception if it is invalid +at the time the method is called. +@end defmethod + @defmethod Inferior threads This method returns a tuple holding all the threads which are valid when it is called. If there are no valid threads, the method will @@ -21313,6 +21990,125 @@ the pattern could not be found. @end defmethod @end table +@node Events In Python +@subsubsection Events In Python +@cindex inferior events in Python + +@value{GDBN} provides a general event facility so that Python code can be +notified of various state changes, particularly changes that occur in +the inferior. + +An @dfn{event} is just an object that describes some state change. The +type of the object and its attributes will vary depending on the details +of the change. All the existing events are described below. + +In order to be notified of an event, you must register an event handler +with an @dfn{event registry}. An event registry is an object in the +@code{gdb.events} module which dispatches particular events. A registry +provides methods to register and unregister event handlers: + +@table @code +@defmethod EventRegistry connect object +Add the given callable @var{object} to the registry. This object will be +called when an event corresponding to this registry occurs. +@end defmethod + +@defmethod EventRegistry disconnect object +Remove the given @var{object} from the registry. Once removed, the object +will no longer receive notifications of events. +@end defmethod +@end table + +Here is an example: + +@smallexample +def exit_handler (event): + print "event type: exit" + print "exit code: %d" % (event.exit_code) + +gdb.events.exited.connect (exit_handler) +@end smallexample + +In the above example we connect our handler @code{exit_handler} to the +registry @code{events.exited}. Once connected, @code{exit_handler} gets +called when the inferior exits. The argument @dfn{event} in this example is +of type @code{gdb.ExitedEvent}. As you can see in the example the +@code{ExitedEvent} object has an attribute which indicates the exit code of +the inferior. + +The following is a listing of the event registries that are available and +details of the events they emit: + +@table @code + +@item events.cont +Emits @code{gdb.ThreadEvent}. + +Some events can be thread specific when @value{GDBN} is running in non-stop +mode. When represented in Python, these events all extend +@code{gdb.ThreadEvent}. Note, this event is not emitted directly; instead, +events which are emitted by this or other modules might extend this event. +Examples of these events are @code{gdb.BreakpointEvent} and +@code{gdb.ContinueEvent}. + +@table @code +@defivar ThreadEvent inferior_thread +In non-stop mode this attribute will be set to the specific thread which was +involved in the emitted event. Otherwise, it will be set to @code{None}. +@end defivar +@end table + +Emits @code{gdb.ContinueEvent} which extends @code{gdb.ThreadEvent}. + +This event indicates that the inferior has been continued after a stop. For +inherited attribute refer to @code{gdb.ThreadEvent} above. + +@item events.exited +Emits @code{events.ExitedEvent} which indicates that the inferior has exited. +@code{events.ExitedEvent} has one optional attribute. This attribute +will exist only in the case that the inferior exited with some +status. +@table @code +@defivar ExitedEvent exit_code +An integer representing the exit code which the inferior has returned. +@end defivar +@end table + +@item events.stop +Emits @code{gdb.StopEvent} which extends @code{gdb.ThreadEvent}. + +Indicates that the inferior has stopped. All events emitted by this registry +extend StopEvent. As a child of @code{gdb.ThreadEvent}, @code{gdb.StopEvent} +will indicate the stopped thread when @value{GDBN} is running in non-stop +mode. Refer to @code{gdb.ThreadEvent} above for more details. + +Emits @code{gdb.SignalEvent} which extends @code{gdb.StopEvent}. + +This event indicates that the inferior or one of its threads has received as +signal. @code{gdb.SignalEvent} has the following attributes: + +@table @code +@defivar SignalEvent stop_signal +A string representing the signal received by the inferior. A list of possible +signal values can be obtained by running the command @code{info signals} in +the @value{GDBN} command prompt. +@end defivar +@end table + +Also emits @code{gdb.BreakpointEvent} which extends @code{gdb.StopEvent}. + +@code{gdb.BreakpointEvent} event indicates that a breakpoint has been hit, and +has the following attributes: + +@table @code +@defivar BreakpointEvent breakpoint +A reference to the breakpoint that was hit of type @code{gdb.Breakpoint}. +@xref{Breakpoints In Python}, for details of the @code{gdb.Breakpoint} object. +@end defivar +@end table + +@end table + @node Threads In Python @subsubsection Threads In Python @cindex threads in python @@ -21333,6 +22129,17 @@ is no selected thread, this will return @code{None}. A @code{gdb.InferiorThread} object has the following attributes: @table @code +@defivar InferiorThread name +The name of the thread. If the user specified a name using +@code{thread name}, then this returns that name. Otherwise, if an +OS-supplied name is available, then it is returned. Otherwise, this +returns @code{None}. + +This attribute can be assigned to. The new value must be a string +object, which sets the new name, or @code{None}, which removes any +user-specified thread name. +@end defivar + @defivar InferiorThread num ID of the thread, as assigned by GDB. @end defivar @@ -21349,6 +22156,14 @@ does not use that identifier. A @code{gdb.InferiorThread} object has the following methods: @table @code +@defmethod InferiorThread is_valid +Returns @code{True} if the @code{gdb.InferiorThread} object is valid, +@code{False} if not. A @code{gdb.InferiorThread} object will become +invalid if the thread exits, or the inferior that the thread belongs +is deleted. All other @code{gdb.InferiorThread} methods will throw an +exception if it is invalid at the time the method is called. +@end defmethod + @defmethod InferiorThread switch This changes @value{GDBN}'s currently selected thread to the one represented by this object. @@ -21710,6 +22525,22 @@ parameter. It can be read and assigned to just as any other attribute. @value{GDBN} does validation when assignments are made. @end defivar +There are two methods that should be implemented in any +@code{Parameter} class. These are: + +@defop Operation {parameter} get_set_string self +@value{GDBN} will call this method when a @var{parameter}'s value has +been changed via the @code{set} API (for example, @kbd{set foo off}). +The @code{value} attribute has already been populated with the new +value and may be used in output. This method must return a string. +@end defop + +@defop Operation {parameter} get_show_string self svalue +@value{GDBN} will call this method when a @var{parameter}'s +@code{show} API has been invoked (for example, @kbd{show foo}). The +argument @code{svalue} receives the string representation of the +current value. This method must return a string. +@end defop When a new parameter is defined, its type must be specified. The available types are represented by constants defined in the @code{gdb} @@ -21926,6 +22757,16 @@ which is used to format the value. @xref{Pretty Printing API}, for more information. @end defivar +A @code{gdb.Objfile} object has the following methods: + +@defmethod Objfile is_valid +Returns @code{True} if the @code{gdb.Objfile} object is valid, +@code{False} if not. A @code{gdb.Objfile} object can become invalid +if the object file it refers to is not loaded in @value{GDBN} any +longer. All other @code{gdb.Objfile} methods will throw an exception +if it is invalid at the time the method is called. +@end defmethod + @node Frames In Python @subsubsection Accessing inferior stack frames from Python. @@ -21934,8 +22775,8 @@ When the debugged program stops, @value{GDBN} is able to analyze its call stack (@pxref{Frames,,Stack frames}). The @code{gdb.Frame} class represents a frame in the stack. A @code{gdb.Frame} object is only valid while its corresponding frame exists in the inferior's stack. If you try -to use an invalid frame object, @value{GDBN} will throw a @code{RuntimeError} -exception. +to use an invalid frame object, @value{GDBN} will throw a @code{gdb.error} +exception (@pxref{Exception Handling}). Two @code{gdb.Frame} objects can be compared for equality with the @code{==} operator, like: @@ -21952,6 +22793,11 @@ The following frame-related functions are available in the @code{gdb} module: Return the selected frame object. (@pxref{Selection,,Selecting a Frame}). @end defun +@findex gdb.newest_frame +@defun newest_frame +Return the newest frame object for the selected thread. +@end defun + @defun frame_stop_reason_string reason Return a string explaining the reason why @value{GDBN} stopped unwinding frames, as expressed by the given @var{reason} code (an integer, see the @@ -21974,9 +22820,30 @@ obtained. @end defmethod @defmethod Frame type -Returns the type of the frame. The value can be one of -@code{gdb.NORMAL_FRAME}, @code{gdb.DUMMY_FRAME}, @code{gdb.SIGTRAMP_FRAME} -or @code{gdb.SENTINEL_FRAME}. +Returns the type of the frame. The value can be one of: +@table @code +@item gdb.NORMAL_FRAME +An ordinary stack frame. + +@item gdb.DUMMY_FRAME +A fake stack frame that was created by @value{GDBN} when performing an +inferior function call. + +@item gdb.INLINE_FRAME +A frame representing an inlined function. The function was inlined +into a @code{gdb.NORMAL_FRAME} that is older than this one. + +@item gdb.SIGTRAMP_FRAME +A signal trampoline frame. This is the frame created by the OS when +it calls into a signal handler. + +@item gdb.ARCH_FRAME +A fake stack frame representing a cross-architecture call. + +@item gdb.SENTINEL_FRAME +This is like @code{gdb.NORMAL_FRAME}, but it is only used for the +newest frame. +@end table @end defmethod @defmethod Frame unwind_stop_reason @@ -22051,6 +22918,20 @@ block cannot be found for the @var{pc} value specified, the function will return @code{None}. @end defun +A @code{gdb.Block} object has the following methods: + +@table @code +@defmethod Block is_valid +Returns @code{True} if the @code{gdb.Block} object is valid, +@code{False} if not. A block object can become invalid if the block it +refers to doesn't exist anymore in the inferior. All other +@code{gdb.Block} methods will throw an exception if it is invalid at +the time the method is called. This method is also made available to +the Python iterator object that @code{gdb.Block} provides in an iteration +context and via the Python @code{iter} built-in function. +@end defmethod +@end table + A @code{gdb.Block} object has the following attributes: @table @code @@ -22089,7 +22970,7 @@ The following symbol-related functions are available in the @code{gdb} module: @findex gdb.lookup_symbol -@defun lookup_symbol name [block] [domain] +@defun lookup_symbol name @r{[}block@r{]} @r{[}domain@r{]} This function searches for a symbol by name. The search scope can be restricted to the parameters defined in the optional domain and block arguments. @@ -22097,10 +22978,33 @@ arguments. @var{name} is the name of the symbol. It must be a string. The optional @var{block} argument restricts the search to symbols visible in that @var{block}. The @var{block} argument must be a -@code{gdb.Block} object. The optional @var{domain} argument restricts +@code{gdb.Block} object. If omitted, the block for the current frame +is used. The optional @var{domain} argument restricts the search to the domain type. The @var{domain} argument must be a domain constant defined in the @code{gdb} module and described later in this chapter. + +The result is a tuple of two elements. +The first element is a @code{gdb.Symbol} object or @code{None} if the symbol +is not found. +If the symbol is found, the second element is @code{True} if the symbol +is a field of a method's object (e.g., @code{this} in C@t{++}), +otherwise it is @code{False}. +If the symbol is not found, the second element is @code{False}. +@end defun + +@findex gdb.lookup_global_symbol +@defun lookup_global_symbol name @r{[}domain@r{]} +This function searches for a global symbol by name. +The search scope can be restricted to by the domain argument. + +@var{name} is the name of the symbol. It must be a string. +The optional @var{domain} argument restricts the search to the domain type. +The @var{domain} argument must be a domain constant defined in the @code{gdb} +module and described later in this chapter. + +The result is a @code{gdb.Symbol} object or @code{None} if the symbol +is not found. @end defun A @code{gdb.Symbol} object has the following attributes: @@ -22150,6 +23054,18 @@ of a symbol. Each address class is a constant defined in the @end defivar @end table +A @code{gdb.Symbol} object has the following methods: + +@table @code +@defmethod Symbol is_valid +Returns @code{True} if the @code{gdb.Symbol} object is valid, +@code{False} if not. A @code{gdb.Symbol} object can become invalid if +the symbol it refers to does not exist in @value{GDBN} any longer. +All other @code{gdb.Symbol} methods will throw an exception if it is +invalid at the time the method is called. +@end defmethod +@end table + The available domain categories in @code{gdb.Symbol} are represented as constants in the @code{gdb} module: @@ -22294,6 +23210,19 @@ attribute is not writable. @end defivar @end table +A @code{gdb.Symtab_and_line} object has the following methods: + +@table @code +@defmethod Symtab_and_line is_valid +Returns @code{True} if the @code{gdb.Symtab_and_line} object is valid, +@code{False} if not. A @code{gdb.Symtab_and_line} object can become +invalid if the Symbol table and line object it refers to does not +exist in @value{GDBN} any longer. All other +@code{gdb.Symtab_and_line} methods will throw an exception if it is +invalid at the time the method is called. +@end defmethod +@end table + A @code{gdb.Symtab} object has the following attributes: @table @code @@ -22307,9 +23236,17 @@ This attribute is not writable. @end defivar @end table -The following methods are provided: +A @code{gdb.Symtab} object has the following methods: @table @code +@defmethod Symtab is_valid +Returns @code{True} if the @code{gdb.Symtab} object is valid, +@code{False} if not. A @code{gdb.Symtab} object can become invalid if +the symbol table it refers to does not exist in @value{GDBN} any +longer. All other @code{gdb.Symtab} methods will throw an exception +if it is invalid at the time the method is called. +@end defmethod + @defmethod Symtab fullname Return the symbol table's source absolute file name. @end defmethod @@ -22324,7 +23261,7 @@ Return the symbol table's source absolute file name. Python code can manipulate breakpoints via the @code{gdb.Breakpoint} class. -@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]} +@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]} @r{[}internal@r{]} Create a new breakpoint. @var{spec} is a string naming the location of the breakpoint, or an expression that defines a watchpoint. The contents can be any location recognized by the @@ -22332,12 +23269,44 @@ watchpoint. The contents can be any location recognized by the command. The optional @var{type} denotes the breakpoint to create from the types defined later in this chapter. This argument can be either: @code{BP_BREAKPOINT} or @code{BP_WATCHPOINT}. @var{type} -defaults to @code{BP_BREAKPOINT}. The optional @var{wp_class} +defaults to @code{BP_BREAKPOINT}. The optional @var{internal} argument +allows the breakpoint to become invisible to the user. The breakpoint +will neither be reported when created, nor will it be listed in the +output from @code{info breakpoints} (but will be listed with the +@code{maint info breakpoints} command). The optional @var{wp_class} argument defines the class of watchpoint to create, if @var{type} is -defined as @code{BP_WATCHPOINT}. If a watchpoint class is not -provided, it is assumed to be a @var{WP_WRITE} class. +@code{BP_WATCHPOINT}. If a watchpoint class is not provided, it is +assumed to be a @var{WP_WRITE} class. @end defmethod +@defop Operation {gdb.Breakpoint} stop (self) +The @code{gdb.Breakpoint} class can be sub-classed and, in +particular, you may choose to implement the @code{stop} method. +If this method is defined as a sub-class of @code{gdb.Breakpoint}, +it will be called when the inferior reaches any location of a +breakpoint which instantiates that sub-class. If the method returns +@code{True}, the inferior will be stopped at the location of the +breakpoint, otherwise the inferior will continue. + +If there are multiple breakpoints at the same location with a +@code{stop} method, each one will be called regardless of the +return status of the previous. This ensures that all @code{stop} +methods have a chance to execute at that location. In this scenario +if one of the methods returns @code{True} but the others return +@code{False}, the inferior will still be stopped. + +Example @code{stop} implementation: + +@smallexample +class MyBreakpoint (gdb.Breakpoint): + def stop (self): + inf_val = gdb.parse_and_eval("foo") + if inf_val == 3: + return True + return False +@end smallexample +@end defop + The available watchpoint types represented by constants are defined in the @code{gdb} module: @@ -22367,6 +23336,12 @@ watchpoint scope, the watchpoint remains valid even if execution of the inferior leaves the scope of that watchpoint. @end defmethod +@defmethod Breakpoint delete +Permanently deletes the @value{GDBN} breakpoint. This also +invalidates the Python @code{Breakpoint} object. Any further access +to this object's attributes or methods will raise an error. +@end defmethod + @defivar Breakpoint enabled This attribute is @code{True} if the breakpoint is enabled, and @code{False} otherwise. This attribute is writable. @@ -22410,6 +23385,12 @@ determine the actual breakpoint type or use-case. This attribute is not writable. @end defivar +@defivar Breakpoint visible +This attribute tells whether the breakpoint is visible to the user +when set, or when the @samp{info breakpoints} command is run. This +attribute is not writable. +@end defivar + The available types are represented by constants defined in the @code{gdb} module: @@ -22548,13 +23529,13 @@ debugging commands and scripts. Auto-loading can be enabled or disabled. @table @code -@kindex maint set python auto-load -@item maint set python auto-load [yes|no] -Enable or disable the Python auto-loading feature. +@kindex set auto-load-scripts +@item set auto-load-scripts [yes|no] +Enable or disable the auto-loading of Python scripts. -@kindex maint show python auto-load -@item maint show python auto-load -Show whether Python auto-loading is enabled or disabled. +@kindex show auto-load-scripts +@item show auto-load-scripts +Show whether auto-loading of Python scripts is enabled or disabled. @end table When reading an auto-loaded file, @value{GDBN} sets the @@ -22683,6 +23664,82 @@ cumbersome. It may be easier to specify the scripts in the top of the source tree to the source search path. @end itemize +@node Python modules +@subsection Python modules +@cindex python modules + +@value{GDBN} comes with a module to assist writing Python code. + +@menu +* gdb.printing:: Building and registering pretty-printers. +* gdb.types:: Utilities for working with types. +@end menu + +@node gdb.printing +@subsubsection gdb.printing +@cindex gdb.printing + +This module provides a collection of utilities for working with +pretty-printers. + +@table @code +@item PrettyPrinter (@var{name}, @var{subprinters}=None) +This class specifies the API that makes @samp{info pretty-printer}, +@samp{enable pretty-printer} and @samp{disable pretty-printer} work. +Pretty-printers should generally inherit from this class. + +@item SubPrettyPrinter (@var{name}) +For printers that handle multiple types, this class specifies the +corresponding API for the subprinters. + +@item RegexpCollectionPrettyPrinter (@var{name}) +Utility class for handling multiple printers, all recognized via +regular expressions. +@xref{Writing a Pretty-Printer}, for an example. + +@item register_pretty_printer (@var{obj}, @var{printer}) +Register @var{printer} with the pretty-printer list of @var{obj}. +@end table + +@node gdb.types +@subsubsection gdb.types +@cindex gdb.types + +This module provides a collection of utilities for working with +@code{gdb.Types} objects. + +@table @code +@item get_basic_type (@var{type}) +Return @var{type} with const and volatile qualifiers stripped, +and with typedefs and C@t{++} references converted to the underlying type. + +C@t{++} example: + +@smallexample +typedef const int const_int; +const_int foo (3); +const_int& foo_ref (foo); +int main () @{ return 0; @} +@end smallexample + +Then in gdb: + +@smallexample +(gdb) start +(gdb) python import gdb.types +(gdb) python foo_ref = gdb.parse_and_eval("foo_ref") +(gdb) python print gdb.types.get_basic_type(foo_ref.type) +int +@end smallexample + +@item has_field (@var{type}, @var{field}) +Return @code{True} if @var{type}, assumed to be a type with fields +(e.g., a structure or union), has field @var{field}. + +@item make_enum_dict (@var{enum_type}) +Return a Python @code{dictionary} type produced from @var{enum_type}. +@end table + @node Interpreters @chapter Command Interpreters @cindex command interpreters @@ -22880,8 +23937,14 @@ Indicates the current program counter address. @cindex TUI key bindings The TUI installs several key bindings in the readline keymaps -(@pxref{Command Line Editing}). The following key bindings -are installed for both TUI mode and the @value{GDBN} standard mode. +@ifset SYSTEM_READLINE +(@pxref{Command Line Editing, , , rluserman, GNU Readline Library}). +@end ifset +@ifclear SYSTEM_READLINE +(@pxref{Command Line Editing}). +@end ifclear +The following key bindings are installed for both TUI mode and the +@value{GDBN} standard mode. @table @kbd @kindex C-x C-a @@ -23896,6 +24959,7 @@ follow development on @email{gdb@@sourceware.org} and * GDB/MI Async Records:: * GDB/MI Frame Information:: * GDB/MI Thread Information:: +* GDB/MI Ada Exception Information:: @end menu @node GDB/MI Result Records @@ -24050,11 +25114,12 @@ was attached to a program. The @var{id} field contains the @value{GDBN} identifier of the thread group. The @var{pid} field contains process identifier, specific to the operating system. -@itemx =thread-group-exited,id="@var{id}" +@item =thread-group-exited,id="@var{id}"[,exit-code="@var{code}"] A thread group is no longer associated with a running program, either because the program has exited, or because it was detached from. The @var{id} field contains the @value{GDBN} identifier of the -thread group. +thread group. @var{code} is the exit code of the inferior; it exists +only when the inferior exited with some code. @item =thread-created,id="@var{id}",group-id="@var{gid}" @itemx =thread-exited,id="@var{id}",group-id="@var{gid}" @@ -24082,11 +25147,12 @@ opaque identifier of the library. For remote debugging case, @var{target-name} and @var{host-name} fields give the name of the library file on the target, and on the host respectively. For native debugging, both those fields have the same value. The -@var{symbols-loaded} field reports if the debug symbols for this -library are loaded. The @var{thread-group} field, if present, -specifies the id of the thread group in whose context the library was loaded. -If the field is absent, it means the library was loaded in the context -of all present thread groups. +@var{symbols-loaded} field is emitted only for backward compatibility +and should not be relied on to convey any useful information. The +@var{thread-group} field, if present, specifies the id of the thread +group in whose context the library was loaded. If the field is +absent, it means the library was loaded in the context of all present +thread groups. @item =library-unloaded,... Reports that a library was unloaded by the program. This notification @@ -24160,6 +25226,13 @@ The value of this field is an integer number of the processor core the thread was last seen on. This field is optional. @end table +@node GDB/MI Ada Exception Information +@subsection @sc{gdb/mi} Ada Exception Information + +Whenever a @code{*stopped} record is emitted because the program +stopped after hitting an exception catchpoint (@pxref{Set Catchpoints}), +@value{GDBN} provides the name of the exception that was raised via +the @code{exception-name} field. @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @node GDB/MI Simple Examples @@ -25097,21 +26170,38 @@ also reports the current thread. The @samp{info thread} command prints the same information about all threads. -@subsubheading Example +@subsubheading Result -@smallexample --thread-info -^done,threads=[ -@{id="2",target-id="Thread 0xb7e14b90 (LWP 21257)", - frame=@{level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]@},state="running"@}, -@{id="1",target-id="Thread 0xb7e156b0 (LWP 21254)", - frame=@{level="0",addr="0x0804891f",func="foo",args=[@{name="i",value="10"@}], - file="/tmp/a.c",fullname="/tmp/a.c",line="158"@},state="running"@}], -current-thread-id="1" -(gdb) -@end smallexample +The result is a list of threads. The following attributes are +defined for a given thread: -The @samp{state} field may have the following values: +@table @samp +@item current +This field exists only for the current thread. It has the value @samp{*}. + +@item id +The identifier that @value{GDBN} uses to refer to the thread. + +@item target-id +The identifier that the target uses to refer to the thread. + +@item details +Extra information about the thread, in a target-specific format. This +field is optional. + +@item name +The name of the thread. If the user specified a name using the +@code{thread name} command, then this name is given. Otherwise, if +@value{GDBN} can extract the thread name from the target, then that +name is given. If @value{GDBN} cannot find the thread name, then this +field is omitted. + +@item frame +The stack frame currently executing in the thread. + +@item state +The thread's state. The @samp{state} field may have the following +values: @table @code @item stopped @@ -25124,6 +26214,29 @@ threads. @end table +@item core +If @value{GDBN} can find the CPU core on which this thread is running, +then this field is the core identifier. This field is optional. + +@end table + +@subsubheading Example + +@smallexample +-thread-info +^done,threads=[ +@{id="2",target-id="Thread 0xb7e14b90 (LWP 21257)", + frame=@{level="0",addr="0xffffe410",func="__kernel_vsyscall", + args=[]@},state="running"@}, +@{id="1",target-id="Thread 0xb7e156b0 (LWP 21254)", + frame=@{level="0",addr="0x0804891f",func="foo", + args=[@{name="i",value="10"@}], + file="/tmp/a.c",fullname="/tmp/a.c",line="158"@}, + state="running"@}], +current-thread-id="1" +(gdb) +@end smallexample + @subheading The @code{-thread-list-ids} Command @findex -thread-list-ids @@ -25886,8 +26999,13 @@ The @code{$pc} value for that frame. Function name. @item @var{file} File name of the source file where the function lives. +@item @var{fullname} +The full file name of the source file where the function lives. @item @var{line} Line number corresponding to the @code{$pc}. +@item @var{from} +The shared library where this function is defined. This is only given +if the frame's function is not known. @end table If invoked without arguments, this command prints a backtrace for the @@ -26960,8 +28078,9 @@ displayed; if @var{lines} is higher than the number of lines between @var{start-addr} and @var{end-addr}, only the lines up to @var{end-addr} are displayed. @item @var{mode} -is either 0 (meaning only disassembly) or 1 (meaning mixed source and -disassembly). +is either 0 (meaning only disassembly), 1 (meaning mixed source and +disassembly), 2 (meaning disassembly with raw opcodes), or 3 (meaning +mixed source and disassembly with raw opcodes). @end table @subsubheading Result @@ -27271,6 +28390,8 @@ don't appear in the actual output): @subheading The @code{-data-read-memory} Command @findex -data-read-memory +This command is deprecated, use @code{-data-read-memory-bytes} instead. + @subsubheading Synopsis @smallexample @@ -27382,6 +28503,128 @@ next-page="0x000013c0",prev-page="0x00001380",memory=[ (gdb) @end smallexample +@subheading The @code{-data-read-memory-bytes} Command +@findex -data-read-memory-bytes + +@subsubheading Synopsis + +@smallexample + -data-read-memory-bytes [ -o @var{byte-offset} ] + @var{address} @var{count} +@end smallexample + +@noindent +where: + +@table @samp +@item @var{address} +An expression specifying the address of the first memory word to be +read. Complex expressions containing embedded white space should be +quoted using the C convention. + +@item @var{count} +The number of bytes to read. This should be an integer literal. + +@item @var{byte-offset} +The offsets in bytes relative to @var{address} at which to start +reading. This should be an integer literal. This option is provided +so that a frontend is not required to first evaluate address and then +perform address arithmetics itself. + +@end table + +This command attempts to read all accessible memory regions in the +specified range. First, all regions marked as unreadable in the memory +map (if one is defined) will be skipped. @xref{Memory Region +Attributes}. Second, @value{GDBN} will attempt to read the remaining +regions. For each one, if reading full region results in an errors, +@value{GDBN} will try to read a subset of the region. + +In general, every single byte in the region may be readable or not, +and the only way to read every readable byte is to try a read at +every address, which is not practical. Therefore, @value{GDBN} will +attempt to read all accessible bytes at either beginning or the end +of the region, using a binary division scheme. This heuristic works +well for reading accross a memory map boundary. Note that if a region +has a readable range that is neither at the beginning or the end, +@value{GDBN} will not read it. + +The result record (@pxref{GDB/MI Result Records}) that is output of +the command includes a field named @samp{memory} whose content is a +list of tuples. Each tuple represent a successfully read memory block +and has the following fields: + +@table @code +@item begin +The start address of the memory block, as hexadecimal literal. + +@item end +The end address of the memory block, as hexadecimal literal. + +@item offset +The offset of the memory block, as hexadecimal literal, relative to +the start address passed to @code{-data-read-memory-bytes}. + +@item contents +The contents of the memory block, in hex. + +@end table + + + +@subsubheading @value{GDBN} Command + +The corresponding @value{GDBN} command is @samp{x}. + +@subsubheading Example + +@smallexample +(gdb) +-data-read-memory-bytes &a 10 +^done,memory=[@{begin="0xbffff154",offset="0x00000000", + end="0xbffff15e", + contents="01000000020000000300"@}] +(gdb) +@end smallexample + + +@subheading The @code{-data-write-memory-bytes} Command +@findex -data-write-memory-bytes + +@subsubheading Synopsis + +@smallexample + -data-write-memory-bytes @var{address} @var{contents} +@end smallexample + +@noindent +where: + +@table @samp +@item @var{address} +An expression specifying the address of the first memory word to be +read. Complex expressions containing embedded white space should be +quoted using the C convention. + +@item @var{contents} +The hex-encoded bytes to write. + +@end table + +@subsubheading @value{GDBN} Command + +There's no corresponding @value{GDBN} command. + +@subsubheading Example + +@smallexample +(gdb) +-data-write-memory-bytes &a "aabbccdd" +^done +(gdb) +@end smallexample + + @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @node GDB/MI Tracepoint Commands @section @sc{gdb/mi} Tracepoint Commands @@ -28720,6 +29963,9 @@ pretty-printing commands, and possible presence of the @samp{display_hint} field in the output of @code{-var-list-children} @item thread-info Indicates presence of the @code{-thread-info} command. +@item data-read-memory-bytes +Indicates presense of the @code{-data-read-memory-bytes} and the +@code{-data-write-memory-bytes} commands. @end table @@ -29725,9 +30971,31 @@ things without first using the debugger to find the facts. @c inc-hist.texinfo @c Use -I with makeinfo to point to the appropriate directory, @c environment var TEXINPUTS with TeX. +@ifclear SYSTEM_READLINE @include rluser.texi @include inc-hist.texinfo +@end ifclear +@node In Memoriam +@appendix In Memoriam + +The GDB project mourns the loss of the following long-time contributors: + +@table @code +@item Fred Fish +Fred was a long-standing contributor to GDB (1991-2006), and to Free +Software in general. Outside of GDB, he was known in the Amiga world +for his series of Fish Disks, and the GeekGadget project. + +@item Michael Snyder +Michael was one of the Global Maintainers of the GDB project, with +contributions recorded as early as 1996, until 2011. In addition to +his day to day participation, he was a large driving force behind +adding Reverse Debugging to GDB. +@end table + +Beyond their technical contributions to the project, they were also +enjoyable members of the Free Software Community. We will miss them. @node Formatting Documentation @appendix Formatting Documentation @@ -29865,6 +31133,8 @@ Target descriptions (@pxref{Target Descriptions}) Remote shared library lists (@pxref{Library List Format}) @item MS-Windows shared libraries (@pxref{Shared Libraries}) +@item +Traceframe info (@pxref{Traceframe Info Format}) @end itemize @item zlib @@ -30687,6 +31957,7 @@ Show the current setting of the target wait timeout. * Library List Format:: * Memory Map Format:: * Thread List Format:: +* Traceframe Info Format:: @end menu @node Overview @@ -31014,6 +32285,21 @@ each register and their position within the @samp{g} packet are determined by the @value{GDBN} internal gdbarch functions @code{DEPRECATED_REGISTER_RAW_SIZE} and @code{gdbarch_register_name}. The specification of several standard @samp{g} packets is specified below. + +When reading registers from a trace frame (@pxref{Analyze Collected +Data,,Using the Collected Data}), the stub may also return a string of +literal @samp{x}'s in place of the register data digits, to indicate +that the corresponding register has not been collected, thus its value +is unavailable. For example, for an architecture with 4 registers of +4 bytes each, the following reply indicates to @value{GDBN} that +registers 0 and 2 have not been collected, while registers 1 and 3 +have been collected, and both have zero value: + +@smallexample +-> @code{g} +<- @code{xxxxxxxx00000000xxxxxxxx00000000} +@end smallexample + @item E @var{NN} for an error. @end table @@ -32222,6 +33508,11 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab Yes +@item @samp{qXfer:traceframe-info:read} +@tab No +@tab @samp{-} +@tab Yes + @item @samp{QNonStop} @tab No @@ -32324,6 +33615,10 @@ The remote stub understands the @samp{qXfer:siginfo:write} packet The remote stub understands the @samp{qXfer:threads:read} packet (@pxref{qXfer threads read}). +@item qXfer:traceframe-info:read +The remote stub understands the @samp{qXfer:traceframe-info:read} +packet (@pxref{qXfer traceframe info read}). + @item QNonStop The remote stub understands the @samp{QNonStop} packet (@pxref{QNonStop}). @@ -32562,6 +33857,16 @@ annex part of the generic @samp{qXfer} packet must be empty This packet is not probed by default; the remote stub must request it, by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +@item qXfer:traceframe-info:read::@var{offset},@var{length} +@anchor{qXfer traceframe info read} + +Return a description of the current traceframe's contents. +@xref{Traceframe Info Format}. The annex part of the generic +@samp{qXfer} packet must be empty (@pxref{qXfer read}). + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). + @item qXfer:osdata:read::@var{offset},@var{length} @anchor{qXfer osdata read} Access the target's @dfn{operating system information}. @@ -34853,60 +36158,59 @@ identifies the thread (@pxref{thread-id syntax}). The the thread was last executing on. The content of the of @samp{thread} element is interpreted as human-readable auxilliary information. -@include agentexpr.texi +@node Traceframe Info Format +@section Traceframe Info Format +@cindex traceframe info format -@node Trace File Format -@appendix Trace File Format -@cindex trace file format +To be able to know which objects in the inferior can be examined when +inspecting a tracepoint hit, @value{GDBN} needs to obtain the list of +memory ranges, registers and trace state variables that have been +collected in a traceframe. -The trace file comes in three parts: a header, a textual description -section, and a trace frame section with binary data. +This list is obtained using the @samp{qXfer:traceframe-info:read} +(@pxref{qXfer traceframe info read}) packet and is an XML document. -The header has the form @code{\x7fTRACE0\n}. The first byte is -@code{0x7f} so as to indicate that the file contains binary data, -while the @code{0} is a version number that may have different values -in the future. +@value{GDBN} must be linked with the Expat library to support XML +traceframe info discovery. @xref{Expat}. -The description section consists of multiple lines of @sc{ascii} text -separated by newline characters (@code{0xa}). The lines may include a -variety of optional descriptive or context-setting information, such -as tracepoint definitions or register set size. @value{GDBN} will -ignore any line that it does not recognize. An empty line marks the end -of this section. +The top-level structure of the document is shown below: -@c FIXME add some specific types of data +@smallexample + + + + block... + +@end smallexample -The trace frame section consists of a number of consecutive frames. -Each frame begins with a two-byte tracepoint number, followed by a -four-byte size giving the amount of data in the frame. The data in -the frame consists of a number of blocks, each introduced by a -character indicating its type (at least register, memory, and trace -state variable). The data in this section is raw binary, not a -hexadecimal or other encoding; its endianness matches the target's -endianness. +Each traceframe block can be either: -@c FIXME bi-arch may require endianness/arch info in description section +@itemize -@table @code -@item R @var{bytes} -Register block. The number and ordering of bytes matches that of a -@code{g} packet in the remote protocol. Note that these are the -actual bytes, in target order and @value{GDBN} register order, not a -hexadecimal encoding. +@item +A region of collected memory starting at @var{addr} and extending for +@var{length} bytes from there: -@item M @var{address} @var{length} @var{bytes}... -Memory block. This is a contiguous block of memory, at the 8-byte -address @var{address}, with a 2-byte length @var{length}, followed by -@var{length} bytes. +@smallexample + +@end smallexample -@item V @var{number} @var{value} -Trace state variable block. This records the 8-byte signed value -@var{value} of trace state variable numbered @var{number}. +@end itemize -@end table +The formal DTD for the traceframe info format is given below: -Future enhancements of the trace file format may include additional types -of blocks. +@smallexample + + + + + +@end smallexample + +@include agentexpr.texi @node Target Descriptions @appendix Target Descriptions @@ -35379,10 +36683,16 @@ registers using the capitalization used in the description. @subsection ARM Features @cindex target descriptions, ARM features -The @samp{org.gnu.gdb.arm.core} feature is required for ARM targets. +The @samp{org.gnu.gdb.arm.core} feature is required for non-M-profile +ARM targets. It should contain registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc}, and @samp{cpsr}. +For M-profile targets (e.g. Cortex-M3), the @samp{org.gnu.gdb.arm.core} +feature is replaced by @samp{org.gnu.gdb.arm.m-profile}. It should contain +registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc}, +and @samp{xpsr}. + The @samp{org.gnu.gdb.arm.fpa} feature is optional. If present, it should contain registers @samp{f0} through @samp{f7} and @samp{fps}. @@ -35449,7 +36759,6 @@ describe the upper 128 bits of @sc{ymm} registers: @samp{ymm0h} through @samp{ymm7h} for i386 @item @samp{ymm0h} through @samp{ymm15h} for amd64 -@item @end itemize The @samp{org.gnu.gdb.i386.linux} feature is optional. It should @@ -35580,6 +36889,59 @@ should contain a comma-separated list of cores that this process is running on. Target may provide additional columns, which @value{GDBN} currently ignores. +@node Trace File Format +@appendix Trace File Format +@cindex trace file format + +The trace file comes in three parts: a header, a textual description +section, and a trace frame section with binary data. + +The header has the form @code{\x7fTRACE0\n}. The first byte is +@code{0x7f} so as to indicate that the file contains binary data, +while the @code{0} is a version number that may have different values +in the future. + +The description section consists of multiple lines of @sc{ascii} text +separated by newline characters (@code{0xa}). The lines may include a +variety of optional descriptive or context-setting information, such +as tracepoint definitions or register set size. @value{GDBN} will +ignore any line that it does not recognize. An empty line marks the end +of this section. + +@c FIXME add some specific types of data + +The trace frame section consists of a number of consecutive frames. +Each frame begins with a two-byte tracepoint number, followed by a +four-byte size giving the amount of data in the frame. The data in +the frame consists of a number of blocks, each introduced by a +character indicating its type (at least register, memory, and trace +state variable). The data in this section is raw binary, not a +hexadecimal or other encoding; its endianness matches the target's +endianness. + +@c FIXME bi-arch may require endianness/arch info in description section + +@table @code +@item R @var{bytes} +Register block. The number and ordering of bytes matches that of a +@code{g} packet in the remote protocol. Note that these are the +actual bytes, in target order and @value{GDBN} register order, not a +hexadecimal encoding. + +@item M @var{address} @var{length} @var{bytes}... +Memory block. This is a contiguous block of memory, at the 8-byte +address @var{address}, with a 2-byte length @var{length}, followed by +@var{length} bytes. + +@item V @var{number} @var{value} +Trace state variable block. This records the 8-byte signed value +@var{value} of trace state variable numbered @var{number}. + +@end table + +Future enhancements of the trace file format may include additional types +of blocks. + @include gpl.texi @node GNU Free Documentation License diff --git a/contrib/gdb-7/gdb/doc/gdbint.texinfo b/contrib/gdb-7/gdb/doc/gdbint.texinfo index 54187dd54d..a49470708f 100644 --- a/contrib/gdb-7/gdb/doc/gdbint.texinfo +++ b/contrib/gdb-7/gdb/doc/gdbint.texinfo @@ -10,7 +10,7 @@ @copying Copyright @copyright{} 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, -2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 +2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions. Written by John Gilmore. Second Edition by Stan Shebs. @@ -83,7 +83,8 @@ as the mechanisms that adapt @value{GDBN} to specific hosts and targets. * Target Vector Definition:: * Native Debugging:: * Support Libraries:: -* Coding:: +* Coding Standards:: +* Misc Guidelines:: * Porting GDB:: * Versions and Branches:: * Start of New Year Procedure:: @@ -1322,9 +1323,9 @@ be signaled. @deftypefun {struct cleanup *} make_cleanup_ui_out_tuple_begin_end (struct ui_out *@var{uiout}, const char *@var{id}) This function first opens the tuple and then establishes a cleanup -(@pxref{Coding, Cleanups}) to close the tuple. It provides a convenient -and correct implementation of the non-portable@footnote{The function -cast is not portable ISO C.} code sequence: +(@pxref{Misc Guidelines, Cleanups}) to close the tuple. +It provides a convenient and correct implementation of the +non-portable@footnote{The function cast is not portable ISO C.} code sequence: @smallexample struct cleanup *old_cleanup; ui_out_tuple_begin (uiout, "..."); @@ -1349,7 +1350,8 @@ be signaled. @deftypefun {struct cleanup *} make_cleanup_ui_out_list_begin_end (struct ui_out *@var{uiout}, const char *@var{id}) Similar to @code{make_cleanup_ui_out_tuple_begin_end}, this function -opens a list and then establishes cleanup (@pxref{Coding, Cleanups}) +opens a list and then establishes cleanup +(@pxref{Misc Guidelines, Cleanups}) that will close the list. @end deftypefun @@ -5756,9 +5758,257 @@ Binary search the array. @section include -@node Coding +@node Coding Standards -@chapter Coding +@chapter Coding Standards +@cindex coding standards + +@section @value{GDBN} C Coding Standards + +@value{GDBN} follows the GNU coding standards, as described in +@file{etc/standards.texi}. This file is also available for anonymous +FTP from GNU archive sites. @value{GDBN} takes a strict interpretation +of the standard; in general, when the GNU standard recommends a practice +but does not require it, @value{GDBN} requires it. + +@value{GDBN} follows an additional set of coding standards specific to +@value{GDBN}, as described in the following sections. + +@subsection ISO C + +@value{GDBN} assumes an ISO/IEC 9899:1990 (a.k.a.@: ISO C90) compliant +compiler. + +@value{GDBN} does not assume an ISO C or POSIX compliant C library. + +@subsection Formatting + +@cindex source code formatting +The standard GNU recommendations for formatting must be followed +strictly. Any @value{GDBN}-specific deviation from GNU +recomendations is described below. + +A function declaration should not have its name in column zero. A +function definition should have its name in column zero. + +@smallexample +/* Declaration */ +static void foo (void); +/* Definition */ +void +foo (void) +@{ +@} +@end smallexample + +@emph{Pragmatics: This simplifies scripting. Function definitions can +be found using @samp{^function-name}.} + +There must be a space between a function or macro name and the opening +parenthesis of its argument list (except for macro definitions, as +required by C). There must not be a space after an open paren/bracket +or before a close paren/bracket. + +While additional whitespace is generally helpful for reading, do not use +more than one blank line to separate blocks, and avoid adding whitespace +after the end of a program line (as of 1/99, some 600 lines had +whitespace after the semicolon). Excess whitespace causes difficulties +for @code{diff} and @code{patch} utilities. + +Pointers are declared using the traditional K&R C style: + +@smallexample +void *foo; +@end smallexample + +@noindent +and not: + +@smallexample +void * foo; +void* foo; +@end smallexample + +In addition, whitespace around casts and unary operators should follow +the following guidelines: + +@multitable @columnfractions .2 .2 .8 +@item Use... @tab ...instead of @tab + +@item @code{!x} +@tab @code{! x} +@item @code{~x} +@tab @code{~ x} +@item @code{-x} +@tab @code{- x} +@tab (unary minus) +@item @code{(foo) x} +@tab @code{(foo)x} +@tab (cast) +@item @code{*x} +@tab @code{* x} +@tab (pointer dereference) +@end multitable + +@subsection Comments + +@cindex comment formatting +The standard GNU requirements on comments must be followed strictly. + +Block comments must appear in the following form, with no @code{/*}- or +@code{*/}-only lines, and no leading @code{*}: + +@smallexample +/* Wait for control to return from inferior to debugger. If inferior + gets a signal, we may decide to start it up again instead of + returning. That is why there is a loop in this function. When + this function actually returns it means the inferior should be left + stopped and @value{GDBN} should read more commands. */ +@end smallexample + +(Note that this format is encouraged by Emacs; tabbing for a multi-line +comment works correctly, and @kbd{M-q} fills the block consistently.) + +Put a blank line between the block comments preceding function or +variable definitions, and the definition itself. + +In general, put function-body comments on lines by themselves, rather +than trying to fit them into the 20 characters left at the end of a +line, since either the comment or the code will inevitably get longer +than will fit, and then somebody will have to move it anyhow. + +@subsection C Usage + +@cindex C data types +Code must not depend on the sizes of C data types, the format of the +host's floating point numbers, the alignment of anything, or the order +of evaluation of expressions. + +@cindex function usage +Use functions freely. There are only a handful of compute-bound areas +in @value{GDBN} that might be affected by the overhead of a function +call, mainly in symbol reading. Most of @value{GDBN}'s performance is +limited by the target interface (whether serial line or system call). + +However, use functions with moderation. A thousand one-line functions +are just as hard to understand as a single thousand-line function. + +@emph{Macros are bad, M'kay.} +(But if you have to use a macro, make sure that the macro arguments are +protected with parentheses.) + +@cindex types + +Declarations like @samp{struct foo *} should be used in preference to +declarations like @samp{typedef struct foo @{ @dots{} @} *foo_ptr}. + +@subsection Function Prototypes +@cindex function prototypes + +Prototypes must be used when both @emph{declaring} and @emph{defining} +a function. Prototypes for @value{GDBN} functions must include both the +argument type and name, with the name matching that used in the actual +function definition. + +All external functions should have a declaration in a header file that +callers include, except for @code{_initialize_*} functions, which must +be external so that @file{init.c} construction works, but shouldn't be +visible to random source files. + +Where a source file needs a forward declaration of a static function, +that declaration must appear in a block near the top of the source file. + +@subsection File Names + +Any file used when building the core of @value{GDBN} must be in lower +case. Any file used when building the core of @value{GDBN} must be 8.3 +unique. These requirements apply to both source and generated files. + +@emph{Pragmatics: The core of @value{GDBN} must be buildable on many +platforms including DJGPP and MacOS/HFS. Every time an unfriendly file +is introduced to the build process both @file{Makefile.in} and +@file{configure.in} need to be modified accordingly. Compare the +convoluted conversion process needed to transform @file{COPYING} into +@file{copying.c} with the conversion needed to transform +@file{version.in} into @file{version.c}.} + +Any file non 8.3 compliant file (that is not used when building the core +of @value{GDBN}) must be added to @file{gdb/config/djgpp/fnchange.lst}. + +@emph{Pragmatics: This is clearly a compromise.} + +When @value{GDBN} has a local version of a system header file (ex +@file{string.h}) the file name based on the POSIX header prefixed with +@file{gdb_} (@file{gdb_string.h}). These headers should be relatively +independent: they should use only macros defined by @file{configure}, +the compiler, or the host; they should include only system headers; they +should refer only to system types. They may be shared between multiple +programs, e.g.@: @value{GDBN} and @sc{gdbserver}. + +For other files @samp{-} is used as the separator. + +@subsection Include Files + +A @file{.c} file should include @file{defs.h} first. + +A @file{.c} file should directly include the @code{.h} file of every +declaration and/or definition it directly refers to. It cannot rely on +indirect inclusion. + +A @file{.h} file should directly include the @code{.h} file of every +declaration and/or definition it directly refers to. It cannot rely on +indirect inclusion. Exception: The file @file{defs.h} does not need to +be directly included. + +An external declaration should only appear in one include file. + +An external declaration should never appear in a @code{.c} file. +Exception: a declaration for the @code{_initialize} function that +pacifies @option{-Wmissing-declaration}. + +A @code{typedef} definition should only appear in one include file. + +An opaque @code{struct} declaration can appear in multiple @file{.h} +files. Where possible, a @file{.h} file should use an opaque +@code{struct} declaration instead of an include. + +All @file{.h} files should be wrapped in: + +@smallexample +#ifndef INCLUDE_FILE_NAME_H +#define INCLUDE_FILE_NAME_H +header body +#endif +@end smallexample + +@section @value{GDBN} Python Coding Standards + +@value{GDBN} follows the published @code{Python} coding standards in +@uref{http://www.python.org/dev/peps/pep-0008/, @code{PEP008}}. + +In addition, the guidelines in the +@uref{http://google-styleguide.googlecode.com/svn/trunk/pyguide.html, +Google Python Style Guide} are also followed where they do not +conflict with @code{PEP008}. + +@subsection @value{GDBN}-specific exceptions + +There are a few exceptions to the published standards. +They exist mainly for consistency with the @code{C} standards. + +@c It is expected that there are a few more exceptions, +@c so we use itemize here. + +@itemize @bullet + +@item +Use @code{FIXME} instead of @code{TODO}. + +@end itemize + +@node Misc Guidelines + +@chapter Misc Guidelines This chapter covers topics that are lower-level than the major algorithms of @value{GDBN}. @@ -5995,28 +6245,7 @@ finish by printing a newline, to flush the wrap buffer, before switching to unfiltered (@code{printf}) output. Symbol reading routines that print warnings are a good example. -@section @value{GDBN} Coding Standards -@cindex coding standards - -@value{GDBN} follows the GNU coding standards, as described in -@file{etc/standards.texi}. This file is also available for anonymous -FTP from GNU archive sites. @value{GDBN} takes a strict interpretation -of the standard; in general, when the GNU standard recommends a practice -but does not require it, @value{GDBN} requires it. - -@value{GDBN} follows an additional set of coding standards specific to -@value{GDBN}, as described in the following sections. - - -@subsection ISO C - -@value{GDBN} assumes an ISO/IEC 9899:1990 (a.k.a.@: ISO C90) compliant -compiler. - -@value{GDBN} does not assume an ISO C or POSIX compliant C library. - - -@subsection Memory Management +@section Memory Management @value{GDBN} does not use the functions @code{malloc}, @code{realloc}, @code{calloc}, @code{free} and @code{asprintf}. @@ -6054,7 +6283,7 @@ functions such as @code{sprintf} are very prone to buffer overflow errors.} -@subsection Compiler Warnings +@section Compiler Warnings @cindex compiler warnings With few exceptions, developers should avoid the configuration option @@ -6109,124 +6338,7 @@ currently too noisy to enable with @samp{-Werror}. @end table -@subsection Formatting - -@cindex source code formatting -The standard GNU recommendations for formatting must be followed -strictly. - -A function declaration should not have its name in column zero. A -function definition should have its name in column zero. - -@smallexample -/* Declaration */ -static void foo (void); -/* Definition */ -void -foo (void) -@{ -@} -@end smallexample - -@emph{Pragmatics: This simplifies scripting. Function definitions can -be found using @samp{^function-name}.} - -There must be a space between a function or macro name and the opening -parenthesis of its argument list (except for macro definitions, as -required by C). There must not be a space after an open paren/bracket -or before a close paren/bracket. - -While additional whitespace is generally helpful for reading, do not use -more than one blank line to separate blocks, and avoid adding whitespace -after the end of a program line (as of 1/99, some 600 lines had -whitespace after the semicolon). Excess whitespace causes difficulties -for @code{diff} and @code{patch} utilities. - -Pointers are declared using the traditional K&R C style: - -@smallexample -void *foo; -@end smallexample - -@noindent -and not: - -@smallexample -void * foo; -void* foo; -@end smallexample - -@subsection Comments - -@cindex comment formatting -The standard GNU requirements on comments must be followed strictly. - -Block comments must appear in the following form, with no @code{/*}- or -@code{*/}-only lines, and no leading @code{*}: - -@smallexample -/* Wait for control to return from inferior to debugger. If inferior - gets a signal, we may decide to start it up again instead of - returning. That is why there is a loop in this function. When - this function actually returns it means the inferior should be left - stopped and @value{GDBN} should read more commands. */ -@end smallexample - -(Note that this format is encouraged by Emacs; tabbing for a multi-line -comment works correctly, and @kbd{M-q} fills the block consistently.) - -Put a blank line between the block comments preceding function or -variable definitions, and the definition itself. - -In general, put function-body comments on lines by themselves, rather -than trying to fit them into the 20 characters left at the end of a -line, since either the comment or the code will inevitably get longer -than will fit, and then somebody will have to move it anyhow. - -@subsection C Usage - -@cindex C data types -Code must not depend on the sizes of C data types, the format of the -host's floating point numbers, the alignment of anything, or the order -of evaluation of expressions. - -@cindex function usage -Use functions freely. There are only a handful of compute-bound areas -in @value{GDBN} that might be affected by the overhead of a function -call, mainly in symbol reading. Most of @value{GDBN}'s performance is -limited by the target interface (whether serial line or system call). - -However, use functions with moderation. A thousand one-line functions -are just as hard to understand as a single thousand-line function. - -@emph{Macros are bad, M'kay.} -(But if you have to use a macro, make sure that the macro arguments are -protected with parentheses.) - -@cindex types - -Declarations like @samp{struct foo *} should be used in preference to -declarations like @samp{typedef struct foo @{ @dots{} @} *foo_ptr}. - - -@subsection Function Prototypes -@cindex function prototypes - -Prototypes must be used when both @emph{declaring} and @emph{defining} -a function. Prototypes for @value{GDBN} functions must include both the -argument type and name, with the name matching that used in the actual -function definition. - -All external functions should have a declaration in a header file that -callers include, except for @code{_initialize_*} functions, which must -be external so that @file{init.c} construction works, but shouldn't be -visible to random source files. - -Where a source file needs a forward declaration of a static function, -that declaration must appear in a block near the top of the source file. - - -@subsection Internal Error Recovery +@section Internal Error Recovery During its execution, @value{GDBN} can encounter two types of errors. User errors and internal errors. User errors include not only a user @@ -6245,76 +6357,11 @@ the code detected a user error, recovered from it and issued a @code{warning} or the code failed to correctly recover from the user error and issued an @code{internal_error}.} -@subsection Command Names +@section Command Names GDB U/I commands are written @samp{foo-bar}, not @samp{foo_bar}. -@subsection File Names - -Any file used when building the core of @value{GDBN} must be in lower -case. Any file used when building the core of @value{GDBN} must be 8.3 -unique. These requirements apply to both source and generated files. - -@emph{Pragmatics: The core of @value{GDBN} must be buildable on many -platforms including DJGPP and MacOS/HFS. Every time an unfriendly file -is introduced to the build process both @file{Makefile.in} and -@file{configure.in} need to be modified accordingly. Compare the -convoluted conversion process needed to transform @file{COPYING} into -@file{copying.c} with the conversion needed to transform -@file{version.in} into @file{version.c}.} - -Any file non 8.3 compliant file (that is not used when building the core -of @value{GDBN}) must be added to @file{gdb/config/djgpp/fnchange.lst}. - -@emph{Pragmatics: This is clearly a compromise.} - -When @value{GDBN} has a local version of a system header file (ex -@file{string.h}) the file name based on the POSIX header prefixed with -@file{gdb_} (@file{gdb_string.h}). These headers should be relatively -independent: they should use only macros defined by @file{configure}, -the compiler, or the host; they should include only system headers; they -should refer only to system types. They may be shared between multiple -programs, e.g.@: @value{GDBN} and @sc{gdbserver}. - -For other files @samp{-} is used as the separator. - - -@subsection Include Files - -A @file{.c} file should include @file{defs.h} first. - -A @file{.c} file should directly include the @code{.h} file of every -declaration and/or definition it directly refers to. It cannot rely on -indirect inclusion. - -A @file{.h} file should directly include the @code{.h} file of every -declaration and/or definition it directly refers to. It cannot rely on -indirect inclusion. Exception: The file @file{defs.h} does not need to -be directly included. - -An external declaration should only appear in one include file. - -An external declaration should never appear in a @code{.c} file. -Exception: a declaration for the @code{_initialize} function that -pacifies @option{-Wmissing-declaration}. - -A @code{typedef} definition should only appear in one include file. - -An opaque @code{struct} declaration can appear in multiple @file{.h} -files. Where possible, a @file{.h} file should use an opaque -@code{struct} declaration instead of an include. - -All @file{.h} files should be wrapped in: - -@smallexample -#ifndef INCLUDE_FILE_NAME_H -#define INCLUDE_FILE_NAME_H -header body -#endif -@end smallexample - - -@subsection Clean Design and Portable Implementation +@section Clean Design and Portable Implementation @cindex design In addition to getting the syntax right, there's the little question of @@ -6448,7 +6495,6 @@ All debugging code must be controllable using the @samp{set debug messages. Use @code{fprintf_unfiltered(gdb_stdlog, ...}. Do not use @code{#ifdef DEBUG}. - @node Porting GDB @chapter Porting @value{GDBN} diff --git a/contrib/gdb-7/gdb/doc/observer.texi b/contrib/gdb-7/gdb/doc/observer.texi index e19b8ed2a9..d16c865335 100644 --- a/contrib/gdb-7/gdb/doc/observer.texi +++ b/contrib/gdb-7/gdb/doc/observer.texi @@ -2,8 +2,8 @@ @c This file is part of the GDB manual. @c -@c Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 -@c Free Software Foundation, Inc. +@c Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 +@c Free Software Foundation, Inc. @c @c See the file gdbint.texinfo for copying conditions. @c diff --git a/contrib/gdb-7/gdb/doc/stabs.texinfo b/contrib/gdb-7/gdb/doc/stabs.texinfo index eea20bad14..732a170d40 100644 --- a/contrib/gdb-7/gdb/doc/stabs.texinfo +++ b/contrib/gdb-7/gdb/doc/stabs.texinfo @@ -14,7 +14,7 @@ @copying Copyright @copyright{} 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 +2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Julia Menapace, Jim Kingdon, and David MacKenzie. diff --git a/contrib/gdb-7/gdb/doublest.c b/contrib/gdb-7/gdb/doublest.c index 7e8b34345f..a339887f8e 100644 --- a/contrib/gdb-7/gdb/doublest.c +++ b/contrib/gdb-7/gdb/doublest.c @@ -1,8 +1,8 @@ /* Floating point routines for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -60,11 +60,11 @@ get_field (const bfd_byte *data, enum floatformat_byteorders order, { /* We start counting from the other end (i.e, from the high bytes rather than the low bytes). As such, we need to be concerned - with what happens if bit 0 doesn't start on a byte boundary. + with what happens if bit 0 doesn't start on a byte boundary. I.e, we need to properly handle the case where total_len is not evenly divisible by 8. So we compute ``excess'' which represents the number of bits from the end of our starting - byte needed to get to bit 0. */ + byte needed to get to bit 0. */ int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) @@ -104,7 +104,7 @@ get_field (const bfd_byte *data, enum floatformat_byteorders order, } } if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) - /* Mask out bits which are not part of the field */ + /* Mask out bits which are not part of the field. */ result &= ((1UL << len) - 1); return result; } @@ -176,7 +176,7 @@ convert_floatformat_to_doublest (const struct floatformat *fmt, unsigned long mant; unsigned int mant_bits, mant_off; int mant_bits_left; - int special_exponent; /* It's a NaN, denorm or zero */ + int special_exponent; /* It's a NaN, denorm or zero. */ enum floatformat_byteorders order; unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES]; enum float_kind kind; @@ -233,17 +233,17 @@ convert_floatformat_to_doublest (const struct floatformat *fmt, special_exponent = exponent == 0 || exponent == fmt->exp_nan; - /* Don't bias NaNs. Use minimum exponent for denorms. For simplicity, - we don't check for zero as the exponent doesn't matter. Note the cast - to int; exp_bias is unsigned, so it's important to make sure the - operation is done in signed arithmetic. */ + /* Don't bias NaNs. Use minimum exponent for denorms. For + simplicity, we don't check for zero as the exponent doesn't matter. + Note the cast to int; exp_bias is unsigned, so it's important to + make sure the operation is done in signed arithmetic. */ if (!special_exponent) exponent -= fmt->exp_bias; else if (exponent == 0) exponent = 1 - fmt->exp_bias; /* Build the result algebraically. Might go infinite, underflow, etc; - who cares. */ + who cares. */ /* If this format uses a hidden bit, explicitly add it in now. Otherwise, increment the exponent by one to account for the integer bit. */ @@ -355,9 +355,10 @@ ldfrexp (long double value, int *eptr) long double tmp; int exp; - /* Unfortunately, there are no portable functions for extracting the exponent - of a long double, so we have to do it iteratively by multiplying or dividing - by two until the fraction is between 0.5 and 1.0. */ + /* Unfortunately, there are no portable functions for extracting the + exponent of a long double, so we have to do it iteratively by + multiplying or dividing by two until the fraction is between 0.5 + and 1.0. */ if (value < 0.0l) value = -value; @@ -446,7 +447,7 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt, /* From is NaN */ put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len, fmt->exp_nan); - /* Be sure it's not infinity, but NaN value is irrel */ + /* Be sure it's not infinity, but NaN value is irrel. */ put_field (uto, order, fmt->totalsize, fmt->man_start, 32, 1); goto finalize_byteorder; @@ -459,7 +460,7 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt, dfrom = -dfrom; } - if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ + if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity. */ { /* Infinity exponent is same as NaN's. */ put_field (uto, order, fmt->totalsize, fmt->exp_start, @@ -699,7 +700,8 @@ floatformat_mantissa (const struct floatformat *fmt, static const struct floatformat *host_float_format = GDB_HOST_FLOAT_FORMAT; static const struct floatformat *host_double_format = GDB_HOST_DOUBLE_FORMAT; -static const struct floatformat *host_long_double_format = GDB_HOST_LONG_DOUBLE_FORMAT; +static const struct floatformat *host_long_double_format + = GDB_HOST_LONG_DOUBLE_FORMAT; void floatformat_to_doublest (const struct floatformat *fmt, @@ -791,7 +793,7 @@ floatformat_from_length (struct gdbarch *gdbarch, int len) [gdbarch_byte_order (gdbarch)]; /* On i386 the 'long double' type takes 96 bits, while the real number of used bits is only 80, - both in processor and in memory. + both in processor and in memory. The code below accepts the real bit size. */ else if ((gdbarch_long_double_format (gdbarch) != NULL) && (len * TARGET_CHAR_BIT @@ -924,7 +926,8 @@ _initialize_doublest (void) floatformat_ieee_single[BFD_ENDIAN_BIG] = &floatformat_ieee_single_big; floatformat_ieee_double[BFD_ENDIAN_LITTLE] = &floatformat_ieee_double_little; floatformat_ieee_double[BFD_ENDIAN_BIG] = &floatformat_ieee_double_big; - floatformat_arm_ext[BFD_ENDIAN_LITTLE] = &floatformat_arm_ext_littlebyte_bigword; + floatformat_arm_ext[BFD_ENDIAN_LITTLE] + = &floatformat_arm_ext_littlebyte_bigword; floatformat_arm_ext[BFD_ENDIAN_BIG] = &floatformat_arm_ext_big; floatformat_ia64_spill[BFD_ENDIAN_LITTLE] = &floatformat_ia64_spill_little; floatformat_ia64_spill[BFD_ENDIAN_BIG] = &floatformat_ia64_spill_big; diff --git a/contrib/gdb-7/gdb/doublest.h b/contrib/gdb-7/gdb/doublest.h index 0c17b5cb77..8a3f25dc79 100644 --- a/contrib/gdb-7/gdb/doublest.h +++ b/contrib/gdb-7/gdb/doublest.h @@ -1,8 +1,8 @@ /* Floating point definitions for GDB. Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/dummy-frame.c b/contrib/gdb-7/gdb/dummy-frame.c index d6a7241369..709cd68495 100644 --- a/contrib/gdb-7/gdb/dummy-frame.c +++ b/contrib/gdb-7/gdb/dummy-frame.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -43,7 +43,7 @@ struct dummy_frame gdbarch_dummy_id. */ struct frame_id id; /* The caller's state prior to the call. */ - struct inferior_thread_state *caller_state; + struct infcall_suspend_state *caller_state; }; static struct dummy_frame *dummy_frame_stack = NULL; @@ -86,7 +86,7 @@ deprecated_pc_in_call_dummy (struct gdbarch *gdbarch, CORE_ADDR pc) dummy-frame stack. */ void -dummy_frame_push (struct inferior_thread_state *caller_state, +dummy_frame_push (struct infcall_suspend_state *caller_state, const struct frame_id *dummy_id) { struct dummy_frame *dummy_frame; @@ -106,7 +106,7 @@ remove_dummy_frame (struct dummy_frame **dummy_ptr) struct dummy_frame *dummy = *dummy_ptr; *dummy_ptr = dummy->next; - discard_inferior_thread_state (dummy->caller_state); + discard_infcall_suspend_state (dummy->caller_state); xfree (dummy); } @@ -118,10 +118,10 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr) { struct dummy_frame *dummy; - restore_inferior_thread_state ((*dummy_ptr)->caller_state); + restore_infcall_suspend_state ((*dummy_ptr)->caller_state); - /* restore_inferior_status frees inf_state, - all that remains is to pop *dummy_ptr */ + /* restore_infcall_control_state frees inf_state, + all that remains is to pop *dummy_ptr. */ dummy = *dummy_ptr; *dummy_ptr = dummy->next; xfree (dummy); @@ -220,7 +220,8 @@ dummy_frame_sniffer (const struct frame_unwind *self, struct dummy_frame_cache *cache; cache = FRAME_OBSTACK_ZALLOC (struct dummy_frame_cache); - cache->prev_regcache = get_inferior_thread_state_regcache (dummyframe->caller_state); + cache->prev_regcache = get_infcall_suspend_state_regcache + (dummyframe->caller_state); cache->this_id = this_id; (*this_prologue_cache) = cache; return 1; @@ -274,19 +275,16 @@ dummy_frame_this_id (struct frame_info *this_frame, (*this_id) = cache->this_id; } -static const struct frame_unwind dummy_frame_unwinder = +const struct frame_unwind dummy_frame_unwind = { DUMMY_FRAME, + default_frame_unwind_stop_reason, dummy_frame_this_id, dummy_frame_prev_register, NULL, dummy_frame_sniffer, }; -const struct frame_unwind *const dummy_frame_unwind = { - &dummy_frame_unwinder -}; - static void fprint_dummy_frames (struct ui_file *file) { diff --git a/contrib/gdb-7/gdb/dummy-frame.h b/contrib/gdb-7/gdb/dummy-frame.h index 80f36f8021..dd14a7b7a7 100644 --- a/contrib/gdb-7/gdb/dummy-frame.h +++ b/contrib/gdb-7/gdb/dummy-frame.h @@ -1,6 +1,6 @@ /* Code dealing with dummy stack frames, for GDB, the GNU debugger. - Copyright (C) 2002, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ #include "frame.h" -struct inferior_thread_state; +struct infcall_suspend_state; struct frame_unwind; /* Push the information needed to identify, and unwind from, a dummy @@ -39,7 +39,7 @@ struct frame_unwind; be expanded so that it knowns the lower/upper extent of the dummy frame's code. */ -extern void dummy_frame_push (struct inferior_thread_state *caller_state, +extern void dummy_frame_push (struct infcall_suspend_state *caller_state, const struct frame_id *dummy_id); /* Pop the dummy frame DUMMY_ID, restoring program state to that before the @@ -56,6 +56,6 @@ extern void dummy_frame_pop (struct frame_id dummy_id); /* If the PC falls in a dummy frame, return a dummy frame unwinder. */ -extern const struct frame_unwind *const dummy_frame_unwind; +extern const struct frame_unwind dummy_frame_unwind; #endif /* !defined (DUMMY_FRAME_H) */ diff --git a/contrib/gdb-7/gdb/dwarf2-frame.c b/contrib/gdb-7/gdb/dwarf2-frame.c index a027b0206c..e78c3284ad 100644 --- a/contrib/gdb-7/gdb/dwarf2-frame.c +++ b/contrib/gdb-7/gdb/dwarf2-frame.c @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -38,6 +38,9 @@ #include "complaints.h" #include "dwarf2-frame.h" +#include "ax.h" +#include "dwarf2loc.h" +#include "exceptions.h" struct comp_unit; @@ -77,6 +80,9 @@ struct dwarf2_cie /* Target address size in bytes. */ int addr_size; + /* Target pointer size in bytes. */ + int ptr_size; + /* True if a 'z' augmentation existed. */ unsigned char saw_z_augmentation; @@ -322,11 +328,20 @@ no_get_frame_cfa (void *baton) _("Support for DW_OP_call_frame_cfa is unimplemented")); } +/* Helper function for execute_stack_op. */ + +static CORE_ADDR +no_get_frame_pc (void *baton) +{ + internal_error (__FILE__, __LINE__, _("\ +Support for DW_OP_GNU_implicit_pointer is unimplemented")); +} + static CORE_ADDR no_get_tls_address (void *baton, CORE_ADDR offset) { - internal_error (__FILE__, __LINE__, - _("Support for DW_OP_GNU_push_tls_address is unimplemented")); + internal_error (__FILE__, __LINE__, _("\ +Support for DW_OP_GNU_push_tls_address is unimplemented")); } /* Helper function for execute_stack_op. */ @@ -388,6 +403,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, ctx->read_mem = read_mem; ctx->get_frame_base = no_get_frame_base; ctx->get_frame_cfa = no_get_frame_cfa; + ctx->get_frame_pc = no_get_frame_pc; ctx->get_tls_address = no_get_tls_address; ctx->dwarf_call = no_dwarf_call; @@ -403,7 +419,8 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, /* This is actually invalid DWARF, but if we ever do run across it somehow, we might as well support it. So, instead, report it as unimplemented. */ - error (_("Not implemented: computing unwound register using explicit value operator")); + error (_("\ +Not implemented: computing unwound register using explicit value operator")); } do_cleanups (old_chain); @@ -414,13 +431,11 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, static void execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, - const gdb_byte *insn_end, struct frame_info *this_frame, - struct dwarf2_frame_state *fs) + const gdb_byte *insn_end, struct gdbarch *gdbarch, + CORE_ADDR pc, struct dwarf2_frame_state *fs) { int eh_frame_p = fde->eh_frame_p; - CORE_ADDR pc = get_frame_pc (this_frame); int bytes_read; - struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); while (insn_ptr < insn_end && fs->pc <= pc) @@ -452,7 +467,7 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, { case DW_CFA_set_loc: fs->pc = read_encoded_value (fde->cie->unit, fde->cie->encoding, - fde->cie->addr_size, insn_ptr, + fde->cie->ptr_size, insn_ptr, &bytes_read, fde->initial_location); /* Apply the objfile offset for relocatable objects. */ fs->pc += ANOFFSET (fde->cie->unit->objfile->section_offsets, @@ -691,7 +706,8 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"), break; default: - internal_error (__FILE__, __LINE__, _("Unknown CFI encountered.")); + internal_error (__FILE__, __LINE__, + _("Unknown CFI encountered.")); } } } @@ -843,7 +859,8 @@ dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch, register. */ static int -dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p) +dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, + int regnum, int eh_frame_p) { struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); @@ -886,11 +903,94 @@ dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs, } +void +dwarf2_compile_cfa_to_ax (struct agent_expr *expr, struct axs_value *loc, + struct gdbarch *gdbarch, + CORE_ADDR pc, + struct dwarf2_per_cu_data *data) +{ + const int num_regs = gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch); + struct dwarf2_fde *fde; + CORE_ADDR text_offset, cfa; + struct dwarf2_frame_state fs; + int addr_size; + + memset (&fs, 0, sizeof (struct dwarf2_frame_state)); + + fs.pc = pc; + + /* Find the correct FDE. */ + fde = dwarf2_frame_find_fde (&fs.pc, &text_offset); + if (fde == NULL) + error (_("Could not compute CFA; needed to translate this expression")); + + /* Extract any interesting information from the CIE. */ + fs.data_align = fde->cie->data_alignment_factor; + fs.code_align = fde->cie->code_alignment_factor; + fs.retaddr_column = fde->cie->return_address_register; + addr_size = fde->cie->addr_size; + + /* Check for "quirks" - known bugs in producers. */ + dwarf2_frame_find_quirks (&fs, fde); + + /* First decode all the insns in the CIE. */ + execute_cfa_program (fde, fde->cie->initial_instructions, + fde->cie->end, gdbarch, pc, &fs); + + /* Save the initialized register set. */ + fs.initial = fs.regs; + fs.initial.reg = dwarf2_frame_state_copy_regs (&fs.regs); + + /* Then decode the insns in the FDE up to our target PC. */ + execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, pc, &fs); + + /* Calculate the CFA. */ + switch (fs.regs.cfa_how) + { + case CFA_REG_OFFSET: + { + int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, fs.regs.cfa_reg); + + if (regnum == -1) + error (_("Unable to access DWARF register number %d"), + (int) fs.regs.cfa_reg); /* FIXME */ + ax_reg (expr, regnum); + + if (fs.regs.cfa_offset != 0) + { + if (fs.armcc_cfa_offsets_reversed) + ax_const_l (expr, -fs.regs.cfa_offset); + else + ax_const_l (expr, fs.regs.cfa_offset); + ax_simple (expr, aop_add); + } + } + break; + + case CFA_EXP: + ax_const_l (expr, text_offset); + dwarf2_compile_expr_to_ax (expr, loc, gdbarch, addr_size, + fs.regs.cfa_exp, + fs.regs.cfa_exp + fs.regs.cfa_exp_len, + data); + break; + + default: + internal_error (__FILE__, __LINE__, _("Unknown CFA rule.")); + } +} + + struct dwarf2_frame_cache { /* DWARF Call Frame Address. */ CORE_ADDR cfa; + /* Set if the return address column was marked as unavailable + (required non-collected memory or registers to compute). */ + int unavailable_retaddr; + /* Set if the return address column was marked as undefined. */ int undefined_retaddr; @@ -918,6 +1018,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) struct dwarf2_frame_cache *cache; struct dwarf2_frame_state *fs; struct dwarf2_fde *fde; + volatile struct gdb_exception ex; if (*this_cache) return *this_cache; @@ -925,10 +1026,10 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) /* Allocate a new cache. */ cache = FRAME_OBSTACK_ZALLOC (struct dwarf2_frame_cache); cache->reg = FRAME_OBSTACK_CALLOC (num_regs, struct dwarf2_frame_state_reg); + *this_cache = cache; /* Allocate and initialize the frame state. */ - fs = XMALLOC (struct dwarf2_frame_state); - memset (fs, 0, sizeof (struct dwarf2_frame_state)); + fs = XZALLOC (struct dwarf2_frame_state); old_chain = make_cleanup (dwarf2_frame_state_free, fs); /* Unwind the PC. @@ -963,35 +1064,49 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) /* First decode all the insns in the CIE. */ execute_cfa_program (fde, fde->cie->initial_instructions, - fde->cie->end, this_frame, fs); + fde->cie->end, gdbarch, get_frame_pc (this_frame), fs); /* Save the initialized register set. */ fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde, fde->instructions, fde->end, this_frame, fs); + execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, + get_frame_pc (this_frame), fs); - /* Calculate the CFA. */ - switch (fs->regs.cfa_how) + TRY_CATCH (ex, RETURN_MASK_ERROR) { - case CFA_REG_OFFSET: - cache->cfa = read_reg (this_frame, fs->regs.cfa_reg); - if (fs->armcc_cfa_offsets_reversed) - cache->cfa -= fs->regs.cfa_offset; - else - cache->cfa += fs->regs.cfa_offset; - break; - - case CFA_EXP: - cache->cfa = - execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len, - cache->addr_size, cache->text_offset, - this_frame, 0, 0); - break; + /* Calculate the CFA. */ + switch (fs->regs.cfa_how) + { + case CFA_REG_OFFSET: + cache->cfa = read_reg (this_frame, fs->regs.cfa_reg); + if (fs->armcc_cfa_offsets_reversed) + cache->cfa -= fs->regs.cfa_offset; + else + cache->cfa += fs->regs.cfa_offset; + break; + + case CFA_EXP: + cache->cfa = + execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len, + cache->addr_size, cache->text_offset, + this_frame, 0, 0); + break; + + default: + internal_error (__FILE__, __LINE__, _("Unknown CFA rule.")); + } + } + if (ex.reason < 0) + { + if (ex.error == NOT_AVAILABLE_ERROR) + { + cache->unavailable_retaddr = 1; + return cache; + } - default: - internal_error (__FILE__, __LINE__, _("Unknown CFA rule.")); + throw_exception (ex); } /* Initialize the register state. */ @@ -1097,10 +1212,25 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"), do_cleanups (old_chain); - *this_cache = cache; return cache; } +static enum unwind_stop_reason +dwarf2_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct dwarf2_frame_cache *cache + = dwarf2_frame_cache (this_frame, this_cache); + + if (cache->unavailable_retaddr) + return UNWIND_UNAVAILABLE; + + if (cache->undefined_retaddr) + return UNWIND_OUTERMOST; + + return UNWIND_NO_REASON; +} + static void dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -1108,6 +1238,9 @@ dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache, struct dwarf2_frame_cache *cache = dwarf2_frame_cache (this_frame, this_cache); + if (cache->unavailable_retaddr) + return; + if (cache->undefined_retaddr) return; @@ -1225,6 +1358,7 @@ dwarf2_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind dwarf2_frame_unwind = { NORMAL_FRAME, + dwarf2_frame_unwind_stop_reason, dwarf2_frame_this_id, dwarf2_frame_prev_register, NULL, @@ -1234,6 +1368,7 @@ static const struct frame_unwind dwarf2_frame_unwind = static const struct frame_unwind dwarf2_signal_frame_unwind = { SIGTRAMP_FRAME, + dwarf2_frame_unwind_stop_reason, dwarf2_frame_this_id, dwarf2_frame_prev_register, NULL, @@ -1473,7 +1608,8 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding, } break; default: - internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding")); + internal_error (__FILE__, __LINE__, + _("Invalid or unsupported encoding")); } if ((encoding & 0x07) == 0x00) @@ -1520,7 +1656,8 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding, *bytes_read_ptr += 8; return (base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf)); default: - internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding")); + internal_error (__FILE__, __LINE__, + _("Invalid or unsupported encoding")); } } @@ -1679,7 +1816,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, buf += bytes_read; end = buf + length; - /* Are we still within the section? */ + /* Are we still within the section? */ if (end > unit->dwarf_frame_buffer + unit->dwarf_frame_size) return NULL; @@ -1732,13 +1869,6 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, depends on the target address size. */ cie->encoding = DW_EH_PE_absptr; - /* The target address size. For .eh_frame FDEs this is considered - equal to the size of a target pointer. For .dwarf_frame FDEs, - this is supposed to be the target address size from the associated - CU header. FIXME: We do not have a good way to determine the - latter. Always use the target pointer size for now. */ - cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; - /* We'll determine the final value later, but we need to initialize it conservatively. */ cie->signal_frame = 0; @@ -1779,9 +1909,17 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, } else { - cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + cie->addr_size = gdbarch_dwarf2_addr_size (gdbarch); cie->segment_size = 0; } + /* Address values in .eh_frame sections are defined to have the + target's pointer size. Watchout: This breaks frame info for + targets with pointer size < address size, unless a .debug_frame + section exists as well. */ + if (eh_frame_p) + cie->ptr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + else + cie->ptr_size = cie->addr_size; cie->code_alignment_factor = read_unsigned_leb128 (unit->abfd, buf, &bytes_read); @@ -1841,7 +1979,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, { /* Skip. Avoid indirection since we throw away the result. */ gdb_byte encoding = (*buf++) & ~DW_EH_PE_indirect; - read_encoded_value (unit, encoding, cie->addr_size, + read_encoded_value (unit, encoding, cie->ptr_size, buf, &bytes_read, 0); buf += bytes_read; augmentation++; @@ -1907,13 +2045,13 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, gdb_assert (fde->cie != NULL); fde->initial_location = - read_encoded_value (unit, fde->cie->encoding, fde->cie->addr_size, + read_encoded_value (unit, fde->cie->encoding, fde->cie->ptr_size, buf, &bytes_read, 0); buf += bytes_read; fde->address_range = read_encoded_value (unit, fde->cie->encoding & 0x0f, - fde->cie->addr_size, buf, &bytes_read, 0); + fde->cie->ptr_size, buf, &bytes_read, 0); buf += bytes_read; /* A 'z' augmentation in the CIE implies the presence of an @@ -2011,15 +2149,15 @@ decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, break; case ALIGN4: - complaint (&symfile_complaints, - _("Corrupt data in %s:%s; align 4 workaround apparently succeeded"), + complaint (&symfile_complaints, _("\ +Corrupt data in %s:%s; align 4 workaround apparently succeeded"), unit->dwarf_frame_section->owner->filename, unit->dwarf_frame_section->name); break; case ALIGN8: - complaint (&symfile_complaints, - _("Corrupt data in %s:%s; align 8 workaround apparently succeeded"), + complaint (&symfile_complaints, _("\ +Corrupt data in %s:%s; align 8 workaround apparently succeeded"), unit->dwarf_frame_section->owner->filename, unit->dwarf_frame_section->name); break; @@ -2037,8 +2175,9 @@ decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, /* Imported from dwarf2read.c. */ -extern void dwarf2_get_section_info (struct objfile *, const char *, asection **, - gdb_byte **, bfd_size_type *); +extern void dwarf2_get_section_info (struct objfile *, const char *, + asection **, gdb_byte **, + bfd_size_type *); static int qsort_fde_cmp (const void *a, const void *b) diff --git a/contrib/gdb-7/gdb/dwarf2-frame.h b/contrib/gdb-7/gdb/dwarf2-frame.h index 2496f05c42..91d7643be6 100644 --- a/contrib/gdb-7/gdb/dwarf2-frame.h +++ b/contrib/gdb-7/gdb/dwarf2-frame.h @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -26,6 +26,9 @@ struct gdbarch; struct objfile; struct frame_info; +struct dwarf2_per_cu_data; +struct agent_expr; +struct axs_value; /* Register rule. */ @@ -114,12 +117,19 @@ void dwarf2_append_unwinders (struct gdbarch *gdbarch); extern const struct frame_base * dwarf2_frame_base_sniffer (struct frame_info *this_frame); -/* Register the DWARF CFI for OBJFILE. */ - -void dwarf2_frame_build_info (struct objfile *objfile); - /* Compute the DWARF CFA for a frame. */ CORE_ADDR dwarf2_frame_cfa (struct frame_info *this_frame); +/* Update the agent expression EXPR with code to compute the CFA for a + frame at PC. GDBARCH is the architecture of the function at PC. + This function may call dwarf2_compile_expr_to_ax; DATA is passed + through to that function if needed. */ + +extern void dwarf2_compile_cfa_to_ax (struct agent_expr *expr, + struct axs_value *loc, + struct gdbarch *gdbarch, + CORE_ADDR pc, + struct dwarf2_per_cu_data *data); + #endif /* dwarf2-frame.h */ diff --git a/contrib/gdb-7/gdb/dwarf2expr.c b/contrib/gdb-7/gdb/dwarf2expr.c index b9ae108c5f..8976a82ca0 100644 --- a/contrib/gdb-7/gdb/dwarf2expr.c +++ b/contrib/gdb-7/gdb/dwarf2expr.c @@ -1,6 +1,6 @@ /* DWARF 2 Expression Evaluator. - Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Daniel Berlin (dan@dberlin.org) @@ -129,7 +129,8 @@ ULONGEST dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) { if (ctx->stack_len <= n) - error (_("Asked for position %d of stack, stack only has %d elements on it."), + error (_("Asked for position %d of stack, " + "stack only has %d elements on it."), n, ctx->stack_len); return ctx->stack[ctx->stack_len - (1 + n)].value; @@ -183,7 +184,8 @@ int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n) { if (ctx->stack_len <= n) - error (_("Asked for position %d of stack, stack only has %d elements on it."), + error (_("Asked for position %d of stack, " + "stack only has %d elements on it."), n, ctx->stack_len); return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory; @@ -233,6 +235,11 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset) p->v.mem.addr = dwarf_expr_fetch_address (ctx, 0); p->v.mem.in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); } + else if (p->location == DWARF_VALUE_IMPLICIT_POINTER) + { + p->v.ptr.die = ctx->len; + p->v.ptr.offset = (LONGEST) dwarf_expr_fetch (ctx, 0); + } else { p->v.value = dwarf_expr_fetch (ctx, 0); @@ -272,7 +279,7 @@ read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r) error (_("read_uleb128: Corrupted DWARF expression.")); byte = *buf++; - result |= (byte & 0x7f) << shift; + result |= ((ULONGEST) (byte & 0x7f)) << shift; if ((byte & 0x80) == 0) break; shift += 7; @@ -298,7 +305,7 @@ read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r) error (_("read_sleb128: Corrupted DWARF expression.")); byte = *buf++; - result |= (byte & 0x7f) << shift; + result |= ((ULONGEST) (byte & 0x7f)) << shift; shift += 7; if ((byte & 0x80) == 0) break; @@ -527,6 +534,26 @@ execute_stack_op (struct dwarf_expr_context *ctx, dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_stack_value"); goto no_push; + case DW_OP_GNU_implicit_pointer: + { + ULONGEST die; + LONGEST len; + + /* The referred-to DIE. */ + ctx->len = extract_unsigned_integer (op_ptr, ctx->addr_size, + byte_order); + op_ptr += ctx->addr_size; + + /* The byte offset into the data. */ + op_ptr = read_sleb128 (op_ptr, op_end, &len); + result = (ULONGEST) len; + + ctx->location = DWARF_VALUE_IMPLICIT_POINTER; + dwarf_expr_require_composition (op_ptr, op_end, + "DW_OP_GNU_implicit_pointer"); + } + break; + case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: @@ -595,7 +622,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, else if (ctx->location == DWARF_VALUE_REGISTER) result = (ctx->read_reg) (ctx->baton, dwarf_expr_fetch (ctx, 0)); else - error (_("Not implemented: computing frame base using explicit value operator")); + error (_("Not implemented: computing frame " + "base using explicit value operator")); result = result + offset; in_stack_memory = 1; ctx->stack_len = before_stack_len; @@ -623,7 +651,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, struct dwarf_stack_value t1, t2; if (ctx->stack_len < 2) - error (_("Not enough elements for DW_OP_swap. Need 2, have %d."), + error (_("Not enough elements for " + "DW_OP_swap. Need 2, have %d."), ctx->stack_len); t1 = ctx->stack[ctx->stack_len - 1]; t2 = ctx->stack[ctx->stack_len - 2]; @@ -642,7 +671,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, struct dwarf_stack_value t1, t2, t3; if (ctx->stack_len < 3) - error (_("Not enough elements for DW_OP_rot. Need 3, have %d."), + error (_("Not enough elements for " + "DW_OP_rot. Need 3, have %d."), ctx->stack_len); t1 = ctx->stack[ctx->stack_len - 1]; t2 = ctx->stack[ctx->stack_len - 2]; @@ -792,7 +822,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_GNU_push_tls_address: /* Variable is at a constant offset in the thread-local storage block into the objfile for the current thread and - the dynamic linker module containing this expression. Here + the dynamic linker module containing this expression. Here we return returns the offset from that base. The top of the stack has the offset from the beginning of the thread control block at which the variable is located. Nothing @@ -874,6 +904,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, op_ptr += 4; ctx->dwarf_call (ctx, result); goto no_push; + + case DW_OP_GNU_entry_value: + /* This operation is not yet supported by GDB. */ + ctx->location = DWARF_VALUE_OPTIMIZED_OUT; + ctx->stack_len = 0; + ctx->num_pieces = 0; + goto abort_expression; default: error (_("Unhandled dwarf expression opcode 0x%x"), op); @@ -881,9 +918,17 @@ execute_stack_op (struct dwarf_expr_context *ctx, /* Most things push a result value. */ dwarf_expr_push (ctx, result, in_stack_memory); - no_push:; + no_push: + ; } + /* To simplify our main caller, if the result is an implicit + pointer, then make a pieced value. This is ok because we can't + have implicit pointers in contexts where pieces are invalid. */ + if (ctx->location == DWARF_VALUE_IMPLICIT_POINTER) + add_piece (ctx, 8 * ctx->addr_size, 0); + +abort_expression: ctx->recursion_depth--; gdb_assert (ctx->recursion_depth >= 0); #undef sign_ext diff --git a/contrib/gdb-7/gdb/dwarf2expr.h b/contrib/gdb-7/gdb/dwarf2expr.h index 61b8f00330..78ff53fcf2 100644 --- a/contrib/gdb-7/gdb/dwarf2expr.h +++ b/contrib/gdb-7/gdb/dwarf2expr.h @@ -1,6 +1,6 @@ /* DWARF 2 Expression Evaluator. - Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Daniel Berlin . @@ -41,7 +41,10 @@ enum dwarf_value_location DWARF_VALUE_LITERAL, /* The piece was optimized out. */ - DWARF_VALUE_OPTIMIZED_OUT + DWARF_VALUE_OPTIMIZED_OUT, + + /* The piece is an implicit pointer. */ + DWARF_VALUE_IMPLICIT_POINTER }; /* The dwarf expression stack. */ @@ -96,6 +99,9 @@ struct dwarf_expr_context /* Return the CFA for the frame. */ CORE_ADDR (*get_frame_cfa) (void *baton); + /* Return the PC for the frame. */ + CORE_ADDR (*get_frame_pc) (void *baton); + /* Return the thread-local storage address for DW_OP_GNU_push_tls_address. */ CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); @@ -120,8 +126,9 @@ struct dwarf_expr_context /* Location of the value. */ enum dwarf_value_location location; - /* For VALUE_LITERAL, a the current literal value's length and - data. */ + /* For DWARF_VALUE_LITERAL, the current literal value's length and + data. For DWARF_VALUE_IMPLICIT_POINTER, LEN is the offset of the + target DIE. */ ULONGEST len; const gdb_byte *data; @@ -185,6 +192,15 @@ struct dwarf_expr_piece /* The length of the available data. */ ULONGEST length; } literal; + + /* Used for DWARF_VALUE_IMPLICIT_POINTER. */ + struct + { + /* The referent DIE from DW_OP_GNU_implicit_pointer. */ + ULONGEST die; + /* The byte offset into the resulting data. */ + LONGEST offset; + } ptr; } v; /* The length of the piece, in bits. */ @@ -213,7 +229,7 @@ const gdb_byte *read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, const gdb_byte *read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r); -const char *dwarf_stack_op_name (unsigned int, int); +const char *dwarf_stack_op_name (unsigned int); void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *, const char *); diff --git a/contrib/gdb-7/gdb/dwarf2loc.c b/contrib/gdb-7/gdb/dwarf2loc.c index f59bc4052f..4c13307bb0 100644 --- a/contrib/gdb-7/gdb/dwarf2loc.c +++ b/contrib/gdb-7/gdb/dwarf2loc.c @@ -1,6 +1,6 @@ /* DWARF 2 location expression support for GDB. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Daniel Jacobowitz, MontaVista Software, Inc. @@ -48,7 +48,13 @@ static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, const gdb_byte **start, size_t *length); -/* A helper function for dealing with location lists. Given a +static struct value * +dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, + const gdb_byte *data, unsigned short size, + struct dwarf2_per_cu_data *per_cu, + LONGEST byte_offset); + +/* A function for dealing with location lists. Given a symbol baton (BATON) and a pc value (PC), find the appropriate location expression, set *LOCEXPR_LENGTH, and return a pointer to the beginning of the expression. Returns NULL on failure. @@ -56,9 +62,9 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, For now, only return the first matching location expression; there can be more than one in the list. */ -static const gdb_byte * -find_location_expression (struct dwarf2_loclist_baton *baton, - size_t *locexpr_length, CORE_ADDR pc) +const gdb_byte * +dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton, + size_t *locexpr_length, CORE_ADDR pc) { CORE_ADDR low, high; const gdb_byte *loc_ptr, *buf_end; @@ -79,7 +85,8 @@ find_location_expression (struct dwarf2_loclist_baton *baton, while (1) { if (buf_end - loc_ptr < 2 * addr_size) - error (_("find_location_expression: Corrupted DWARF expression.")); + error (_("dwarf2_find_location_expression: " + "Corrupted DWARF expression.")); if (signed_addr_p) low = extract_signed_integer (loc_ptr, addr_size, byte_order); @@ -193,7 +200,7 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, struct dwarf2_loclist_baton *symbaton; symbaton = SYMBOL_LOCATION_BATON (framefunc); - *start = find_location_expression (symbaton, length, pc); + *start = dwarf2_find_location_expression (symbaton, length, pc); } else { @@ -225,6 +232,17 @@ dwarf_expr_frame_cfa (void *baton) return dwarf2_frame_cfa (debaton->frame); } +/* Helper function for dwarf2_evaluate_loc_desc. Computes the PC for + the frame in BATON. */ + +static CORE_ADDR +dwarf_expr_frame_pc (void *baton) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + + return get_frame_address_in_block (debaton->frame); +} + /* Using the objfile specified in BATON, find the address for the current thread's thread-local storage with offset OFFSET. */ static CORE_ADDR @@ -236,16 +254,20 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset) return target_translate_tls_address (objfile, offset); } -/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in current CU - (as is PER_CU). State of the CTX is not affected by the call and return. */ +/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in + current CU (as is PER_CU). State of the CTX is not affected by the + call and return. */ static void per_cu_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset, - struct dwarf2_per_cu_data *per_cu) + struct dwarf2_per_cu_data *per_cu, + CORE_ADDR (*get_frame_pc) (void *baton), + void *baton) { struct dwarf2_locexpr_baton block; - block = dwarf2_fetch_die_location_block (die_offset, per_cu); + block = dwarf2_fetch_die_location_block (die_offset, per_cu, + get_frame_pc, baton); /* DW_OP_call_ref is currently not supported. */ gdb_assert (block.per_cu == per_cu); @@ -260,7 +282,8 @@ dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) { struct dwarf_expr_baton *debaton = ctx->baton; - return per_cu_dwarf_call (ctx, die_offset, debaton->per_cu); + per_cu_dwarf_call (ctx, die_offset, debaton->per_cu, + ctx->get_frame_pc, ctx->baton); } struct piece_closure @@ -268,6 +291,9 @@ struct piece_closure /* Reference count. */ int refc; + /* The CU from which this closure's expression came. */ + struct dwarf2_per_cu_data *per_cu; + /* The number of pieces used to describe this variable. */ int n_pieces; @@ -282,12 +308,14 @@ struct piece_closure PIECES. */ static struct piece_closure * -allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces, +allocate_piece_closure (struct dwarf2_per_cu_data *per_cu, + int n_pieces, struct dwarf_expr_piece *pieces, int addr_size) { struct piece_closure *c = XZALLOC (struct piece_closure); c->refc = 1; + c->per_cu = per_cu; c->n_pieces = n_pieces; c->addr_size = addr_size; c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece); @@ -394,7 +422,7 @@ insert_bits (unsigned int datum, { unsigned int mask; - gdb_assert (dest_offset_bits >= 0 && dest_offset_bits + nbits <= 8); + gdb_assert (dest_offset_bits + nbits <= 8); mask = (1 << nbits) - 1; if (bits_big_endian) @@ -476,7 +504,8 @@ read_pieced_value (struct value *v) long offset = 0; ULONGEST bits_to_skip; gdb_byte *contents; - struct piece_closure *c = (struct piece_closure *) value_computed_closure (v); + struct piece_closure *c + = (struct piece_closure *) value_computed_closure (v); struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v)); size_t type_len; size_t buffer_size = 0; @@ -562,8 +591,20 @@ read_pieced_value (struct value *v) if (gdb_regnum != -1) { - get_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, buffer); + int optim, unavail; + + if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + this_size, buffer, + &optim, &unavail)) + { + /* Just so garbage doesn't ever shine through. */ + memset (buffer, 0, this_size); + + if (optim) + set_value_optimized_out (v, 1); + if (unavail) + mark_value_bytes_unavailable (v, offset, this_size); + } } else { @@ -574,10 +615,10 @@ read_pieced_value (struct value *v) break; case DWARF_VALUE_MEMORY: - if (p->v.mem.in_stack_memory) - read_stack (p->v.mem.addr + source_offset, buffer, this_size); - else - read_memory (p->v.mem.addr + source_offset, buffer, this_size); + read_value_memory (v, offset, + p->v.mem.in_stack_memory, + p->v.mem.addr + source_offset, + buffer, this_size); break; case DWARF_VALUE_STACK: @@ -622,6 +663,11 @@ read_pieced_value (struct value *v) } break; + /* These bits show up as zeros -- but do not cause the value + to be considered optimized-out. */ + case DWARF_VALUE_IMPLICIT_POINTER: + break; + case DWARF_VALUE_OPTIMIZED_OUT: set_value_optimized_out (v, 1); break; @@ -630,7 +676,8 @@ read_pieced_value (struct value *v) internal_error (__FILE__, __LINE__, _("invalid location type")); } - if (p->location != DWARF_VALUE_OPTIMIZED_OUT) + if (p->location != DWARF_VALUE_OPTIMIZED_OUT + && p->location != DWARF_VALUE_IMPLICIT_POINTER) copy_bitwise (contents, dest_offset_bits, intermediate_buffer, source_offset_bits % 8, this_size_bits, bits_big_endian); @@ -648,7 +695,8 @@ write_pieced_value (struct value *to, struct value *from) long offset = 0; ULONGEST bits_to_skip; const gdb_byte *contents; - struct piece_closure *c = (struct piece_closure *) value_computed_closure (to); + struct piece_closure *c + = (struct piece_closure *) value_computed_closure (to); struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to)); size_t type_len; size_t buffer_size = 0; @@ -740,8 +788,22 @@ write_pieced_value (struct value *to, struct value *from) { if (need_bitwise) { - get_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, buffer); + int optim, unavail; + + if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + this_size, buffer, + &optim, &unavail)) + { + if (optim) + error (_("Can't do read-modify-write to " + "update bitfield; containing word has been " + "optimized out")); + if (unavail) + throw_error (NOT_AVAILABLE_ERROR, + _("Can't do read-modify-write to update " + "bitfield; containing word " + "is unavailable")); + } copy_bitwise (buffer, dest_offset_bits, contents, source_offset_bits, this_size_bits, @@ -785,13 +847,24 @@ write_pieced_value (struct value *to, struct value *from) do_cleanups (cleanup); } +/* A helper function that checks bit validity in a pieced value. + CHECK_FOR indicates the kind of validity checking. + DWARF_VALUE_MEMORY means to check whether any bit is valid. + DWARF_VALUE_OPTIMIZED_OUT means to check whether any bit is + optimized out. + DWARF_VALUE_IMPLICIT_POINTER means to check whether the bits are an + implicit pointer. */ + static int check_pieced_value_bits (const struct value *value, int bit_offset, - int bit_length, int validity) + int bit_length, + enum dwarf_value_location check_for) { struct piece_closure *c = (struct piece_closure *) value_computed_closure (value); int i; + int validity = (check_for == DWARF_VALUE_MEMORY + || check_for == DWARF_VALUE_IMPLICIT_POINTER); bit_offset += 8 * value_offset (value); if (value_bitsize (value)) @@ -816,7 +889,13 @@ check_pieced_value_bits (const struct value *value, int bit_offset, else bit_length -= this_size_bits; - if (p->location == DWARF_VALUE_OPTIMIZED_OUT) + if (check_for == DWARF_VALUE_IMPLICIT_POINTER) + { + if (p->location != DWARF_VALUE_IMPLICIT_POINTER) + return 0; + } + else if (p->location == DWARF_VALUE_OPTIMIZED_OUT + || p->location == DWARF_VALUE_IMPLICIT_POINTER) { if (validity) return 0; @@ -835,20 +914,111 @@ static int check_pieced_value_validity (const struct value *value, int bit_offset, int bit_length) { - return check_pieced_value_bits (value, bit_offset, bit_length, 1); + return check_pieced_value_bits (value, bit_offset, bit_length, + DWARF_VALUE_MEMORY); } static int check_pieced_value_invalid (const struct value *value) { return check_pieced_value_bits (value, 0, - 8 * TYPE_LENGTH (value_type (value)), 0); + 8 * TYPE_LENGTH (value_type (value)), + DWARF_VALUE_OPTIMIZED_OUT); +} + +/* An implementation of an lval_funcs method to see whether a value is + a synthetic pointer. */ + +static int +check_pieced_synthetic_pointer (const struct value *value, int bit_offset, + int bit_length) +{ + return check_pieced_value_bits (value, bit_offset, bit_length, + DWARF_VALUE_IMPLICIT_POINTER); +} + +/* A wrapper function for get_frame_address_in_block. */ + +static CORE_ADDR +get_frame_address_in_block_wrapper (void *baton) +{ + return get_frame_address_in_block (baton); +} + +/* An implementation of an lval_funcs method to indirect through a + pointer. This handles the synthetic pointer case when needed. */ + +static struct value * +indirect_pieced_value (struct value *value) +{ + struct piece_closure *c + = (struct piece_closure *) value_computed_closure (value); + struct type *type; + struct frame_info *frame; + struct dwarf2_locexpr_baton baton; + int i, bit_offset, bit_length; + struct dwarf_expr_piece *piece = NULL; + struct value *result; + LONGEST byte_offset; + + type = value_type (value); + if (TYPE_CODE (type) != TYPE_CODE_PTR) + return NULL; + + bit_length = 8 * TYPE_LENGTH (type); + bit_offset = 8 * value_offset (value); + if (value_bitsize (value)) + bit_offset += value_bitpos (value); + + for (i = 0; i < c->n_pieces && bit_length > 0; i++) + { + struct dwarf_expr_piece *p = &c->pieces[i]; + size_t this_size_bits = p->size; + + if (bit_offset > 0) + { + if (bit_offset >= this_size_bits) + { + bit_offset -= this_size_bits; + continue; + } + + bit_length -= this_size_bits - bit_offset; + bit_offset = 0; + } + else + bit_length -= this_size_bits; + + if (p->location != DWARF_VALUE_IMPLICIT_POINTER) + return NULL; + + if (bit_length != 0) + error (_("Invalid use of DW_OP_GNU_implicit_pointer")); + + piece = p; + break; + } + + frame = get_selected_frame (_("No frame selected.")); + byte_offset = value_as_address (value); + + gdb_assert (piece); + baton = dwarf2_fetch_die_location_block (piece->v.ptr.die, c->per_cu, + get_frame_address_in_block_wrapper, + frame); + + result = dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, + baton.data, baton.size, baton.per_cu, + byte_offset); + + return result; } static void * copy_pieced_value_closure (const struct value *v) { - struct piece_closure *c = (struct piece_closure *) value_computed_closure (v); + struct piece_closure *c + = (struct piece_closure *) value_computed_closure (v); ++c->refc; return c; @@ -857,7 +1027,8 @@ copy_pieced_value_closure (const struct value *v) static void free_pieced_value_closure (struct value *v) { - struct piece_closure *c = (struct piece_closure *) value_computed_closure (v); + struct piece_closure *c + = (struct piece_closure *) value_computed_closure (v); --c->refc; if (c->refc == 0) @@ -873,24 +1044,42 @@ static struct lval_funcs pieced_value_funcs = { write_pieced_value, check_pieced_value_validity, check_pieced_value_invalid, + indirect_pieced_value, + check_pieced_synthetic_pointer, copy_pieced_value_closure, free_pieced_value_closure }; +/* Helper function which throws an error if a synthetic pointer is + invalid. */ + +static void +invalid_synthetic_pointer (void) +{ + error (_("access outside bounds of object " + "referenced via synthetic pointer")); +} + /* Evaluate a location description, starting at DATA and with length - SIZE, to find the current location of variable of TYPE in the context - of FRAME. */ + SIZE, to find the current location of variable of TYPE in the + context of FRAME. BYTE_OFFSET is applied after the contents are + computed. */ static struct value * -dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, - const gdb_byte *data, unsigned short size, - struct dwarf2_per_cu_data *per_cu) +dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, + const gdb_byte *data, unsigned short size, + struct dwarf2_per_cu_data *per_cu, + LONGEST byte_offset) { struct value *retval; struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; struct cleanup *old_chain; struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); + volatile struct gdb_exception ex; + + if (byte_offset < 0) + invalid_synthetic_pointer (); if (size == 0) { @@ -914,19 +1103,43 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; ctx->get_frame_cfa = dwarf_expr_frame_cfa; + ctx->get_frame_pc = dwarf_expr_frame_pc; ctx->get_tls_address = dwarf_expr_tls_address; ctx->dwarf_call = dwarf_expr_dwarf_call; - dwarf_expr_eval (ctx, data, size); + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + dwarf_expr_eval (ctx, data, size); + } + if (ex.reason < 0) + { + if (ex.error == NOT_AVAILABLE_ERROR) + { + retval = allocate_value (type); + mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type)); + return retval; + } + else + throw_exception (ex); + } + if (ctx->num_pieces > 0) { struct piece_closure *c; struct frame_id frame_id = get_frame_id (frame); + ULONGEST bit_size = 0; + int i; - c = allocate_piece_closure (ctx->num_pieces, ctx->pieces, + for (i = 0; i < ctx->num_pieces; ++i) + bit_size += ctx->pieces[i].size; + if (8 * (byte_offset + TYPE_LENGTH (type)) > bit_size) + invalid_synthetic_pointer (); + + c = allocate_piece_closure (per_cu, ctx->num_pieces, ctx->pieces, ctx->addr_size); retval = allocate_computed_value (type, &pieced_value_funcs, c); VALUE_FRAME_ID (retval) = frame_id; + set_value_offset (retval, byte_offset); } else { @@ -938,6 +1151,8 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, ULONGEST dwarf_regnum = dwarf_expr_fetch (ctx, 0); int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum); + if (byte_offset != 0) + error (_("cannot use offset on synthetic pointer to register")); if (gdb_regnum != -1) retval = value_from_register (type, gdb_regnum, frame); else @@ -951,47 +1166,71 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0); int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); - retval = allocate_value (type); + retval = allocate_value_lazy (type); VALUE_LVAL (retval) = lval_memory; - set_value_lazy (retval, 1); if (in_stack_memory) set_value_stack (retval, 1); - set_value_address (retval, address); + set_value_address (retval, address + byte_offset); } break; case DWARF_VALUE_STACK: { ULONGEST value = dwarf_expr_fetch (ctx, 0); - bfd_byte *contents; + bfd_byte *contents, *tem; size_t n = ctx->addr_size; + if (byte_offset + TYPE_LENGTH (type) > n) + invalid_synthetic_pointer (); + + tem = alloca (n); + store_unsigned_integer (tem, n, + gdbarch_byte_order (ctx->gdbarch), + value); + + tem += byte_offset; + n -= byte_offset; + retval = allocate_value (type); contents = value_contents_raw (retval); if (n > TYPE_LENGTH (type)) n = TYPE_LENGTH (type); - store_unsigned_integer (contents, n, - gdbarch_byte_order (ctx->gdbarch), - value); + memcpy (contents, tem, n); } break; case DWARF_VALUE_LITERAL: { bfd_byte *contents; + const bfd_byte *ldata; size_t n = ctx->len; + if (byte_offset + TYPE_LENGTH (type) > n) + invalid_synthetic_pointer (); + retval = allocate_value (type); contents = value_contents_raw (retval); + + ldata = ctx->data + byte_offset; + n -= byte_offset; + if (n > TYPE_LENGTH (type)) n = TYPE_LENGTH (type); - memcpy (contents, ctx->data, n); + memcpy (contents, ldata, n); } break; + case DWARF_VALUE_OPTIMIZED_OUT: + retval = allocate_value (type); + VALUE_LVAL (retval) = not_lval; + set_value_optimized_out (retval, 1); + break; + + /* DWARF_VALUE_IMPLICIT_POINTER was converted to a pieced + operation by execute_stack_op. */ + case DWARF_VALUE_IMPLICIT_POINTER: /* DWARF_VALUE_OPTIMIZED_OUT can't occur in this context -- it can only be encountered when making a piece. */ - case DWARF_VALUE_OPTIMIZED_OUT: default: internal_error (__FILE__, __LINE__, _("invalid location type")); } @@ -1003,6 +1242,18 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, return retval; } + +/* The exported interface to dwarf2_evaluate_loc_desc_full; it always + passes 0 as the byte_offset. */ + +struct value * +dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, + const gdb_byte *data, unsigned short size, + struct dwarf2_per_cu_data *per_cu) +{ + return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0); +} + /* Helper functions and baton for dwarf2_loc_desc_needs_frame. */ @@ -1070,7 +1321,8 @@ needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) { struct needs_frame_baton *nf_baton = ctx->baton; - return per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu); + per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu, + ctx->get_frame_pc, ctx->baton); } /* Return non-zero iff the location expression at DATA (length SIZE) @@ -1100,6 +1352,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, ctx->read_mem = needs_frame_read_mem; ctx->get_frame_base = needs_frame_frame_base; ctx->get_frame_cfa = needs_frame_frame_cfa; + ctx->get_frame_pc = needs_frame_frame_cfa; ctx->get_tls_address = needs_frame_tls_address; ctx->dwarf_call = needs_frame_dwarf_call; @@ -1129,8 +1382,15 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, static void unimplemented (unsigned int op) { - error (_("DWARF operator %s cannot be translated to an agent expression"), - dwarf_stack_op_name (op, 1)); + const char *name = dwarf_stack_op_name (op); + + if (name) + error (_("DWARF operator %s cannot be translated to an agent expression"), + name); + else + error (_("Unknown DWARF operator 0x%02x cannot be translated " + "to an agent expression"), + op); } /* A helper function to convert a DWARF register to an arch register. @@ -1191,6 +1451,16 @@ access_memory (struct gdbarch *arch, struct agent_expr *expr, ULONGEST nbits) } } +/* A helper function to return the frame's PC. */ + +static CORE_ADDR +get_ax_pc (void *baton) +{ + struct agent_expr *expr = baton; + + return expr->scope; +} + /* Compile a DWARF location expression to an agent expression. EXPR is the agent expression we are building. @@ -1204,11 +1474,11 @@ access_memory (struct gdbarch *arch, struct agent_expr *expr, ULONGEST nbits) example, if the expression cannot be compiled, or if the expression is invalid. */ -static void -compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, - struct gdbarch *arch, unsigned int addr_size, - const gdb_byte *op_ptr, const gdb_byte *op_end, - struct dwarf2_per_cu_data *per_cu) +void +dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc, + struct gdbarch *arch, unsigned int addr_size, + const gdb_byte *op_ptr, const gdb_byte *op_end, + struct dwarf2_per_cu_data *per_cu) { struct cleanup *cleanups; int i, *offsets; @@ -1495,8 +1765,8 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, &datastart, &datalen); op_ptr = read_sleb128 (op_ptr, op_end, &offset); - compile_dwarf_to_ax (expr, loc, arch, addr_size, datastart, - datastart + datalen, per_cu); + dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, datastart, + datastart + datalen, per_cu); if (offset != 0) { @@ -1518,7 +1788,7 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, case DW_OP_pick: offset = *op_ptr++; - unimplemented (op); + ax_pick (expr, offset); break; case DW_OP_swap: @@ -1526,31 +1796,11 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, break; case DW_OP_over: - /* We can't directly support DW_OP_over, but GCC emits it as - part of a sequence to implement signed modulus. As a - hack, we recognize this sequence. Note that if GCC ever - generates a branch to the middle of this sequence, then - we will die somehow. */ - if (op_end - op_ptr >= 4 - && op_ptr[0] == DW_OP_over - && op_ptr[1] == DW_OP_div - && op_ptr[2] == DW_OP_mul - && op_ptr[3] == DW_OP_minus) - { - /* Sign extend the operands. */ - ax_ext (expr, addr_size_bits); - ax_simple (expr, aop_swap); - ax_ext (expr, addr_size_bits); - ax_simple (expr, aop_swap); - ax_simple (expr, aop_rem_signed); - op_ptr += 4; - } - else - unimplemented (op); + ax_pick (expr, 1); break; case DW_OP_rot: - unimplemented (op); + ax_simple (expr, aop_rot); break; case DW_OP_deref: @@ -1578,8 +1828,10 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, ax_simple (expr, aop_ref64); break; default: + /* Note that dwarf_stack_op_name will never return + NULL here. */ error (_("Unsupported size %d in %s"), - size, dwarf_stack_op_name (op, 1)); + size, dwarf_stack_op_name (op)); } } break; @@ -1731,7 +1983,8 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, break; case DW_OP_call_frame_cfa: - unimplemented (op); + dwarf2_compile_cfa_to_ax (expr, loc, arch, expr->scope, per_cu); + loc->kind = axs_lvalue_memory; break; case DW_OP_GNU_push_tls_address: @@ -1839,14 +2092,15 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, uoffset = extract_unsigned_integer (op_ptr, size, byte_order); op_ptr += size; - block = dwarf2_fetch_die_location_block (uoffset, per_cu); + block = dwarf2_fetch_die_location_block (uoffset, per_cu, + get_ax_pc, expr); /* DW_OP_call_ref is currently not supported. */ gdb_assert (block.per_cu == per_cu); - compile_dwarf_to_ax (expr, loc, arch, addr_size, - block.data, block.data + block.size, - per_cu); + dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, + block.data, block.data + block.size, + per_cu); } break; @@ -1854,7 +2108,7 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, unimplemented (op); default: - error (_("Unhandled dwarf expression opcode 0x%x"), op); + unimplemented (op); } } @@ -1940,7 +2194,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, struct symbol *framefunc; int frame_reg = 0; LONGEST frame_offset; - const gdb_byte *base_data, *new_data; + const gdb_byte *base_data, *new_data, *save_data = data; size_t base_size; LONGEST base_offset = 0; @@ -1971,7 +2225,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, buf_end = read_sleb128 (base_data + 1, base_data + base_size, &base_offset); if (buf_end != base_data + base_size) - error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."), + error (_("Unexpected opcode after " + "DW_OP_breg%u for symbol \"%s\"."), frame_reg, SYMBOL_PRINT_NAME (symbol)); } else if (base_data[0] >= DW_OP_reg0 && base_data[0] <= DW_OP_reg31) @@ -1984,15 +2239,13 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, { /* We don't know what to do with the frame base expression, so we can't trace this variable; give up. */ - error (_("Cannot describe location of symbol \"%s\"; " - "DWARF 2 encoding not handled, " - "first opcode in base data is 0x%x."), - SYMBOL_PRINT_NAME (symbol), base_data[0]); + return save_data; } regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg); - fprintf_filtered (stream, _("a variable at frame base reg $%s offset %s+%s"), + fprintf_filtered (stream, + _("a variable at frame base reg $%s offset %s+%s"), gdbarch_register_name (gdbarch, regno), plongest (base_offset), plongest (frame_offset)); } @@ -2021,9 +2274,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, as the size of an address on the target machine (here is 8 bytes). Note that more recent version of GCC emit DW_OP_const4u or DW_OP_const8u, depending on address size, rather than - DW_OP_addr. 0xe0 is the encoding for - DW_OP_GNU_push_tls_address. The operand represents the offset at - which the variable is within the thread local storage. */ + DW_OP_addr. 0xe0 is the encoding for DW_OP_GNU_push_tls_address. + The operand represents the offset at which the variable is within + the thread local storage. */ else if (data + 1 + addr_size < end && (data[0] == DW_OP_addr @@ -2080,7 +2333,7 @@ disassemble_dwarf_expression (struct ui_file *stream, LONGEST l; const char *name; - name = dwarf_stack_op_name (op, 0); + name = dwarf_stack_op_name (op); if (!name) error (_("Unrecognized DWARF opcode 0x%02x at %ld"), @@ -2225,27 +2478,23 @@ disassemble_dwarf_expression (struct ui_file *stream, case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - data = read_sleb128 (data, end, &ul); - fprintf_filtered (stream, " %s [$%s]", pulongest (ul), + data = read_sleb128 (data, end, &l); + fprintf_filtered (stream, " %s [$%s]", plongest (l), gdbarch_register_name (arch, op - DW_OP_breg0)); break; case DW_OP_bregx: - { - ULONGEST offset; - - data = read_uleb128 (data, end, &ul); - data = read_sleb128 (data, end, &offset); - fprintf_filtered (stream, " register %s [$%s] offset %s", - pulongest (ul), - gdbarch_register_name (arch, (int) ul), - pulongest (offset)); - } + data = read_uleb128 (data, end, &ul); + data = read_sleb128 (data, end, &l); + fprintf_filtered (stream, " register %s [$%s] offset %s", + pulongest (ul), + gdbarch_register_name (arch, (int) ul), + plongest (l)); break; case DW_OP_fbreg: - data = read_sleb128 (data, end, &ul); - fprintf_filtered (stream, " %s", pulongest (ul)); + data = read_sleb128 (data, end, &l); + fprintf_filtered (stream, " %s", plongest (l)); break; case DW_OP_xderef_size: @@ -2308,6 +2557,20 @@ disassemble_dwarf_expression (struct ui_file *stream, pulongest (ul), pulongest (offset)); } break; + + case DW_OP_GNU_implicit_pointer: + { + ul = extract_unsigned_integer (data, offset_size, + gdbarch_byte_order (arch)); + data += offset_size; + + data = read_sleb128 (data, end, &l); + + fprintf_filtered (stream, " DIE %s offset %s", + phex_nz (ul, offset_size), + plongest (l)); + } + break; } fprintf_filtered (stream, "\n"); @@ -2341,7 +2604,8 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr, if (!dwarf2_always_disassemble) { - data = locexpr_describe_location_piece (symbol, stream, addr, objfile, + data = locexpr_describe_location_piece (symbol, stream, + addr, objfile, data, end, addr_size); /* If we printed anything, or if we have an empty piece, then don't disassemble. */ @@ -2351,7 +2615,8 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr, disassemble = 0; } if (disassemble) - data = disassemble_dwarf_expression (stream, get_objfile_arch (objfile), + data = disassemble_dwarf_expression (stream, + get_objfile_arch (objfile), addr_size, offset_size, data, end, dwarf2_always_disassemble); @@ -2415,7 +2680,8 @@ locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr, unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu); - locexpr_describe_location_1 (symbol, addr, stream, dlbaton->data, dlbaton->size, + locexpr_describe_location_1 (symbol, addr, stream, + dlbaton->data, dlbaton->size, objfile, addr_size, offset_size); } @@ -2432,9 +2698,9 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, if (dlbaton->data == NULL || dlbaton->size == 0) value->optimized_out = 1; else - compile_dwarf_to_ax (ax, value, gdbarch, addr_size, - dlbaton->data, dlbaton->data + dlbaton->size, - dlbaton->per_cu); + dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, + dlbaton->data, dlbaton->data + dlbaton->size, + dlbaton->per_cu); } /* The set of location functions used with the DWARF-2 expression @@ -2459,10 +2725,9 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame) struct value *val; const gdb_byte *data; size_t size; + CORE_ADDR pc = frame ? get_frame_address_in_block (frame) : 0; - data = find_location_expression (dlbaton, &size, - frame ? get_frame_address_in_block (frame) - : 0); + data = dwarf2_find_location_expression (dlbaton, &size, pc); if (data == NULL) { val = allocate_value (SYMBOL_TYPE (symbol)); @@ -2582,12 +2847,12 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, size_t size; unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); - data = find_location_expression (dlbaton, &size, ax->scope); + data = dwarf2_find_location_expression (dlbaton, &size, ax->scope); if (data == NULL || size == 0) value->optimized_out = 1; else - compile_dwarf_to_ax (ax, value, gdbarch, addr_size, data, data + size, - dlbaton->per_cu); + dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, data, data + size, + dlbaton->per_cu); } /* The set of location functions used with the DWARF-2 expression diff --git a/contrib/gdb-7/gdb/dwarf2loc.h b/contrib/gdb-7/gdb/dwarf2loc.h index 826bc454c6..96a490e5de 100644 --- a/contrib/gdb-7/gdb/dwarf2loc.h +++ b/contrib/gdb-7/gdb/dwarf2loc.h @@ -1,6 +1,6 @@ /* DWARF 2 location expression support for GDB. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -24,6 +24,9 @@ struct symbol_computed_ops; struct objfile; struct dwarf2_per_cu_data; +struct dwarf2_loclist_baton; +struct agent_expr; +struct axs_value; /* This header is private to the DWARF-2 reader. It is shared between dwarf2read.c and dwarf2loc.c. */ @@ -45,8 +48,26 @@ int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu); offset in the parent objfile. */ CORE_ADDR dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *cu); +/* Find a particular location expression from a location list. */ +const gdb_byte *dwarf2_find_location_expression + (struct dwarf2_loclist_baton *baton, + size_t *locexpr_length, + CORE_ADDR pc); + struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block - (unsigned int offset, struct dwarf2_per_cu_data *per_cu); + (unsigned int offset, struct dwarf2_per_cu_data *per_cu, + CORE_ADDR (*get_frame_pc) (void *baton), + void *baton); + +/* Evaluate a location description, starting at DATA and with length + SIZE, to find the current location of variable of TYPE in the context + of FRAME. */ + +struct value *dwarf2_evaluate_loc_desc (struct type *type, + struct frame_info *frame, + const gdb_byte *data, + unsigned short size, + struct dwarf2_per_cu_data *per_cu); /* The symbol location baton types used by the DWARF-2 reader (i.e. SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct @@ -87,4 +108,25 @@ struct dwarf2_loclist_baton extern const struct symbol_computed_ops dwarf2_locexpr_funcs; extern const struct symbol_computed_ops dwarf2_loclist_funcs; +/* Compile a DWARF location expression to an agent expression. + + EXPR is the agent expression we are building. + LOC is the agent value we modify. + ARCH is the architecture. + ADDR_SIZE is the size of addresses, in bytes. + OP_PTR is the start of the location expression. + OP_END is one past the last byte of the location expression. + + This will throw an exception for various kinds of errors -- for + example, if the expression cannot be compiled, or if the expression + is invalid. */ + +extern void dwarf2_compile_expr_to_ax (struct agent_expr *expr, + struct axs_value *loc, + struct gdbarch *arch, + unsigned int addr_size, + const gdb_byte *op_ptr, + const gdb_byte *op_end, + struct dwarf2_per_cu_data *per_cu); + #endif /* dwarf2loc.h */ diff --git a/contrib/gdb-7/gdb/dwarf2read.c b/contrib/gdb-7/gdb/dwarf2read.c index 1e752357e0..5bc9d0edc9 100644 --- a/contrib/gdb-7/gdb/dwarf2read.c +++ b/contrib/gdb-7/gdb/dwarf2read.c @@ -1,7 +1,7 @@ /* DWARF 2 debugging format support for GDB. Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, @@ -51,6 +51,13 @@ #include "typeprint.h" #include "jv-lang.h" #include "psympriv.h" +#include "exceptions.h" +#include "gdb_stat.h" +#include "completer.h" +#include "vec.h" +#include "c-lang.h" +#include "valprint.h" +#include #include #include "gdb_string.h" @@ -66,6 +73,9 @@ #endif #endif +typedef struct symbol *symbolp; +DEF_VEC_P (symbolp); + #if 0 /* .debug_info header for a compilation unit Because of alignment constraints, this structure has padding and cannot @@ -109,6 +119,9 @@ _STATEMENT_PROLOGUE; /* When non-zero, dump DIEs after they are read in. */ static int dwarf2_die_debug = 0; +/* When non-zero, cross-check physname against demangler. */ +static int check_physname = 0; + static int pagesize; /* When set, the file that we're processing is known to have debugging @@ -129,6 +142,30 @@ struct dwarf2_section_info int readin; }; +/* All offsets in the index are of this type. It must be + architecture-independent. */ +typedef uint32_t offset_type; + +DEF_VEC_I (offset_type); + +/* A description of the mapped index. The file format is described in + a comment by the code that writes the index. */ +struct mapped_index +{ + /* The total length of the buffer. */ + off_t total_size; + /* A pointer to the address table data. */ + const gdb_byte *address_table; + /* Size of the address table data in bytes. */ + offset_type address_table_size; + /* The symbol table, implemented as a hash table. */ + const offset_type *symbol_table; + /* Size in slots, each slot is 2 offset_types. */ + offset_type symbol_table_slots; + /* A pointer to the constant pool. */ + const char *constant_pool; +}; + struct dwarf2_per_objfile { struct dwarf2_section_info info; @@ -141,6 +178,7 @@ struct dwarf2_per_objfile struct dwarf2_section_info types; struct dwarf2_section_info frame; struct dwarf2_section_info eh_frame; + struct dwarf2_section_info gdb_index; /* Back link. */ struct objfile *objfile; @@ -152,6 +190,12 @@ struct dwarf2_per_objfile /* The number of compilation units in ALL_COMP_UNITS. */ int n_comp_units; + /* The number of .debug_types-related CUs. */ + int n_type_comp_units; + + /* The .debug_types-related CUs. */ + struct dwarf2_per_cu_data **type_comp_units; + /* A chain of compilation units that are currently read in, so that they can be freed later. */ struct dwarf2_per_cu_data *read_in_chain; @@ -163,6 +207,33 @@ struct dwarf2_per_objfile /* A flag indicating wether this objfile has a section loaded at a VMA of 0. */ int has_section_at_zero; + + /* True if we are using the mapped index, + or we are faking it for OBJF_READNOW's sake. */ + unsigned char using_index; + + /* The mapped index, or NULL if .gdb_index is missing or not being used. */ + struct mapped_index *index_table; + + /* When using index_table, this keeps track of all quick_file_names entries. + TUs can share line table entries with CUs or other TUs, and there can be + a lot more TUs than unique line tables, so we maintain a separate table + of all line table entries to support the sharing. */ + htab_t quick_file_names_table; + + /* Set during partial symbol reading, to prevent queueing of full + symbols. */ + int reading_partial_symbols; + + /* Table mapping type .debug_info DIE offsets to types. + This is NULL if not allocated yet. + It (currently) makes sense to allocate debug_types_type_hash lazily. + To keep things simple we allocate both lazily. */ + htab_t debug_info_type_hash; + + /* Table mapping type .debug_types DIE offsets to types. + This is NULL if not allocated yet. */ + htab_t debug_types_type_hash; }; static struct dwarf2_per_objfile *dwarf2_per_objfile; @@ -182,10 +253,11 @@ static struct dwarf2_per_objfile *dwarf2_per_objfile; #define TYPES_SECTION "debug_types" #define FRAME_SECTION "debug_frame" #define EH_FRAME_SECTION "eh_frame" +#define GDB_INDEX_SECTION "gdb_index" /* local data types */ -/* We hold several abbreviation tables in memory at the same time. */ +/* We hold several abbreviation tables in memory at the same time. */ #ifndef ABBREV_HASH_SIZE #define ABBREV_HASH_SIZE 121 #endif @@ -215,6 +287,29 @@ struct comp_unit_head unsigned int first_die_offset; }; +/* Type used for delaying computation of method physnames. + See comments for compute_delayed_physnames. */ +struct delayed_method_info +{ + /* The type to which the method is attached, i.e., its parent class. */ + struct type *type; + + /* The index of the method in the type's function fieldlists. */ + int fnfield_index; + + /* The index of the method in the fieldlist. */ + int index; + + /* The name of the DIE. */ + const char *name; + + /* The DIE associated with this method. */ + struct die_info *die; +}; + +typedef struct delayed_method_info delayed_method_info; +DEF_VEC_O (delayed_method_info); + /* Internal state when decoding a particular compilation unit. */ struct dwarf2_cu { @@ -271,11 +366,6 @@ struct dwarf2_cu /* Backchain to our per_cu entry if the tree has been built. */ struct dwarf2_per_cu_data *per_cu; - /* Pointer to the die -> type map. Although it is stored - permanently in per_cu, we copy it here to avoid double - indirection. */ - htab_t type_hash; - /* How many compilation units ago was this CU last referenced? */ int last_used; @@ -293,6 +383,10 @@ struct dwarf2_cu /* Header data from the line table, during full symbol processing. */ struct line_header *line_header; + /* A list of methods which need to have physnames computed + after all type information has been read. */ + VEC (delayed_method_info) *method_list; + /* Mark used when releasing cached dies. */ unsigned int mark : 1; @@ -305,6 +399,13 @@ struct dwarf2_cu DIEs for namespaces, we don't need to try to infer them from mangled names. */ unsigned int has_namespace_info : 1; + + /* This CU references .debug_loc. See the symtab->locations_valid field. + This test is imperfect as there may exist optimized debug code not using + any location list and still facing inlining issues if handled as + unoptimized code. For a future better test see GCC PR other/32998. */ + + unsigned int has_loclist : 1; }; /* Persistent data held for a compilation unit, even when not @@ -341,16 +442,21 @@ struct dwarf2_per_cu_data of the CU cache it gets reset to NULL again. */ struct dwarf2_cu *cu; - /* If full symbols for this CU have been read in, then this field - holds a map of DIE offsets to types. It isn't always possible - to reconstruct this information later, so we have to preserve - it. */ - htab_t type_hash; + /* The corresponding objfile. */ + struct objfile *objfile; - /* The partial symbol table associated with this compilation unit, - or NULL for partial units (which do not have an associated - symtab). */ - struct partial_symtab *psymtab; + /* When using partial symbol tables, the 'psymtab' field is active. + Otherwise the 'quick' field is active. */ + union + { + /* The partial symbol table associated with this compilation unit, + or NULL for partial units (which do not have an associated + symtab). */ + struct partial_symtab *psymtab; + + /* Data needed by the "quick" functions. */ + struct dwarf2_per_cu_quick_data *quick; + } v; }; /* Entry in the signatured_types hash table. */ @@ -369,11 +475,11 @@ struct signatured_type struct dwarf2_per_cu_data per_cu; }; -/* Struct used to pass misc. parameters to read_die_and_children, et. al. - which are used for both .debug_info and .debug_types dies. - All parameters here are unchanging for the life of the call. - This struct exists to abstract away the constant parameters of - die reading. */ +/* Struct used to pass misc. parameters to read_die_and_children, et + al. which are used for both .debug_info and .debug_types dies. + All parameters here are unchanging for the life of the call. This + struct exists to abstract away the constant parameters of die + reading. */ struct die_reader_specs { @@ -436,7 +542,7 @@ struct line_header }; /* When we construct a partial symbol table entry we only - need this much information. */ + need this much information. */ struct partial_die_info { /* Offset of this DIE. */ @@ -460,10 +566,19 @@ struct partial_die_info /* Flag set if the DIE has a byte_size attribute. */ unsigned int has_byte_size : 1; + /* Flag set if any of the DIE's children are template arguments. */ + unsigned int has_template_arguments : 1; + + /* Flag set if fixup_partial_die has been called on this die. */ + unsigned int fixup_called : 1; + /* The name of this DIE. Normally the value of DW_AT_name, but sometimes a default name for unnamed DIEs. */ char *name; + /* The linkage name, if present. */ + const char *linkage_name; + /* The scope to prepend to our children. This is generally allocated on the comp_unit_obstack, so will disappear when this compilation unit leaves the cache. */ @@ -478,6 +593,8 @@ struct partial_die_info /* Pointer into the info_buffer (or types_buffer) pointing at the target of DW_AT_sibling, if any. */ + /* NOTE: This member isn't strictly necessary, read_partial_die could + return DW_AT_sibling values to its caller load_partial_dies. */ gdb_byte *sibling; /* If HAS_SPECIFICATION, the offset of the DIE referred to by @@ -490,7 +607,7 @@ struct partial_die_info struct partial_die_info *die_parent, *die_child, *die_sibling; }; -/* This data structure holds the information of an abbrev. */ +/* This data structure holds the information of an abbrev. */ struct abbrev_info { unsigned int number; /* number identifying abbrev */ @@ -507,7 +624,7 @@ struct attr_abbrev ENUM_BITFIELD(dwarf_form) form : 16; }; -/* Attributes have a name and a value */ +/* Attributes have a name and a value. */ struct attribute { ENUM_BITFIELD(dwarf_attribute) name : 16; @@ -530,14 +647,18 @@ struct attribute u; }; -/* This data structure holds a complete die structure. */ +/* This data structure holds a complete die structure. */ struct die_info { /* DWARF-2 tag for this DIE. */ ENUM_BITFIELD(dwarf_tag) tag : 16; /* Number of attributes */ - unsigned short num_attrs; + unsigned char num_attrs; + + /* True if we're presently building the full type name for the + type derived from this DIE. */ + unsigned char building_fullname : 1; /* Abbrev number */ unsigned int abbrev; @@ -548,8 +669,7 @@ struct die_info /* The dies in a compilation unit form an n-ary tree. PARENT points to this die's parent; CHILD points to the first child of this node; and all the children of a given node are chained - together via their SIBLING fields, terminated by a die whose - tag is zero. */ + together via their SIBLING fields. */ struct die_info *child; /* Its first child, if any. */ struct die_info *sibling; /* Its next sibling, if any. */ struct die_info *parent; /* Its parent, if any. */ @@ -568,7 +688,7 @@ struct function_range struct function_range *next; }; -/* Get at parts of an attribute structure */ +/* Get at parts of an attribute structure. */ #define DW_STRING(attr) ((attr)->u.str) #define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical) @@ -578,7 +698,7 @@ struct function_range #define DW_ADDR(attr) ((attr)->u.addr) #define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type) -/* Blocks are a bunch of untyped bytes. */ +/* Blocks are a bunch of untyped bytes. */ struct dwarf_block { unsigned int size; @@ -604,7 +724,7 @@ static int bits_per_byte = 8; in an instance of a field_info structure, as defined below. */ struct field_info { - /* List of data member and baseclasses fields. */ + /* List of data member and baseclasses fields. */ struct nextfield { struct nextfield *next; @@ -678,13 +798,13 @@ static void show_dwarf2_max_cache_age (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The upper bound on the age of cached dwarf2 compilation units is %s.\n"), + fprintf_filtered (file, _("The upper bound on the age of cached " + "dwarf2 compilation units is %s.\n"), value); } -/* Various complaints about symbol reading that don't abort the process */ +/* Various complaints about symbol reading that don't abort the process. */ static void dwarf2_statement_list_fits_in_line_number_section_complaint (void) @@ -704,7 +824,8 @@ static void dwarf2_debug_line_missing_end_sequence_complaint (void) { complaint (&symfile_complaints, - _(".debug_line section has line program sequence without an end")); + _(".debug_line section has line " + "program sequence without an end")); } static void @@ -718,8 +839,8 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2, int arg3) { complaint (&symfile_complaints, - _("const value length mismatch for '%s', got %d, expected %d"), arg1, - arg2, arg3); + _("const value length mismatch for '%s', got %d, expected %d"), + arg1, arg2, arg3); } static void @@ -733,7 +854,8 @@ static void dwarf2_macro_malformed_definition_complaint (const char *arg1) { complaint (&symfile_complaints, - _("macro debug info contains a malformed macro definition:\n`%s'"), + _("macro debug info contains a " + "malformed macro definition:\n`%s'"), arg1); } @@ -741,7 +863,8 @@ static void dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2) { complaint (&symfile_complaints, - _("invalid attribute class or form for '%s' in '%s'"), arg1, arg2); + _("invalid attribute class or form for '%s' in '%s'"), + arg1, arg2); } /* local function prototypes */ @@ -751,10 +874,6 @@ static void dwarf2_locate_sections (bfd *, asection *, void *); static void dwarf2_create_include_psymtab (char *, struct partial_symtab *, struct objfile *); -static void dwarf2_build_include_psymtabs (struct dwarf2_cu *, - struct die_info *, - struct partial_symtab *); - static void dwarf2_build_psymtabs_hard (struct objfile *); static void scan_partial_symbols (struct partial_die_info *, @@ -845,7 +964,7 @@ static LONGEST read_offset_1 (bfd *, gdb_byte *, unsigned int); static gdb_byte *read_n_bytes (bfd *, gdb_byte *, unsigned int); -static char *read_string (bfd *, gdb_byte *, unsigned int *); +static char *read_direct_string (bfd *, gdb_byte *, unsigned int *); static char *read_indirect_string (bfd *, gdb_byte *, const struct comp_unit_head *, @@ -883,26 +1002,34 @@ static struct line_header *(dwarf_decode_line_header (unsigned int offset, bfd *abfd, struct dwarf2_cu *cu)); -static void dwarf_decode_lines (struct line_header *, char *, bfd *, +static void dwarf_decode_lines (struct line_header *, const char *, bfd *, struct dwarf2_cu *, struct partial_symtab *); -static void dwarf2_start_subfile (char *, char *, char *); +static void dwarf2_start_subfile (char *, const char *, const char *); static struct symbol *new_symbol (struct die_info *, struct type *, struct dwarf2_cu *); +static struct symbol *new_symbol_full (struct die_info *, struct type *, + struct dwarf2_cu *, struct symbol *); + static void dwarf2_const_value (struct attribute *, struct symbol *, struct dwarf2_cu *); -static void dwarf2_const_value_data (struct attribute *attr, - struct symbol *sym, - int bits); +static void dwarf2_const_value_attr (struct attribute *attr, + struct type *type, + const char *name, + struct obstack *obstack, + struct dwarf2_cu *cu, long *value, + gdb_byte **bytes, + struct dwarf2_locexpr_baton **baton); static struct type *die_type (struct die_info *, struct dwarf2_cu *); static int need_gnat_info (struct dwarf2_cu *); -static struct type *die_descriptive_type (struct die_info *, struct dwarf2_cu *); +static struct type *die_descriptive_type (struct die_info *, + struct dwarf2_cu *); static void set_descriptive_type (struct type *, struct die_info *, struct dwarf2_cu *); @@ -910,10 +1037,13 @@ static void set_descriptive_type (struct type *, struct die_info *, static struct type *die_containing_type (struct die_info *, struct dwarf2_cu *); -static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *); +static struct type *lookup_die_type (struct die_info *, struct attribute *, + struct dwarf2_cu *); static struct type *read_type_die (struct die_info *, struct dwarf2_cu *); +static struct type *read_type_die_1 (struct die_info *, struct dwarf2_cu *); + static char *determine_prefix (struct die_info *die, struct dwarf2_cu *); static char *typename_concat (struct obstack *obs, const char *prefix, @@ -953,7 +1083,8 @@ static void dwarf2_add_member_fn (struct field_info *, struct dwarf2_cu *); static void dwarf2_attach_fn_fields_to_type (struct field_info *, - struct type *, struct dwarf2_cu *); + struct type *, + struct dwarf2_cu *); static void process_structure_scope (struct die_info *, struct dwarf2_cu *); @@ -1006,6 +1137,10 @@ static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *, static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *); +static const char *dwarf2_full_name (char *name, + struct die_info *die, + struct dwarf2_cu *cu); + static struct die_info *dwarf2_extension (struct die_info *die, struct dwarf2_cu **); @@ -1083,6 +1218,10 @@ static int attr_form_is_section_offset (struct attribute *); static int attr_form_is_constant (struct attribute *); +static void fill_in_loclist_baton (struct dwarf2_cu *cu, + struct dwarf2_loclist_baton *baton, + struct attribute *attr); + static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu); @@ -1103,7 +1242,11 @@ static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit static struct dwarf2_per_cu_data *dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile); -static struct dwarf2_cu *alloc_one_comp_unit (struct objfile *objfile); +static void init_one_comp_unit (struct dwarf2_cu *cu, + struct objfile *objfile); + +static void prepare_one_comp_unit (struct dwarf2_cu *cu, + struct die_info *comp_unit_die); static void free_one_comp_unit (void *); @@ -1118,6 +1261,8 @@ static struct type *set_die_type (struct die_info *, struct type *, static void create_all_comp_units (struct objfile *); +static int create_debug_types_hash_table (struct objfile *objfile); + static void load_full_comp_unit (struct dwarf2_per_cu_data *, struct objfile *); @@ -1130,8 +1275,63 @@ static void dwarf2_mark (struct dwarf2_cu *); static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); +static struct type *get_die_type_at_offset (unsigned int, + struct dwarf2_per_cu_data *per_cu); + static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); +static void dwarf2_release_queue (void *dummy); + +static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, + struct objfile *objfile); + +static void process_queue (struct objfile *objfile); + +static void find_file_and_directory (struct die_info *die, + struct dwarf2_cu *cu, + char **name, char **comp_dir); + +static char *file_full_name (int file, struct line_header *lh, + const char *comp_dir); + +static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header, + gdb_byte *info_ptr, + gdb_byte *buffer, + unsigned int buffer_size, + bfd *abfd); + +static void init_cu_die_reader (struct die_reader_specs *reader, + struct dwarf2_cu *cu); + +static htab_t allocate_signatured_type_table (struct objfile *objfile); + +#if WORDS_BIGENDIAN + +/* Convert VALUE between big- and little-endian. */ +static offset_type +byte_swap (offset_type value) +{ + offset_type result; + + result = (value & 0xff) << 24; + result |= (value & 0xff00) << 8; + result |= (value & 0xff0000) >> 8; + result |= (value & 0xff000000) >> 24; + return result; +} + +#define MAYBE_SWAP(V) byte_swap (V) + +#else +#define MAYBE_SWAP(V) (V) +#endif /* WORDS_BIGENDIAN */ + +/* The suffix for an index file. */ +#define INDEX_SUFFIX ".gdb-index" + +static const char *dwarf2_physname (char *name, struct die_info *die, + struct dwarf2_cu *cu); + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ @@ -1230,6 +1430,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) dwarf2_per_objfile->types.asection = sectp; dwarf2_per_objfile->types.size = bfd_get_section_size (sectp); } + else if (section_is_p (sectp->name, GDB_INDEX_SECTION)) + { + dwarf2_per_objfile->gdb_index.asection = sectp; + dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp); + } if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD) && bfd_section_vma (abfd, sectp) == 0) @@ -1259,7 +1464,8 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, int header_size = 12; if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 - || bfd_bread (compressed_buffer, compressed_size, abfd) != compressed_size) + || bfd_bread (compressed_buffer, + compressed_size, abfd) != compressed_size) error (_("Dwarf Error: Can't read DWARF data from '%s'"), bfd_get_filename (abfd)); @@ -1314,6 +1520,14 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, #endif } +/* A helper function that decides whether a section is empty. */ + +static int +dwarf2_section_empty_p (struct dwarf2_section_info *info) +{ + return info->asection == NULL || info->size == 0; +} + /* Read the contents of the section SECTP from object file specified by OBJFILE, store info about the section into INFO. If the section is compressed, uncompress it before returning. */ @@ -1332,7 +1546,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) info->was_mmapped = 0; info->readin = 1; - if (info->asection == NULL || info->size == 0) + if (dwarf2_section_empty_p (info)) return; /* Check if the file has a 4-byte header indicating compression. */ @@ -1397,8 +1611,24 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) bfd_get_filename (abfd)); } +/* A helper function that returns the size of a section in a safe way. + If you are positive that the section has been read before using the + size, then it is safe to refer to the dwarf2_section_info object's + "size" field directly. In other cases, you must call this + function, because for compressed sections the size field is not set + correctly until the section has been read. */ + +static bfd_size_type +dwarf2_section_size (struct objfile *objfile, + struct dwarf2_section_info *info) +{ + if (!info->readin) + dwarf2_read_section (objfile, info); + return info->size; +} + /* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and - SECTION_NAME. */ + SECTION_NAME. */ void dwarf2_get_section_info (struct objfile *objfile, const char *section_name, @@ -1423,401 +1653,545 @@ dwarf2_get_section_info (struct objfile *objfile, const char *section_name, else if (section_is_p (section_name, FRAME_SECTION)) info = &data->frame; else - gdb_assert (0); + gdb_assert_not_reached ("unexpected section"); - if (info->asection != NULL && info->size != 0 && info->buffer == NULL) - /* We haven't read this section in yet. Do it now. */ - dwarf2_read_section (objfile, info); + dwarf2_read_section (objfile, info); *sectp = info->asection; *bufp = info->buffer; *sizep = info->size; } -/* Build a partial symbol table. */ + +/* DWARF quick_symbols_functions support. */ -void -dwarf2_build_psymtabs (struct objfile *objfile) +/* TUs can share .debug_line entries, and there can be a lot more TUs than + unique line tables, so we maintain a separate table of all .debug_line + derived entries to support the sharing. + All the quick functions need is the list of file names. We discard the + line_header when we're done and don't need to record it here. */ +struct quick_file_names { - if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0) - { - init_psymbol_list (objfile, 1024); - } + /* The offset in .debug_line of the line table. We hash on this. */ + unsigned int offset; - dwarf2_build_psymtabs_hard (objfile); -} + /* The number of entries in file_names, real_names. */ + unsigned int num_file_names; -/* Return TRUE if OFFSET is within CU_HEADER. */ + /* The file names from the line table, after being run through + file_full_name. */ + const char **file_names; -static inline int -offset_in_cu_p (const struct comp_unit_head *cu_header, unsigned int offset) -{ - unsigned int bottom = cu_header->offset; - unsigned int top = (cu_header->offset - + cu_header->length - + cu_header->initial_length_size); + /* The file names from the line table after being run through + gdb_realpath. These are computed lazily. */ + const char **real_names; +}; - return (offset >= bottom && offset < top); -} +/* When using the index (and thus not using psymtabs), each CU has an + object of this type. This is used to hold information needed by + the various "quick" methods. */ +struct dwarf2_per_cu_quick_data +{ + /* The file table. This can be NULL if there was no file table + or it's currently not read in. + NOTE: This points into dwarf2_per_objfile->quick_file_names_table. */ + struct quick_file_names *file_names; -/* Read in the comp unit header information from the debug_info at info_ptr. - NOTE: This leaves members offset, first_die_offset to be filled in - by the caller. */ + /* The corresponding symbol table. This is NULL if symbols for this + CU have not yet been read. */ + struct symtab *symtab; -static gdb_byte * -read_comp_unit_head (struct comp_unit_head *cu_header, - gdb_byte *info_ptr, bfd *abfd) -{ - int signed_addr; - unsigned int bytes_read; + /* A temporary mark bit used when iterating over all CUs in + expand_symtabs_matching. */ + unsigned int mark : 1; - cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read); - cu_header->initial_length_size = bytes_read; - cu_header->offset_size = (bytes_read == 4) ? 4 : 8; - info_ptr += bytes_read; - cu_header->version = read_2_bytes (abfd, info_ptr); - info_ptr += 2; - cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header, - &bytes_read); - info_ptr += bytes_read; - cu_header->addr_size = read_1_byte (abfd, info_ptr); - info_ptr += 1; - signed_addr = bfd_get_sign_extend_vma (abfd); - if (signed_addr < 0) - internal_error (__FILE__, __LINE__, - _("read_comp_unit_head: dwarf from non elf file")); - cu_header->signed_addr_p = signed_addr; + /* True if we've tried to read the file table and found there isn't one. + There will be no point in trying to read it again next time. */ + unsigned int no_file_data : 1; +}; - return info_ptr; -} +/* Hash function for a quick_file_names. */ -static gdb_byte * -partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, - gdb_byte *buffer, unsigned int buffer_size, - bfd *abfd) +static hashval_t +hash_file_name_entry (const void *e) { - gdb_byte *beg_of_comp_unit = info_ptr; - - info_ptr = read_comp_unit_head (header, info_ptr, abfd); + const struct quick_file_names *file_data = e; - if (header->version != 2 && header->version != 3 && header->version != 4) - error (_("Dwarf Error: wrong version in compilation unit header " - "(is %d, should be 2, 3, or 4) [in module %s]"), header->version, - bfd_get_filename (abfd)); + return file_data->offset; +} - if (header->abbrev_offset >= dwarf2_per_objfile->abbrev.size) - error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header " - "(offset 0x%lx + 6) [in module %s]"), - (long) header->abbrev_offset, - (long) (beg_of_comp_unit - buffer), - bfd_get_filename (abfd)); +/* Equality function for a quick_file_names. */ - if (beg_of_comp_unit + header->length + header->initial_length_size - > buffer + buffer_size) - error (_("Dwarf Error: bad length (0x%lx) in compilation unit header " - "(offset 0x%lx + 0) [in module %s]"), - (long) header->length, - (long) (beg_of_comp_unit - buffer), - bfd_get_filename (abfd)); +static int +eq_file_name_entry (const void *a, const void *b) +{ + const struct quick_file_names *ea = a; + const struct quick_file_names *eb = b; - return info_ptr; + return ea->offset == eb->offset; } -/* Read in the types comp unit header information from .debug_types entry at - types_ptr. The result is a pointer to one past the end of the header. */ +/* Delete function for a quick_file_names. */ -static gdb_byte * -read_type_comp_unit_head (struct comp_unit_head *cu_header, - ULONGEST *signature, - gdb_byte *types_ptr, bfd *abfd) +static void +delete_file_name_entry (void *e) { - gdb_byte *initial_types_ptr = types_ptr; + struct quick_file_names *file_data = e; + int i; - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->types); - cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer; + for (i = 0; i < file_data->num_file_names; ++i) + { + xfree ((void*) file_data->file_names[i]); + if (file_data->real_names) + xfree ((void*) file_data->real_names[i]); + } - types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd); + /* The space for the struct itself lives on objfile_obstack, + so we don't free it here. */ +} - *signature = read_8_bytes (abfd, types_ptr); - types_ptr += 8; - types_ptr += cu_header->offset_size; - cu_header->first_die_offset = types_ptr - initial_types_ptr; +/* Create a quick_file_names hash table. */ - return types_ptr; +static htab_t +create_quick_file_names_table (unsigned int nr_initial_entries) +{ + return htab_create_alloc (nr_initial_entries, + hash_file_name_entry, eq_file_name_entry, + delete_file_name_entry, xcalloc, xfree); } -/* Allocate a new partial symtab for file named NAME and mark this new - partial symtab as being an include of PST. */ +/* Read in the symbols for PER_CU. OBJFILE is the objfile from which + this CU came. */ static void -dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst, - struct objfile *objfile) +dw2_do_instantiate_symtab (struct objfile *objfile, + struct dwarf2_per_cu_data *per_cu) { - struct partial_symtab *subpst = allocate_psymtab (name, objfile); + struct cleanup *back_to; - subpst->section_offsets = pst->section_offsets; - subpst->textlow = 0; - subpst->texthigh = 0; + back_to = make_cleanup (dwarf2_release_queue, NULL); - subpst->dependencies = (struct partial_symtab **) - obstack_alloc (&objfile->objfile_obstack, - sizeof (struct partial_symtab *)); - subpst->dependencies[0] = pst; - subpst->number_of_dependencies = 1; + queue_comp_unit (per_cu, objfile); - subpst->globals_offset = 0; - subpst->n_global_syms = 0; - subpst->statics_offset = 0; - subpst->n_static_syms = 0; - subpst->symtab = NULL; - subpst->read_symtab = pst->read_symtab; - subpst->readin = 0; + if (per_cu->from_debug_types) + read_signatured_type_at_offset (objfile, per_cu->offset); + else + load_full_comp_unit (per_cu, objfile); - /* No private part is necessary for include psymtabs. This property - can be used to differentiate between such include psymtabs and - the regular ones. */ - subpst->read_symtab_private = NULL; + process_queue (objfile); + + /* Age the cache, releasing compilation units that have not + been used recently. */ + age_cached_comp_units (); + + do_cleanups (back_to); } -/* Read the Line Number Program data and extract the list of files - included by the source file represented by PST. Build an include - partial symtab for each of these included files. */ +/* Ensure that the symbols for PER_CU have been read in. OBJFILE is + the objfile from which this CU came. Returns the resulting symbol + table. */ -static void -dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, - struct die_info *die, - struct partial_symtab *pst) +static struct symtab * +dw2_instantiate_symtab (struct objfile *objfile, + struct dwarf2_per_cu_data *per_cu) { - struct objfile *objfile = cu->objfile; - bfd *abfd = objfile->obfd; - struct line_header *lh = NULL; - struct attribute *attr; - - attr = dwarf2_attr (die, DW_AT_stmt_list, cu); - if (attr) + if (!per_cu->v.quick->symtab) { - unsigned int line_offset = DW_UNSND (attr); - - lh = dwarf_decode_line_header (line_offset, abfd, cu); + struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL); + increment_reading_symtab (); + dw2_do_instantiate_symtab (objfile, per_cu); + do_cleanups (back_to); } - if (lh == NULL) - return; /* No linetable, so no includes. */ - - dwarf_decode_lines (lh, NULL, abfd, cu, pst); - - free_line_header (lh); + return per_cu->v.quick->symtab; } -static hashval_t -hash_type_signature (const void *item) -{ - const struct signatured_type *type_sig = item; +/* Return the CU given its index. */ - /* This drops the top 32 bits of the signature, but is ok for a hash. */ - return type_sig->signature; +static struct dwarf2_per_cu_data * +dw2_get_cu (int index) +{ + if (index >= dwarf2_per_objfile->n_comp_units) + { + index -= dwarf2_per_objfile->n_comp_units; + return dwarf2_per_objfile->type_comp_units[index]; + } + return dwarf2_per_objfile->all_comp_units[index]; } +/* A helper function that knows how to read a 64-bit value in a way + that doesn't make gdb die. Returns 1 if the conversion went ok, 0 + otherwise. */ + static int -eq_type_signature (const void *item_lhs, const void *item_rhs) +extract_cu_value (const char *bytes, ULONGEST *result) { - const struct signatured_type *lhs = item_lhs; - const struct signatured_type *rhs = item_rhs; + if (sizeof (ULONGEST) < 8) + { + int i; - return lhs->signature == rhs->signature; + /* Ignore the upper 4 bytes if they are all zero. */ + for (i = 0; i < 4; ++i) + if (bytes[i + 4] != 0) + return 0; + + *result = extract_unsigned_integer (bytes, 4, BFD_ENDIAN_LITTLE); + } + else + *result = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); + return 1; } -/* Create the hash table of all entries in the .debug_types section. - The result is zero if there is an error (e.g. missing .debug_types section), - otherwise non-zero. */ +/* Read the CU list from the mapped index, and use it to create all + the CU objects for this objfile. Return 0 if something went wrong, + 1 if everything went ok. */ static int -create_debug_types_hash_table (struct objfile *objfile) +create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list, + offset_type cu_list_elements) { - gdb_byte *info_ptr; - htab_t types_htab; + offset_type i; - dwarf2_read_section (objfile, &dwarf2_per_objfile->types); - info_ptr = dwarf2_per_objfile->types.buffer; + dwarf2_per_objfile->n_comp_units = cu_list_elements / 2; + dwarf2_per_objfile->all_comp_units + = obstack_alloc (&objfile->objfile_obstack, + dwarf2_per_objfile->n_comp_units + * sizeof (struct dwarf2_per_cu_data *)); - if (info_ptr == NULL) + for (i = 0; i < cu_list_elements; i += 2) { - dwarf2_per_objfile->signatured_types = NULL; - return 0; + struct dwarf2_per_cu_data *the_cu; + ULONGEST offset, length; + + if (!extract_cu_value (cu_list, &offset) + || !extract_cu_value (cu_list + 8, &length)) + return 0; + cu_list += 2 * 8; + + the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_per_cu_data); + the_cu->offset = offset; + the_cu->length = length; + the_cu->objfile = objfile; + the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_per_cu_quick_data); + dwarf2_per_objfile->all_comp_units[i / 2] = the_cu; } - types_htab = htab_create_alloc_ex (41, - hash_type_signature, - eq_type_signature, - NULL, - &objfile->objfile_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); + return 1; +} - if (dwarf2_die_debug) - fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); +/* Create the signatured type hash table from the index. */ - while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) - { - unsigned int offset; - unsigned int offset_size; - unsigned int type_offset; - unsigned int length, initial_length_size; - unsigned short version; - ULONGEST signature; - struct signatured_type *type_sig; - void **slot; - gdb_byte *ptr = info_ptr; +static int +create_signatured_type_table_from_index (struct objfile *objfile, + const gdb_byte *bytes, + offset_type elements) +{ + offset_type i; + htab_t sig_types_hash; - offset = ptr - dwarf2_per_objfile->types.buffer; + dwarf2_per_objfile->n_type_comp_units = elements / 3; + dwarf2_per_objfile->type_comp_units + = obstack_alloc (&objfile->objfile_obstack, + dwarf2_per_objfile->n_type_comp_units + * sizeof (struct dwarf2_per_cu_data *)); - /* We need to read the type's signature in order to build the hash - table, but we don't need to read anything else just yet. */ + sig_types_hash = allocate_signatured_type_table (objfile); - /* Sanity check to ensure entire cu is present. */ - length = read_initial_length (objfile->obfd, ptr, &initial_length_size); - if (ptr + length + initial_length_size - > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) - { - complaint (&symfile_complaints, - _("debug type entry runs off end of `.debug_types' section, ignored")); - break; - } + for (i = 0; i < elements; i += 3) + { + struct signatured_type *type_sig; + ULONGEST offset, type_offset, signature; + void **slot; - offset_size = initial_length_size == 4 ? 4 : 8; - ptr += initial_length_size; - version = bfd_get_16 (objfile->obfd, ptr); - ptr += 2; - ptr += offset_size; /* abbrev offset */ - ptr += 1; /* address size */ - signature = bfd_get_64 (objfile->obfd, ptr); - ptr += 8; - type_offset = read_offset_1 (objfile->obfd, ptr, offset_size); + if (!extract_cu_value (bytes, &offset) + || !extract_cu_value (bytes + 8, &type_offset)) + return 0; + signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); + bytes += 3 * 8; - type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig)); - memset (type_sig, 0, sizeof (*type_sig)); + type_sig = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct signatured_type); type_sig->signature = signature; type_sig->offset = offset; type_sig->type_offset = type_offset; - - slot = htab_find_slot (types_htab, type_sig, INSERT); - gdb_assert (slot != NULL); + type_sig->per_cu.from_debug_types = 1; + type_sig->per_cu.offset = offset; + type_sig->per_cu.objfile = objfile; + type_sig->per_cu.v.quick + = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_per_cu_quick_data); + + slot = htab_find_slot (sig_types_hash, type_sig, INSERT); *slot = type_sig; - if (dwarf2_die_debug) - fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n", - offset, phex (signature, sizeof (signature))); - - info_ptr = info_ptr + initial_length_size + length; + dwarf2_per_objfile->type_comp_units[i / 3] = &type_sig->per_cu; } - dwarf2_per_objfile->signatured_types = types_htab; + dwarf2_per_objfile->signatured_types = sig_types_hash; return 1; } -/* Lookup a signature based type. - Returns NULL if SIG is not present in the table. */ +/* Read the address map data from the mapped index, and use it to + populate the objfile's psymtabs_addrmap. */ -static struct signatured_type * -lookup_signatured_type (struct objfile *objfile, ULONGEST sig) +static void +create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) { - struct signatured_type find_entry, *entry; + const gdb_byte *iter, *end; + struct obstack temp_obstack; + struct addrmap *mutable_map; + struct cleanup *cleanup; + CORE_ADDR baseaddr; - if (dwarf2_per_objfile->signatured_types == NULL) + obstack_init (&temp_obstack); + cleanup = make_cleanup_obstack_free (&temp_obstack); + mutable_map = addrmap_create_mutable (&temp_obstack); + + iter = index->address_table; + end = iter + index->address_table_size; + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + while (iter < end) { - complaint (&symfile_complaints, - _("missing `.debug_types' section for DW_FORM_sig8 die")); - return 0; + ULONGEST hi, lo, cu_index; + lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); + iter += 8; + hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); + iter += 8; + cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); + iter += 4; + + addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1, + dw2_get_cu (cu_index)); } - find_entry.signature = sig; - entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); - return entry; + objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map, + &objfile->objfile_obstack); + do_cleanups (cleanup); } -/* Initialize a die_reader_specs struct from a dwarf2_cu struct. */ +/* The hash function for strings in the mapped index. This is the + same as the hashtab.c hash function, but we keep a separate copy to + maintain control over the implementation. This is necessary + because the hash function is tied to the format of the mapped index + file. */ -static void -init_cu_die_reader (struct die_reader_specs *reader, - struct dwarf2_cu *cu) +static hashval_t +mapped_index_string_hash (const void *p) { - reader->abfd = cu->objfile->obfd; - reader->cu = cu; - if (cu->per_cu->from_debug_types) - { - gdb_assert (dwarf2_per_objfile->types.readin); - reader->buffer = dwarf2_per_objfile->types.buffer; - } - else - { - gdb_assert (dwarf2_per_objfile->info.readin); - reader->buffer = dwarf2_per_objfile->info.buffer; - } + const unsigned char *str = (const unsigned char *) p; + hashval_t r = 0; + unsigned char c; + + while ((c = *str++) != 0) + r = r * 67 + c - 113; + + return r; } -/* Find the base address of the compilation unit for range lists and - location lists. It will normally be specified by DW_AT_low_pc. - In DWARF-3 draft 4, the base address could be overridden by - DW_AT_entry_pc. It's been removed, but GCC still uses this for - compilation units with discontinuous ranges. */ +/* Find a slot in the mapped index INDEX for the object named NAME. + If NAME is found, set *VEC_OUT to point to the CU vector in the + constant pool and return 1. If NAME cannot be found, return 0. */ -static void -dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu) +static int +find_slot_in_mapped_hash (struct mapped_index *index, const char *name, + offset_type **vec_out) { - struct attribute *attr; - - cu->base_known = 0; - cu->base_address = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); + offset_type hash; + offset_type slot, step; - attr = dwarf2_attr (die, DW_AT_entry_pc, cu); - if (attr) + if (current_language->la_language == language_cplus + || current_language->la_language == language_java + || current_language->la_language == language_fortran) { - cu->base_address = DW_ADDR (attr); - cu->base_known = 1; + /* NAME is already canonical. Drop any qualifiers as .gdb_index does + not contain any. */ + const char *paren = strchr (name, '('); + + if (paren) + { + char *dup; + + dup = xmalloc (paren - name + 1); + memcpy (dup, name, paren - name); + dup[paren - name] = 0; + + make_cleanup (xfree, dup); + name = dup; + } } - else + + hash = mapped_index_string_hash (name); + slot = hash & (index->symbol_table_slots - 1); + step = ((hash * 17) & (index->symbol_table_slots - 1)) | 1; + + for (;;) { - attr = dwarf2_attr (die, DW_AT_low_pc, cu); - if (attr) + /* Convert a slot number to an offset into the table. */ + offset_type i = 2 * slot; + const char *str; + if (index->symbol_table[i] == 0 && index->symbol_table[i + 1] == 0) { - cu->base_address = DW_ADDR (attr); - cu->base_known = 1; + do_cleanups (back_to); + return 0; + } + + str = index->constant_pool + MAYBE_SWAP (index->symbol_table[i]); + if (!strcmp (name, str)) + { + *vec_out = (offset_type *) (index->constant_pool + + MAYBE_SWAP (index->symbol_table[i + 1])); + do_cleanups (back_to); + return 1; } + + slot = (slot + step) & (index->symbol_table_slots - 1); } } -/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard - to combine the common parts. - Process a compilation unit for a psymtab. - BUFFER is a pointer to the beginning of the dwarf section buffer, - either .debug_info or debug_types. - INFO_PTR is a pointer to the start of the CU. - Returns a pointer to the next CU. */ +/* Read the index file. If everything went ok, initialize the "quick" + elements of all the CUs and return 1. Otherwise, return 0. */ -static gdb_byte * -process_psymtab_comp_unit (struct objfile *objfile, - struct dwarf2_per_cu_data *this_cu, - gdb_byte *buffer, gdb_byte *info_ptr, - unsigned int buffer_size) +static int +dwarf2_read_index (struct objfile *objfile) +{ + char *addr; + struct mapped_index *map; + offset_type *metadata; + const gdb_byte *cu_list; + const gdb_byte *types_list = NULL; + offset_type version, cu_list_elements; + offset_type types_list_elements = 0; + int i; + + if (dwarf2_section_empty_p (&dwarf2_per_objfile->gdb_index)) + return 0; + + /* Older elfutils strip versions could keep the section in the main + executable while splitting it for the separate debug info file. */ + if ((bfd_get_file_flags (dwarf2_per_objfile->gdb_index.asection) + & SEC_HAS_CONTENTS) == 0) + return 0; + + dwarf2_read_section (objfile, &dwarf2_per_objfile->gdb_index); + + addr = dwarf2_per_objfile->gdb_index.buffer; + /* Version check. */ + version = MAYBE_SWAP (*(offset_type *) addr); + /* Versions earlier than 3 emitted every copy of a psymbol. This + causes the index to behave very poorly for certain requests. Version 3 + contained incomplete addrmap. So, it seems better to just ignore such + indices. */ + if (version < 4) + return 0; + /* Indexes with higher version than the one supported by GDB may be no + longer backward compatible. */ + if (version > 4) + return 0; + + map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index); + map->total_size = dwarf2_per_objfile->gdb_index.size; + + metadata = (offset_type *) (addr + sizeof (offset_type)); + + i = 0; + cu_list = addr + MAYBE_SWAP (metadata[i]); + cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i])) + / 8); + ++i; + + types_list = addr + MAYBE_SWAP (metadata[i]); + types_list_elements = ((MAYBE_SWAP (metadata[i + 1]) + - MAYBE_SWAP (metadata[i])) + / 8); + ++i; + + map->address_table = addr + MAYBE_SWAP (metadata[i]); + map->address_table_size = (MAYBE_SWAP (metadata[i + 1]) + - MAYBE_SWAP (metadata[i])); + ++i; + + map->symbol_table = (offset_type *) (addr + MAYBE_SWAP (metadata[i])); + map->symbol_table_slots = ((MAYBE_SWAP (metadata[i + 1]) + - MAYBE_SWAP (metadata[i])) + / (2 * sizeof (offset_type))); + ++i; + + map->constant_pool = addr + MAYBE_SWAP (metadata[i]); + + if (!create_cus_from_index (objfile, cu_list, cu_list_elements)) + return 0; + + if (types_list_elements + && !create_signatured_type_table_from_index (objfile, types_list, + types_list_elements)) + return 0; + + create_addrmap_from_index (objfile, map); + + dwarf2_per_objfile->index_table = map; + dwarf2_per_objfile->using_index = 1; + dwarf2_per_objfile->quick_file_names_table = + create_quick_file_names_table (dwarf2_per_objfile->n_comp_units); + + return 1; +} + +/* A helper for the "quick" functions which sets the global + dwarf2_per_objfile according to OBJFILE. */ + +static void +dw2_setup (struct objfile *objfile) +{ + dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_assert (dwarf2_per_objfile); +} + +/* A helper for the "quick" functions which attempts to read the line + table for THIS_CU. */ + +static struct quick_file_names * +dw2_get_file_names (struct objfile *objfile, + struct dwarf2_per_cu_data *this_cu) { bfd *abfd = objfile->obfd; - gdb_byte *beg_of_comp_unit = info_ptr; + struct line_header *lh; + struct attribute *attr; + struct cleanup *cleanups; struct die_info *comp_unit_die; - struct partial_symtab *pst; - CORE_ADDR baseaddr; - struct cleanup *back_to_inner; + struct dwarf2_section_info* sec; + gdb_byte *beg_of_comp_unit, *info_ptr, *buffer; + int has_children, i; struct dwarf2_cu cu; - int has_children, has_pc_info; - struct attribute *attr; - CORE_ADDR best_lowpc = 0, best_highpc = 0; + unsigned int bytes_read, buffer_size; struct die_reader_specs reader_specs; + char *name, *comp_dir; + void **slot; + struct quick_file_names *qfn; + unsigned int line_offset; - memset (&cu, 0, sizeof (cu)); - cu.objfile = objfile; - obstack_init (&cu.comp_unit_obstack); + if (this_cu->v.quick->file_names != NULL) + return this_cu->v.quick->file_names; + /* If we know there is no line data, no point in looking again. */ + if (this_cu->v.quick->no_file_data) + return NULL; - back_to_inner = make_cleanup (free_stack_comp_unit, &cu); + init_one_comp_unit (&cu, objfile); + cleanups = make_cleanup (free_stack_comp_unit, &cu); + + if (this_cu->from_debug_types) + sec = &dwarf2_per_objfile->types; + else + sec = &dwarf2_per_objfile->info; + dwarf2_read_section (objfile, sec); + buffer_size = sec->size; + buffer = sec->buffer; + info_ptr = buffer + this_cu->offset; + beg_of_comp_unit = info_ptr; info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, buffer, buffer_size, @@ -1827,8064 +2201,10367 @@ process_psymtab_comp_unit (struct objfile *objfile, cu.header.offset = beg_of_comp_unit - buffer; cu.header.first_die_offset = info_ptr - beg_of_comp_unit; - cu.list_in_scope = &file_symbols; - - /* If this compilation unit was already read in, free the - cached copy in order to read it in again. This is - necessary because we skipped some symbols when we first - read in the compilation unit (see load_partial_dies). - This problem could be avoided, but the benefit is - unclear. */ - if (this_cu->cu != NULL) - free_one_cached_comp_unit (this_cu->cu); - - /* Note that this is a pointer to our stack frame, being - added to a global data structure. It will be cleaned up - in free_stack_comp_unit when we finish with this - compilation unit. */ this_cu->cu = &cu; cu.per_cu = this_cu; - /* Read the abbrevs for this compilation unit into a table. */ dwarf2_read_abbrevs (abfd, &cu); make_cleanup (dwarf2_free_abbrev_table, &cu); - /* Read the compilation unit die. */ if (this_cu->from_debug_types) info_ptr += 8 /*signature*/ + cu.header.offset_size; init_cu_die_reader (&reader_specs, &cu); - info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, - &has_children); + read_full_die (&reader_specs, &comp_unit_die, info_ptr, + &has_children); - if (this_cu->from_debug_types) + lh = NULL; + slot = NULL; + line_offset = 0; + attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu); + if (attr) { - /* offset,length haven't been set yet for type units. */ - this_cu->offset = cu.header.offset; - this_cu->length = cu.header.length + cu.header.initial_length_size; + struct quick_file_names find_entry; + + line_offset = DW_UNSND (attr); + + /* We may have already read in this line header (TU line header sharing). + If we have we're done. */ + find_entry.offset = line_offset; + slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table, + &find_entry, INSERT); + if (*slot != NULL) + { + do_cleanups (cleanups); + this_cu->v.quick->file_names = *slot; + return *slot; + } + + lh = dwarf_decode_line_header (line_offset, abfd, &cu); } - else if (comp_unit_die->tag == DW_TAG_partial_unit) + if (lh == NULL) { - info_ptr = (beg_of_comp_unit + cu.header.length - + cu.header.initial_length_size); - do_cleanups (back_to_inner); - return info_ptr; + do_cleanups (cleanups); + this_cu->v.quick->no_file_data = 1; + return NULL; } - /* Set the language we're debugging. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_language, &cu); - if (attr) - set_cu_language (DW_UNSND (attr), &cu); - else - set_cu_language (language_minimal, &cu); + qfn = obstack_alloc (&objfile->objfile_obstack, sizeof (*qfn)); + qfn->offset = line_offset; + gdb_assert (slot != NULL); + *slot = qfn; - /* Allocate a new partial symbol table structure. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu); - pst = start_psymtab_common (objfile, objfile->section_offsets, - (attr != NULL) ? DW_STRING (attr) : "", - /* TEXTLOW and TEXTHIGH are set below. */ - 0, - objfile->global_psymbols.next, - objfile->static_psymbols.next); + find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir); - attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu); - if (attr != NULL) - pst->dirname = DW_STRING (attr); + qfn->num_file_names = lh->num_file_names; + qfn->file_names = obstack_alloc (&objfile->objfile_obstack, + lh->num_file_names * sizeof (char *)); + for (i = 0; i < lh->num_file_names; ++i) + qfn->file_names[i] = file_full_name (i + 1, lh, comp_dir); + qfn->real_names = NULL; - pst->read_symtab_private = this_cu; + free_line_header (lh); + do_cleanups (cleanups); - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + this_cu->v.quick->file_names = qfn; + return qfn; +} - /* Store the function that reads in the rest of the symbol table */ - pst->read_symtab = dwarf2_psymtab_to_symtab; +/* A helper for the "quick" functions which computes and caches the + real path for a given file name from the line table. */ - this_cu->psymtab = pst; +static const char * +dw2_get_real_path (struct objfile *objfile, + struct quick_file_names *qfn, int index) +{ + if (qfn->real_names == NULL) + qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack, + qfn->num_file_names, sizeof (char *)); - dwarf2_find_base_address (comp_unit_die, &cu); + if (qfn->real_names[index] == NULL) + qfn->real_names[index] = gdb_realpath (qfn->file_names[index]); - /* Possibly set the default values of LOWPC and HIGHPC from - `DW_AT_ranges'. */ - has_pc_info = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, - &best_highpc, &cu, pst); - if (has_pc_info == 1 && best_lowpc < best_highpc) - /* Store the contiguous range if it is not empty; it can be empty for - CUs with no code. */ - addrmap_set_empty (objfile->psymtabs_addrmap, - best_lowpc + baseaddr, - best_highpc + baseaddr - 1, pst); + return qfn->real_names[index]; +} - /* Check if comp unit has_children. - If so, read the rest of the partial symbols from this comp unit. - If not, there's no more debug_info for this comp unit. */ - if (has_children) - { - struct partial_die_info *first_die; - CORE_ADDR lowpc, highpc; +static struct symtab * +dw2_find_last_source_symtab (struct objfile *objfile) +{ + int index; - lowpc = ((CORE_ADDR) -1); - highpc = ((CORE_ADDR) 0); + dw2_setup (objfile); + index = dwarf2_per_objfile->n_comp_units - 1; + return dw2_instantiate_symtab (objfile, dw2_get_cu (index)); +} - first_die = load_partial_dies (abfd, buffer, info_ptr, 1, &cu); +/* Traversal function for dw2_forget_cached_source_info. */ - scan_partial_symbols (first_die, &lowpc, &highpc, - ! has_pc_info, &cu); +static int +dw2_free_cached_file_names (void **slot, void *info) +{ + struct quick_file_names *file_data = (struct quick_file_names *) *slot; - /* If we didn't find a lowpc, set it to highpc to avoid - complaints from `maint check'. */ - if (lowpc == ((CORE_ADDR) -1)) - lowpc = highpc; + if (file_data->real_names) + { + int i; - /* If the compilation unit didn't have an explicit address range, - then use the information extracted from its child dies. */ - if (! has_pc_info) + for (i = 0; i < file_data->num_file_names; ++i) { - best_lowpc = lowpc; - best_highpc = highpc; + xfree ((void*) file_data->real_names[i]); + file_data->real_names[i] = NULL; } } - pst->textlow = best_lowpc + baseaddr; - pst->texthigh = best_highpc + baseaddr; - pst->n_global_syms = objfile->global_psymbols.next - - (objfile->global_psymbols.list + pst->globals_offset); - pst->n_static_syms = objfile->static_psymbols.next - - (objfile->static_psymbols.list + pst->statics_offset); - sort_pst_symbols (pst); + return 1; +} - info_ptr = (beg_of_comp_unit + cu.header.length - + cu.header.initial_length_size); +static void +dw2_forget_cached_source_info (struct objfile *objfile) +{ + dw2_setup (objfile); - if (this_cu->from_debug_types) + htab_traverse_noresize (dwarf2_per_objfile->quick_file_names_table, + dw2_free_cached_file_names, NULL); +} + +static int +dw2_lookup_symtab (struct objfile *objfile, const char *name, + const char *full_path, const char *real_path, + struct symtab **result) +{ + int i; + int check_basename = lbasename (name) == name; + struct dwarf2_per_cu_data *base_cu = NULL; + + dw2_setup (objfile); + + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) { - /* It's not clear we want to do anything with stmt lists here. - Waiting to see what gcc ultimately does. */ + int j; + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct quick_file_names *file_data; + + if (per_cu->v.quick->symtab) + continue; + + file_data = dw2_get_file_names (objfile, per_cu); + if (file_data == NULL) + continue; + + for (j = 0; j < file_data->num_file_names; ++j) + { + const char *this_name = file_data->file_names[j]; + + if (FILENAME_CMP (name, this_name) == 0) + { + *result = dw2_instantiate_symtab (objfile, per_cu); + return 1; + } + + if (check_basename && ! base_cu + && FILENAME_CMP (lbasename (this_name), name) == 0) + base_cu = per_cu; + + if (full_path != NULL) + { + const char *this_real_name = dw2_get_real_path (objfile, + file_data, j); + + if (this_real_name != NULL + && FILENAME_CMP (full_path, this_real_name) == 0) + { + *result = dw2_instantiate_symtab (objfile, per_cu); + return 1; + } + } + + if (real_path != NULL) + { + const char *this_real_name = dw2_get_real_path (objfile, + file_data, j); + + if (this_real_name != NULL + && FILENAME_CMP (real_path, this_real_name) == 0) + { + *result = dw2_instantiate_symtab (objfile, per_cu); + return 1; + } + } + } } - else + + if (base_cu) { - /* Get the list of files included in the current compilation unit, - and build a psymtab for each of them. */ - dwarf2_build_include_psymtabs (&cu, comp_unit_die, pst); + *result = dw2_instantiate_symtab (objfile, base_cu); + return 1; } - do_cleanups (back_to_inner); + return 0; +} - return info_ptr; +static struct symtab * +dw2_lookup_symbol (struct objfile *objfile, int block_index, + const char *name, domain_enum domain) +{ + /* We do all the work in the pre_expand_symtabs_matching hook + instead. */ + return NULL; } -/* Traversal function for htab_traverse_noresize. - Process one .debug_types comp-unit. */ +/* A helper function that expands all symtabs that hold an object + named NAME. */ -static int -process_type_comp_unit (void **slot, void *info) +static void +dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name) { - struct signatured_type *entry = (struct signatured_type *) *slot; - struct objfile *objfile = (struct objfile *) info; - struct dwarf2_per_cu_data *this_cu; + dw2_setup (objfile); - this_cu = &entry->per_cu; - this_cu->from_debug_types = 1; + /* index_table is NULL if OBJF_READNOW. */ + if (dwarf2_per_objfile->index_table) + { + offset_type *vec; - gdb_assert (dwarf2_per_objfile->types.readin); - process_psymtab_comp_unit (objfile, this_cu, - dwarf2_per_objfile->types.buffer, - dwarf2_per_objfile->types.buffer + entry->offset, - dwarf2_per_objfile->types.size); + if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, + name, &vec)) + { + offset_type i, len = MAYBE_SWAP (*vec); + for (i = 0; i < len; ++i) + { + offset_type cu_index = MAYBE_SWAP (vec[i + 1]); + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index); - return 1; + dw2_instantiate_symtab (objfile, per_cu); + } + } + } } -/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. - Build partial symbol tables for the .debug_types comp-units. */ +static void +dw2_pre_expand_symtabs_matching (struct objfile *objfile, + int kind, const char *name, + domain_enum domain) +{ + dw2_do_expand_symtabs_matching (objfile, name); +} static void -build_type_psymtabs (struct objfile *objfile) +dw2_print_stats (struct objfile *objfile) { - if (! create_debug_types_hash_table (objfile)) - return; + int i, count; - htab_traverse_noresize (dwarf2_per_objfile->signatured_types, - process_type_comp_unit, objfile); + dw2_setup (objfile); + count = 0; + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) + { + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + + if (!per_cu->v.quick->symtab) + ++count; + } + printf_filtered (_(" Number of unread CUs: %d\n"), count); } -/* A cleanup function that clears objfile's psymtabs_addrmap field. */ +static void +dw2_dump (struct objfile *objfile) +{ + /* Nothing worth printing. */ +} static void -psymtabs_addrmap_cleanup (void *o) +dw2_relocate (struct objfile *objfile, struct section_offsets *new_offsets, + struct section_offsets *delta) { - struct objfile *objfile = o; + /* There's nothing to relocate here. */ +} - objfile->psymtabs_addrmap = NULL; +static void +dw2_expand_symtabs_for_function (struct objfile *objfile, + const char *func_name) +{ + dw2_do_expand_symtabs_matching (objfile, func_name); } -/* Build the partial symbol table by doing a quick pass through the - .debug_info and .debug_abbrev sections. */ +static void +dw2_expand_all_symtabs (struct objfile *objfile) +{ + int i; + + dw2_setup (objfile); + + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) + { + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + + dw2_instantiate_symtab (objfile, per_cu); + } +} static void -dwarf2_build_psymtabs_hard (struct objfile *objfile) +dw2_expand_symtabs_with_filename (struct objfile *objfile, + const char *filename) { - gdb_byte *info_ptr; - struct cleanup *back_to, *addrmap_cleanup; - struct obstack temp_obstack; + int i; - dwarf2_read_section (objfile, &dwarf2_per_objfile->info); - info_ptr = dwarf2_per_objfile->info.buffer; + dw2_setup (objfile); - /* Any cached compilation units will be linked by the per-objfile - read_in_chain. Make sure to free them when we're done. */ - back_to = make_cleanup (free_cached_comp_units, NULL); + /* We don't need to consider type units here. + This is only called for examining code, e.g. expand_line_sal. + There can be an order of magnitude (or more) more type units + than comp units, and we avoid them if we can. */ - build_type_psymtabs (objfile); + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { + int j; + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct quick_file_names *file_data; - create_all_comp_units (objfile); + if (per_cu->v.quick->symtab) + continue; - /* Create a temporary address map on a temporary obstack. We later - copy this to the final obstack. */ - obstack_init (&temp_obstack); - make_cleanup_obstack_free (&temp_obstack); - objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack); - addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile); + file_data = dw2_get_file_names (objfile, per_cu); + if (file_data == NULL) + continue; - /* Since the objects we're extracting from .debug_info vary in - length, only the individual functions to extract them (like - read_comp_unit_head and load_partial_die) can really know whether - the buffer is large enough to hold another complete object. + for (j = 0; j < file_data->num_file_names; ++j) + { + const char *this_name = file_data->file_names[j]; + if (FILENAME_CMP (this_name, filename) == 0) + { + dw2_instantiate_symtab (objfile, per_cu); + break; + } + } + } +} - At the moment, they don't actually check that. If .debug_info - holds just one extra byte after the last compilation unit's dies, - then read_comp_unit_head will happily read off the end of the - buffer. read_partial_die is similarly casual. Those functions - should be fixed. +static const char * +dw2_find_symbol_file (struct objfile *objfile, const char *name) +{ + struct dwarf2_per_cu_data *per_cu; + offset_type *vec; + struct quick_file_names *file_data; - For this loop condition, simply checking whether there's any data - left at all should be sufficient. */ + dw2_setup (objfile); - while (info_ptr < (dwarf2_per_objfile->info.buffer - + dwarf2_per_objfile->info.size)) - { - struct dwarf2_per_cu_data *this_cu; + /* index_table is NULL if OBJF_READNOW. */ + if (!dwarf2_per_objfile->index_table) + return NULL; - this_cu = dwarf2_find_comp_unit (info_ptr - dwarf2_per_objfile->info.buffer, - objfile); + if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, + name, &vec)) + return NULL; - info_ptr = process_psymtab_comp_unit (objfile, this_cu, - dwarf2_per_objfile->info.buffer, - info_ptr, - dwarf2_per_objfile->info.size); - } + /* Note that this just looks at the very first one named NAME -- but + actually we are looking for a function. find_main_filename + should be rewritten so that it doesn't require a custom hook. It + could just use the ordinary symbol tables. */ + /* vec[0] is the length, which must always be >0. */ + per_cu = dw2_get_cu (MAYBE_SWAP (vec[1])); - objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap, - &objfile->objfile_obstack); - discard_cleanups (addrmap_cleanup); + file_data = dw2_get_file_names (objfile, per_cu); + if (file_data == NULL) + return NULL; - do_cleanups (back_to); + return file_data->file_names[file_data->num_file_names - 1]; } -/* Load the partial DIEs for a secondary CU into memory. */ +static void +dw2_map_matching_symbols (const char * name, domain_enum namespace, + struct objfile *objfile, int global, + int (*callback) (struct block *, + struct symbol *, void *), + void *data, symbol_compare_ftype *match, + symbol_compare_ftype *ordered_compare) +{ + /* Currently unimplemented; used for Ada. The function can be called if the + current language is Ada for a non-Ada objfile using GNU index. As Ada + does not look for non-Ada symbols this function should just return. */ +} static void -load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, - struct objfile *objfile) +dw2_expand_symtabs_matching (struct objfile *objfile, + int (*file_matcher) (const char *, void *), + int (*name_matcher) (const char *, void *), + domain_enum kind, + void *data) { - bfd *abfd = objfile->obfd; - gdb_byte *info_ptr, *beg_of_comp_unit; - struct die_info *comp_unit_die; - struct dwarf2_cu *cu; - struct cleanup *back_to; - struct attribute *attr; - int has_children; - struct die_reader_specs reader_specs; + int i; + offset_type iter; + struct mapped_index *index; - gdb_assert (! this_cu->from_debug_types); + dw2_setup (objfile); - gdb_assert (dwarf2_per_objfile->info.readin); - info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; - beg_of_comp_unit = info_ptr; + /* index_table is NULL if OBJF_READNOW. */ + if (!dwarf2_per_objfile->index_table) + return; + index = dwarf2_per_objfile->index_table; - cu = alloc_one_comp_unit (objfile); + if (file_matcher != NULL) + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) + { + int j; + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct quick_file_names *file_data; - /* ??? Missing cleanup for CU? */ + per_cu->v.quick->mark = 0; + if (per_cu->v.quick->symtab) + continue; - /* Link this compilation unit into the compilation unit tree. */ - this_cu->cu = cu; - cu->per_cu = this_cu; - cu->type_hash = this_cu->type_hash; + file_data = dw2_get_file_names (objfile, per_cu); + if (file_data == NULL) + continue; - info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, - dwarf2_per_objfile->info.buffer, - dwarf2_per_objfile->info.size, - abfd); + for (j = 0; j < file_data->num_file_names; ++j) + { + if (file_matcher (file_data->file_names[j], data)) + { + per_cu->v.quick->mark = 1; + break; + } + } + } - /* Complete the cu_header. */ - cu->header.offset = this_cu->offset; - cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + for (iter = 0; iter < index->symbol_table_slots; ++iter) + { + offset_type idx = 2 * iter; + const char *name; + offset_type *vec, vec_len, vec_idx; - /* Read the abbrevs for this compilation unit into a table. */ - dwarf2_read_abbrevs (abfd, cu); - back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0) + continue; - /* Read the compilation unit die. */ - init_cu_die_reader (&reader_specs, cu); - info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, - &has_children); + name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]); - /* Set the language we're debugging. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_language, cu); - if (attr) - set_cu_language (DW_UNSND (attr), cu); - else - set_cu_language (language_minimal, cu); + if (! (*name_matcher) (name, data)) + continue; - /* Check if comp unit has_children. - If so, read the rest of the partial symbols from this comp unit. - If not, there's no more debug_info for this comp unit. */ - if (has_children) - load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu); + /* The name was matched, now expand corresponding CUs that were + marked. */ + vec = (offset_type *) (index->constant_pool + + MAYBE_SWAP (index->symbol_table[idx + 1])); + vec_len = MAYBE_SWAP (vec[0]); + for (vec_idx = 0; vec_idx < vec_len; ++vec_idx) + { + struct dwarf2_per_cu_data *per_cu; - do_cleanups (back_to); + per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1])); + if (file_matcher == NULL || per_cu->v.quick->mark) + dw2_instantiate_symtab (objfile, per_cu); + } + } } -/* Create a list of all compilation units in OBJFILE. We do this only - if an inter-comp-unit reference is found; presumably if there is one, - there will be many, and one will occur early in the .debug_info section. - So there's no point in building this list incrementally. */ - -static void -create_all_comp_units (struct objfile *objfile) +static struct symtab * +dw2_find_pc_sect_symtab (struct objfile *objfile, + struct minimal_symbol *msymbol, + CORE_ADDR pc, + struct obj_section *section, + int warn_if_readin) { - int n_allocated; - int n_comp_units; - struct dwarf2_per_cu_data **all_comp_units; - gdb_byte *info_ptr; - - dwarf2_read_section (objfile, &dwarf2_per_objfile->info); - info_ptr = dwarf2_per_objfile->info.buffer; - - n_comp_units = 0; - n_allocated = 10; - all_comp_units = xmalloc (n_allocated - * sizeof (struct dwarf2_per_cu_data *)); - - while (info_ptr < dwarf2_per_objfile->info.buffer + dwarf2_per_objfile->info.size) - { - unsigned int length, initial_length_size; - struct dwarf2_per_cu_data *this_cu; - unsigned int offset; - - offset = info_ptr - dwarf2_per_objfile->info.buffer; + struct dwarf2_per_cu_data *data; - /* Read just enough information to find out where the next - compilation unit is. */ - length = read_initial_length (objfile->obfd, info_ptr, - &initial_length_size); + dw2_setup (objfile); - /* Save the compilation unit for later lookup. */ - this_cu = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_per_cu_data)); - memset (this_cu, 0, sizeof (*this_cu)); - this_cu->offset = offset; - this_cu->length = length + initial_length_size; + if (!objfile->psymtabs_addrmap) + return NULL; - if (n_comp_units == n_allocated) - { - n_allocated *= 2; - all_comp_units = xrealloc (all_comp_units, - n_allocated - * sizeof (struct dwarf2_per_cu_data *)); - } - all_comp_units[n_comp_units++] = this_cu; + data = addrmap_find (objfile->psymtabs_addrmap, pc); + if (!data) + return NULL; - info_ptr = info_ptr + this_cu->length; - } + if (warn_if_readin && data->v.quick->symtab) + warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"), + paddress (get_objfile_arch (objfile), pc)); - dwarf2_per_objfile->all_comp_units - = obstack_alloc (&objfile->objfile_obstack, - n_comp_units * sizeof (struct dwarf2_per_cu_data *)); - memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units, - n_comp_units * sizeof (struct dwarf2_per_cu_data *)); - xfree (all_comp_units); - dwarf2_per_objfile->n_comp_units = n_comp_units; + return dw2_instantiate_symtab (objfile, data); } -/* Process all loaded DIEs for compilation unit CU, starting at - FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation - unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or - DW_AT_ranges). If NEED_PC is set, then this function will set - *LOWPC and *HIGHPC to the lowest and highest PC values found in CU - and record the covered ranges in the addrmap. */ - static void -scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, - CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu) +dw2_map_symbol_filenames (struct objfile *objfile, + void (*fun) (const char *, const char *, void *), + void *data) { - struct partial_die_info *pdi; - - /* Now, march along the PDI's, descending into ones which have - interesting children but skipping the children of the other ones, - until we reach the end of the compilation unit. */ + int i; - pdi = first_die; + dw2_setup (objfile); - while (pdi != NULL) + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) { - fixup_partial_die (pdi, cu); + int j; + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct quick_file_names *file_data; - /* Anonymous namespaces or modules have no name but have interesting - children, so we need to look at them. Ditto for anonymous - enums. */ + if (per_cu->v.quick->symtab) + continue; - if (pdi->name != NULL || pdi->tag == DW_TAG_namespace - || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type) + file_data = dw2_get_file_names (objfile, per_cu); + if (file_data == NULL) + continue; + + for (j = 0; j < file_data->num_file_names; ++j) { - switch (pdi->tag) - { - case DW_TAG_subprogram: - add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu); - break; - case DW_TAG_variable: - case DW_TAG_typedef: - case DW_TAG_union_type: - if (!pdi->is_declaration) - { - add_partial_symbol (pdi, cu); - } - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - if (!pdi->is_declaration) - { - add_partial_symbol (pdi, cu); - } - break; - case DW_TAG_enumeration_type: - if (!pdi->is_declaration) - add_partial_enumeration (pdi, cu); - break; - case DW_TAG_base_type: - case DW_TAG_subrange_type: - /* File scope base type definitions are added to the partial - symbol table. */ - add_partial_symbol (pdi, cu); - break; - case DW_TAG_namespace: - add_partial_namespace (pdi, lowpc, highpc, need_pc, cu); - break; - case DW_TAG_module: - add_partial_module (pdi, lowpc, highpc, need_pc, cu); - break; - default: - break; - } + const char *this_real_name = dw2_get_real_path (objfile, file_data, + j); + (*fun) (file_data->file_names[j], this_real_name, data); } - - /* If the die has a sibling, skip to the sibling. */ - - pdi = pdi->die_sibling; } } -/* Functions used to compute the fully scoped name of a partial DIE. +static int +dw2_has_symbols (struct objfile *objfile) +{ + return 1; +} - Normally, this is simple. For C++, the parent DIE's fully scoped - name is concatenated with "::" and the partial DIE's name. For - Java, the same thing occurs except that "." is used instead of "::". - Enumerators are an exception; they use the scope of their parent - enumeration type, i.e. the name of the enumeration type is not - prepended to the enumerator. +const struct quick_symbol_functions dwarf2_gdb_index_functions = +{ + dw2_has_symbols, + dw2_find_last_source_symtab, + dw2_forget_cached_source_info, + dw2_lookup_symtab, + dw2_lookup_symbol, + dw2_pre_expand_symtabs_matching, + dw2_print_stats, + dw2_dump, + dw2_relocate, + dw2_expand_symtabs_for_function, + dw2_expand_all_symtabs, + dw2_expand_symtabs_with_filename, + dw2_find_symbol_file, + dw2_map_matching_symbols, + dw2_expand_symtabs_matching, + dw2_find_pc_sect_symtab, + dw2_map_symbol_filenames +}; - There are two complexities. One is DW_AT_specification; in this - case "parent" means the parent of the target of the specification, - instead of the direct parent of the DIE. The other is compilers - which do not emit DW_TAG_namespace; in this case we try to guess - the fully qualified name of structure types from their members' - linkage names. This must be done using the DIE's children rather - than the children of any DW_AT_specification target. We only need - to do this for structures at the top level, i.e. if the target of - any DW_AT_specification (if any; otherwise the DIE itself) does not - have a parent. */ +/* Initialize for reading DWARF for this objfile. Return 0 if this + file will use psymtabs, or 1 if using the GNU index. */ -/* Compute the scope prefix associated with PDI's parent, in - compilation unit CU. The result will be allocated on CU's - comp_unit_obstack, or a copy of the already allocated PDI->NAME - field. NULL is returned if no prefix is necessary. */ -static char * -partial_die_parent_scope (struct partial_die_info *pdi, - struct dwarf2_cu *cu) +int +dwarf2_initialize_objfile (struct objfile *objfile) { - char *grandparent_scope; - struct partial_die_info *parent, *real_pdi; + /* If we're about to read full symbols, don't bother with the + indices. In this case we also don't care if some other debug + format is making psymtabs, because they are all about to be + expanded anyway. */ + if ((objfile->flags & OBJF_READNOW)) + { + int i; - /* We need to look at our parent DIE; if we have a DW_AT_specification, - then this means the parent of the specification DIE. */ + dwarf2_per_objfile->using_index = 1; + create_all_comp_units (objfile); + create_debug_types_hash_table (objfile); + dwarf2_per_objfile->quick_file_names_table = + create_quick_file_names_table (dwarf2_per_objfile->n_comp_units); - real_pdi = pdi; - while (real_pdi->has_specification) - real_pdi = find_partial_die (real_pdi->spec_offset, cu); + for (i = 0; i < (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_type_comp_units); ++i) + { + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); - parent = real_pdi->die_parent; - if (parent == NULL) - return NULL; + per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_per_cu_quick_data); + } - if (parent->scope_set) - return parent->scope; + /* Return 1 so that gdb sees the "quick" functions. However, + these functions will be no-ops because we will have expanded + all symtabs. */ + return 1; + } - fixup_partial_die (parent, cu); + if (dwarf2_read_index (objfile)) + return 1; - grandparent_scope = partial_die_parent_scope (parent, cu); + return 0; +} - /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus - DW_TAG_namespace DIEs with a name of "::" for the global namespace. - Work around this problem here. */ - if (cu->language == language_cplus - && parent->tag == DW_TAG_namespace - && strcmp (parent->name, "::") == 0 - && grandparent_scope == NULL) - { - parent->scope = NULL; - parent->scope_set = 1; - return NULL; - } + - if (parent->tag == DW_TAG_namespace - || parent->tag == DW_TAG_module - || parent->tag == DW_TAG_structure_type - || parent->tag == DW_TAG_class_type - || parent->tag == DW_TAG_interface_type - || parent->tag == DW_TAG_union_type - || parent->tag == DW_TAG_enumeration_type) - { - if (grandparent_scope == NULL) - parent->scope = parent->name; - else - parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope, - parent->name, 0, cu); - } - else if (parent->tag == DW_TAG_enumerator) - /* Enumerators should not get the name of the enumeration as a prefix. */ - parent->scope = grandparent_scope; - else +/* Build a partial symbol table. */ + +void +dwarf2_build_psymtabs (struct objfile *objfile) +{ + if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0) { - /* FIXME drow/2004-04-01: What should we be doing with - function-local names? For partial symbols, we should probably be - ignoring them. */ - complaint (&symfile_complaints, - _("unhandled containing DIE tag %d for DIE at %d"), - parent->tag, pdi->offset); - parent->scope = grandparent_scope; + init_psymbol_list (objfile, 1024); } - parent->scope_set = 1; - return parent->scope; + dwarf2_build_psymtabs_hard (objfile); } -/* Return the fully scoped name associated with PDI, from compilation unit - CU. The result will be allocated with malloc. */ -static char * -partial_die_full_name (struct partial_die_info *pdi, - struct dwarf2_cu *cu) +/* Return TRUE if OFFSET is within CU_HEADER. */ + +static inline int +offset_in_cu_p (const struct comp_unit_head *cu_header, unsigned int offset) { - char *parent_scope; + unsigned int bottom = cu_header->offset; + unsigned int top = (cu_header->offset + + cu_header->length + + cu_header->initial_length_size); - parent_scope = partial_die_parent_scope (pdi, cu); - if (parent_scope == NULL) - return NULL; - else - return typename_concat (NULL, parent_scope, pdi->name, 0, cu); + return (offset >= bottom && offset < top); } -static void -add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - CORE_ADDR addr = 0; - char *actual_name = NULL; - const struct partial_symbol *psym = NULL; - CORE_ADDR baseaddr; - int built_actual_name = 0; +/* Read in the comp unit header information from the debug_info at info_ptr. + NOTE: This leaves members offset, first_die_offset to be filled in + by the caller. */ - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); +static gdb_byte * +read_comp_unit_head (struct comp_unit_head *cu_header, + gdb_byte *info_ptr, bfd *abfd) +{ + int signed_addr; + unsigned int bytes_read; - actual_name = partial_die_full_name (pdi, cu); - if (actual_name) - built_actual_name = 1; + cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read); + cu_header->initial_length_size = bytes_read; + cu_header->offset_size = (bytes_read == 4) ? 4 : 8; + info_ptr += bytes_read; + cu_header->version = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header, + &bytes_read); + info_ptr += bytes_read; + cu_header->addr_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + signed_addr = bfd_get_sign_extend_vma (abfd); + if (signed_addr < 0) + internal_error (__FILE__, __LINE__, + _("read_comp_unit_head: dwarf from non elf file")); + cu_header->signed_addr_p = signed_addr; - if (actual_name == NULL) - actual_name = pdi->name; + return info_ptr; +} - switch (pdi->tag) - { - case DW_TAG_subprogram: - if (pdi->is_external || cu->language == language_ada) - { - /* brobecker/2007-12-26: Normally, only "external" DIEs are part - of the global scope. But in Ada, we want to be able to access - nested procedures globally. So all Ada subprograms are stored - in the global scope. */ - /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr, - mst_text, objfile); */ - psym = add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_BLOCK, - &objfile->global_psymbols, - 0, pdi->lowpc + baseaddr, - cu->language, objfile); - } - else - { - /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr, - mst_file_text, objfile); */ - psym = add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_BLOCK, - &objfile->static_psymbols, - 0, pdi->lowpc + baseaddr, - cu->language, objfile); - } - break; - case DW_TAG_variable: - if (pdi->is_external) - { - /* Global Variable. - Don't enter into the minimal symbol tables as there is - a minimal symbol table entry from the ELF symbols already. - Enter into partial symbol table if it has a location - descriptor or a type. - If the location descriptor is missing, new_symbol will create - a LOC_UNRESOLVED symbol, the address of the variable will then - be determined from the minimal symbol table whenever the variable - is referenced. - The address for the partial symbol table entry is not - used by GDB, but it comes in handy for debugging partial symbol - table building. */ +static gdb_byte * +partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, + gdb_byte *buffer, unsigned int buffer_size, + bfd *abfd) +{ + gdb_byte *beg_of_comp_unit = info_ptr; - if (pdi->locdesc) - addr = decode_locdesc (pdi->locdesc, cu); - if (pdi->locdesc || pdi->has_type) - psym = add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_STATIC, - &objfile->global_psymbols, - 0, addr + baseaddr, - cu->language, objfile); - } - else - { - /* Static Variable. Skip symbols without location descriptors. */ - if (pdi->locdesc == NULL) - { - if (built_actual_name) - xfree (actual_name); - return; - } - addr = decode_locdesc (pdi->locdesc, cu); - /*prim_record_minimal_symbol (actual_name, addr + baseaddr, - mst_file_data, objfile); */ - psym = add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_STATIC, - &objfile->static_psymbols, - 0, addr + baseaddr, - cu->language, objfile); - } - break; - case DW_TAG_typedef: - case DW_TAG_base_type: - case DW_TAG_subrange_type: - add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_TYPEDEF, - &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); - break; - case DW_TAG_namespace: - add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_TYPEDEF, - &objfile->global_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - /* Skip external references. The DWARF standard says in the section - about "Structure, Union, and Class Type Entries": "An incomplete - structure, union or class type is represented by a structure, - union or class entry that does not have a byte size attribute - and that has a DW_AT_declaration attribute." */ - if (!pdi->has_byte_size && pdi->is_declaration) - { - if (built_actual_name) - xfree (actual_name); - return; - } + info_ptr = read_comp_unit_head (header, info_ptr, abfd); - /* NOTE: carlton/2003-10-07: See comment in new_symbol about - static vs. global. */ - add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - STRUCT_DOMAIN, LOC_TYPEDEF, - (cu->language == language_cplus - || cu->language == language_java) - ? &objfile->global_psymbols - : &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + if (header->version != 2 && header->version != 3 && header->version != 4) + error (_("Dwarf Error: wrong version in compilation unit header " + "(is %d, should be 2, 3, or 4) [in module %s]"), header->version, + bfd_get_filename (abfd)); - break; - case DW_TAG_enumerator: - add_psymbol_to_list (actual_name, strlen (actual_name), - built_actual_name, - VAR_DOMAIN, LOC_CONST, - (cu->language == language_cplus - || cu->language == language_java) - ? &objfile->global_psymbols - : &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); - break; - default: - break; - } + if (header->abbrev_offset + >= dwarf2_section_size (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->abbrev)) + error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header " + "(offset 0x%lx + 6) [in module %s]"), + (long) header->abbrev_offset, + (long) (beg_of_comp_unit - buffer), + bfd_get_filename (abfd)); - if (built_actual_name) - xfree (actual_name); + if (beg_of_comp_unit + header->length + header->initial_length_size + > buffer + buffer_size) + error (_("Dwarf Error: bad length (0x%lx) in compilation unit header " + "(offset 0x%lx + 0) [in module %s]"), + (long) header->length, + (long) (beg_of_comp_unit - buffer), + bfd_get_filename (abfd)); + + return info_ptr; } -/* Read a partial die corresponding to a namespace; also, add a symbol - corresponding to that namespace to the symbol table. NAMESPACE is - the name of the enclosing namespace. */ +/* Read in the types comp unit header information from .debug_types entry at + types_ptr. The result is a pointer to one past the end of the header. */ -static void -add_partial_namespace (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int need_pc, struct dwarf2_cu *cu) +static gdb_byte * +read_type_comp_unit_head (struct comp_unit_head *cu_header, + ULONGEST *signature, + gdb_byte *types_ptr, bfd *abfd) { - /* Add a symbol for the namespace. */ + gdb_byte *initial_types_ptr = types_ptr; - add_partial_symbol (pdi, cu); + dwarf2_read_section (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->types); + cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer; - /* Now scan partial symbols in that namespace. */ + types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd); - if (pdi->has_children) - scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu); + *signature = read_8_bytes (abfd, types_ptr); + types_ptr += 8; + types_ptr += cu_header->offset_size; + cu_header->first_die_offset = types_ptr - initial_types_ptr; + + return types_ptr; } -/* Read a partial die corresponding to a Fortran module. */ +/* Allocate a new partial symtab for file named NAME and mark this new + partial symtab as being an include of PST. */ static void -add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, - CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu) +dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst, + struct objfile *objfile) { - /* Now scan partial symbols in that module. */ + struct partial_symtab *subpst = allocate_psymtab (name, objfile); - if (pdi->has_children) - scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu); -} + subpst->section_offsets = pst->section_offsets; + subpst->textlow = 0; + subpst->texthigh = 0; -/* Read a partial die corresponding to a subprogram and create a partial - symbol for that subprogram. When the CU language allows it, this - routine also defines a partial symbol for each nested subprogram - that this subprogram contains. + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->objfile_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; - DIE my also be a lexical block, in which case we simply search - recursively for suprograms defined inside that lexical block. - Again, this is only performed when the CU language allows this - type of definitions. */ + subpst->globals_offset = 0; + subpst->n_global_syms = 0; + subpst->statics_offset = 0; + subpst->n_static_syms = 0; + subpst->symtab = NULL; + subpst->read_symtab = pst->read_symtab; + subpst->readin = 0; + + /* No private part is necessary for include psymtabs. This property + can be used to differentiate between such include psymtabs and + the regular ones. */ + subpst->read_symtab_private = NULL; +} + +/* Read the Line Number Program data and extract the list of files + included by the source file represented by PST. Build an include + partial symtab for each of these included files. */ static void -add_partial_subprogram (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int need_pc, struct dwarf2_cu *cu) +dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, + struct die_info *die, + struct partial_symtab *pst) { - if (pdi->tag == DW_TAG_subprogram) + struct objfile *objfile = cu->objfile; + bfd *abfd = objfile->obfd; + struct line_header *lh = NULL; + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_stmt_list, cu); + if (attr) { - if (pdi->has_pc_info) - { - if (pdi->lowpc < *lowpc) - *lowpc = pdi->lowpc; - if (pdi->highpc > *highpc) - *highpc = pdi->highpc; - if (need_pc) - { - CORE_ADDR baseaddr; - struct objfile *objfile = cu->objfile; + unsigned int line_offset = DW_UNSND (attr); - baseaddr = ANOFFSET (objfile->section_offsets, - SECT_OFF_TEXT (objfile)); - addrmap_set_empty (objfile->psymtabs_addrmap, - pdi->lowpc + baseaddr, - pdi->highpc - 1 + baseaddr, - cu->per_cu->psymtab); - } - if (!pdi->is_declaration) - /* Ignore subprogram DIEs that do not have a name, they are - illegal. Do not emit a complaint at this point, we will - do so when we convert this psymtab into a symtab. */ - if (pdi->name) - add_partial_symbol (pdi, cu); - } + lh = dwarf_decode_line_header (line_offset, abfd, cu); } + if (lh == NULL) + return; /* No linetable, so no includes. */ - if (! pdi->has_children) - return; + /* NOTE: pst->dirname is DW_AT_comp_dir (if present). */ + dwarf_decode_lines (lh, pst->dirname, abfd, cu, pst); - if (cu->language == language_ada) - { - pdi = pdi->die_child; - while (pdi != NULL) - { - fixup_partial_die (pdi, cu); - if (pdi->tag == DW_TAG_subprogram - || pdi->tag == DW_TAG_lexical_block) - add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu); - pdi = pdi->die_sibling; - } - } + free_line_header (lh); } -/* See if we can figure out if the class lives in a namespace. We do - this by looking for a member function; its demangled name will - contain namespace info, if there is any. */ - -static void -guess_structure_name (struct partial_die_info *struct_pdi, - struct dwarf2_cu *cu) +static hashval_t +hash_type_signature (const void *item) { - if ((cu->language == language_cplus - || cu->language == language_java) - && cu->has_namespace_info == 0 - && struct_pdi->has_children) - { - /* NOTE: carlton/2003-10-07: Getting the info this way changes - what template types look like, because the demangler - frequently doesn't give the same name as the debug info. We - could fix this by only using the demangled name to get the - prefix (but see comment in read_structure_type). */ + const struct signatured_type *type_sig = item; - struct partial_die_info *real_pdi; + /* This drops the top 32 bits of the signature, but is ok for a hash. */ + return type_sig->signature; +} + +static int +eq_type_signature (const void *item_lhs, const void *item_rhs) +{ + const struct signatured_type *lhs = item_lhs; + const struct signatured_type *rhs = item_rhs; - /* If this DIE (this DIE's specification, if any) has a parent, then - we should not do this. We'll prepend the parent's fully qualified - name when we create the partial symbol. */ + return lhs->signature == rhs->signature; +} - real_pdi = struct_pdi; - while (real_pdi->has_specification) - real_pdi = find_partial_die (real_pdi->spec_offset, cu); +/* Allocate a hash table for signatured types. */ - if (real_pdi->die_parent != NULL) - return; - } +static htab_t +allocate_signatured_type_table (struct objfile *objfile) +{ + return htab_create_alloc_ex (41, + hash_type_signature, + eq_type_signature, + NULL, + &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); } -/* Read a partial die corresponding to an enumeration type. */ +/* A helper function to add a signatured type CU to a list. */ -static void -add_partial_enumeration (struct partial_die_info *enum_pdi, - struct dwarf2_cu *cu) +static int +add_signatured_type_cu_to_list (void **slot, void *datum) { - struct partial_die_info *pdi; + struct signatured_type *sigt = *slot; + struct dwarf2_per_cu_data ***datap = datum; - if (enum_pdi->name != NULL) - add_partial_symbol (enum_pdi, cu); + **datap = &sigt->per_cu; + ++*datap; - pdi = enum_pdi->die_child; - while (pdi) - { - if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL) - complaint (&symfile_complaints, _("malformed enumerator DIE ignored")); - else - add_partial_symbol (pdi, cu); - pdi = pdi->die_sibling; - } + return 1; } -/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU. - Return the corresponding abbrev, or NULL if the number is zero (indicating - an empty DIE). In either case *BYTES_READ will be set to the length of - the initial number. */ +/* Create the hash table of all entries in the .debug_types section. + The result is zero if there is an error (e.g. missing .debug_types section), + otherwise non-zero. */ -static struct abbrev_info * -peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read, - struct dwarf2_cu *cu) +static int +create_debug_types_hash_table (struct objfile *objfile) { - bfd *abfd = cu->objfile->obfd; - unsigned int abbrev_number; - struct abbrev_info *abbrev; + gdb_byte *info_ptr; + htab_t types_htab; + struct dwarf2_per_cu_data **iter; - abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read); + dwarf2_read_section (objfile, &dwarf2_per_objfile->types); + info_ptr = dwarf2_per_objfile->types.buffer; - if (abbrev_number == 0) - return NULL; + if (info_ptr == NULL) + { + dwarf2_per_objfile->signatured_types = NULL; + return 0; + } - abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); - if (!abbrev) + types_htab = allocate_signatured_type_table (objfile); + + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); + + while (info_ptr < dwarf2_per_objfile->types.buffer + + dwarf2_per_objfile->types.size) { - error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"), abbrev_number, - bfd_get_filename (abfd)); + unsigned int offset; + unsigned int offset_size; + unsigned int type_offset; + unsigned int length, initial_length_size; + unsigned short version; + ULONGEST signature; + struct signatured_type *type_sig; + void **slot; + gdb_byte *ptr = info_ptr; + + offset = ptr - dwarf2_per_objfile->types.buffer; + + /* We need to read the type's signature in order to build the hash + table, but we don't need to read anything else just yet. */ + + /* Sanity check to ensure entire cu is present. */ + length = read_initial_length (objfile->obfd, ptr, &initial_length_size); + if (ptr + length + initial_length_size + > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) + { + complaint (&symfile_complaints, + _("debug type entry runs off end " + "of `.debug_types' section, ignored")); + break; + } + + offset_size = initial_length_size == 4 ? 4 : 8; + ptr += initial_length_size; + version = bfd_get_16 (objfile->obfd, ptr); + ptr += 2; + ptr += offset_size; /* abbrev offset */ + ptr += 1; /* address size */ + signature = bfd_get_64 (objfile->obfd, ptr); + ptr += 8; + type_offset = read_offset_1 (objfile->obfd, ptr, offset_size); + + type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig)); + memset (type_sig, 0, sizeof (*type_sig)); + type_sig->signature = signature; + type_sig->offset = offset; + type_sig->type_offset = type_offset; + type_sig->per_cu.objfile = objfile; + type_sig->per_cu.from_debug_types = 1; + + slot = htab_find_slot (types_htab, type_sig, INSERT); + gdb_assert (slot != NULL); + *slot = type_sig; + + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n", + offset, phex (signature, sizeof (signature))); + + info_ptr = info_ptr + initial_length_size + length; } - return abbrev; + dwarf2_per_objfile->signatured_types = types_htab; + + dwarf2_per_objfile->n_type_comp_units = htab_elements (types_htab); + dwarf2_per_objfile->type_comp_units + = obstack_alloc (&objfile->objfile_obstack, + dwarf2_per_objfile->n_type_comp_units + * sizeof (struct dwarf2_per_cu_data *)); + iter = &dwarf2_per_objfile->type_comp_units[0]; + htab_traverse_noresize (types_htab, add_signatured_type_cu_to_list, &iter); + gdb_assert (iter - &dwarf2_per_objfile->type_comp_units[0] + == dwarf2_per_objfile->n_type_comp_units); + + return 1; } -/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. - Returns a pointer to the end of a series of DIEs, terminated by an empty - DIE. Any children of the skipped DIEs will also be skipped. */ +/* Lookup a signature based type. + Returns NULL if SIG is not present in the table. */ -static gdb_byte * -skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu) +static struct signatured_type * +lookup_signatured_type (struct objfile *objfile, ULONGEST sig) { - struct abbrev_info *abbrev; - unsigned int bytes_read; + struct signatured_type find_entry, *entry; - while (1) + if (dwarf2_per_objfile->signatured_types == NULL) { - abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); - if (abbrev == NULL) - return info_ptr + bytes_read; - else - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); + complaint (&symfile_complaints, + _("missing `.debug_types' section for DW_FORM_ref_sig8 die")); + return 0; + } + + find_entry.signature = sig; + entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + return entry; +} + +/* Initialize a die_reader_specs struct from a dwarf2_cu struct. */ + +static void +init_cu_die_reader (struct die_reader_specs *reader, + struct dwarf2_cu *cu) +{ + reader->abfd = cu->objfile->obfd; + reader->cu = cu; + if (cu->per_cu->from_debug_types) + { + gdb_assert (dwarf2_per_objfile->types.readin); + reader->buffer = dwarf2_per_objfile->types.buffer; + } + else + { + gdb_assert (dwarf2_per_objfile->info.readin); + reader->buffer = dwarf2_per_objfile->info.buffer; } } -/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. - INFO_PTR should point just after the initial uleb128 of a DIE, and the - abbrev corresponding to that skipped uleb128 should be passed in - ABBREV. Returns a pointer to this DIE's sibling, skipping any - children. */ +/* Find the base address of the compilation unit for range lists and + location lists. It will normally be specified by DW_AT_low_pc. + In DWARF-3 draft 4, the base address could be overridden by + DW_AT_entry_pc. It's been removed, but GCC still uses this for + compilation units with discontinuous ranges. */ -static gdb_byte * -skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr, - struct abbrev_info *abbrev, struct dwarf2_cu *cu) +static void +dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu) { - unsigned int bytes_read; - struct attribute attr; - bfd *abfd = cu->objfile->obfd; - unsigned int form, i; + struct attribute *attr; - for (i = 0; i < abbrev->num_attrs; i++) + cu->base_known = 0; + cu->base_address = 0; + + attr = dwarf2_attr (die, DW_AT_entry_pc, cu); + if (attr) { - /* The only abbrev we care about is DW_AT_sibling. */ - if (abbrev->attrs[i].name == DW_AT_sibling) + cu->base_address = DW_ADDR (attr); + cu->base_known = 1; + } + else + { + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + if (attr) { - read_attribute (&attr, &abbrev->attrs[i], - abfd, info_ptr, cu); - if (attr.form == DW_FORM_ref_addr) - complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); - else - return buffer + dwarf2_get_ref_die_offset (&attr); - } - - /* If it isn't DW_AT_sibling, skip this attribute. */ - form = abbrev->attrs[i].form; - skip_attribute: - switch (form) - { - case DW_FORM_ref_addr: - /* In DWARF 2, DW_FORM_ref_addr is address sized; in DWARF 3 - and later it is offset sized. */ - if (cu->header.version == 2) - info_ptr += cu->header.addr_size; - else - info_ptr += cu->header.offset_size; - break; - case DW_FORM_addr: - info_ptr += cu->header.addr_size; - break; - case DW_FORM_data1: - case DW_FORM_ref1: - case DW_FORM_flag: - info_ptr += 1; - break; - case DW_FORM_flag_present: - break; - case DW_FORM_data2: - case DW_FORM_ref2: - info_ptr += 2; - break; - case DW_FORM_data4: - case DW_FORM_ref4: - info_ptr += 4; - break; - case DW_FORM_data8: - case DW_FORM_ref8: - case DW_FORM_sig8: - info_ptr += 8; - break; - case DW_FORM_string: - read_string (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_sec_offset: - case DW_FORM_strp: - info_ptr += cu->header.offset_size; - break; - case DW_FORM_exprloc: - case DW_FORM_block: - info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_block1: - info_ptr += 1 + read_1_byte (abfd, info_ptr); - break; - case DW_FORM_block2: - info_ptr += 2 + read_2_bytes (abfd, info_ptr); - break; - case DW_FORM_block4: - info_ptr += 4 + read_4_bytes (abfd, info_ptr); - break; - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - info_ptr = skip_leb128 (abfd, info_ptr); - break; - case DW_FORM_indirect: - form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - /* We need to continue parsing from here, so just go back to - the top. */ - goto skip_attribute; - - default: - error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"), - dwarf_form_name (form), - bfd_get_filename (abfd)); + cu->base_address = DW_ADDR (attr); + cu->base_known = 1; } } - - if (abbrev->has_children) - return skip_children (buffer, info_ptr, cu); - else - return info_ptr; } -/* Locate ORIG_PDI's sibling. - INFO_PTR should point to the start of the next DIE after ORIG_PDI - in BUFFER. */ +/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard + to combine the common parts. + Process a compilation unit for a psymtab. + BUFFER is a pointer to the beginning of the dwarf section buffer, + either .debug_info or debug_types. + INFO_PTR is a pointer to the start of the CU. + Returns a pointer to the next CU. */ static gdb_byte * -locate_pdi_sibling (struct partial_die_info *orig_pdi, - gdb_byte *buffer, gdb_byte *info_ptr, - bfd *abfd, struct dwarf2_cu *cu) +process_psymtab_comp_unit (struct objfile *objfile, + struct dwarf2_per_cu_data *this_cu, + gdb_byte *buffer, gdb_byte *info_ptr, + unsigned int buffer_size) { - /* Do we know the sibling already? */ - - if (orig_pdi->sibling) - return orig_pdi->sibling; - - /* Are there any children to deal with? */ - - if (!orig_pdi->has_children) - return info_ptr; + bfd *abfd = objfile->obfd; + gdb_byte *beg_of_comp_unit = info_ptr; + struct die_info *comp_unit_die; + struct partial_symtab *pst; + CORE_ADDR baseaddr; + struct cleanup *back_to_inner; + struct dwarf2_cu cu; + int has_children, has_pc_info; + struct attribute *attr; + CORE_ADDR best_lowpc = 0, best_highpc = 0; + struct die_reader_specs reader_specs; + const char *filename; - /* Skip the children the long way. */ + init_one_comp_unit (&cu, objfile); + back_to_inner = make_cleanup (free_stack_comp_unit, &cu); - return skip_children (buffer, info_ptr, cu); -} + info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, + buffer, buffer_size, + abfd); -/* Expand this partial symbol table into a full symbol table. */ + /* Complete the cu_header. */ + cu.header.offset = beg_of_comp_unit - buffer; + cu.header.first_die_offset = info_ptr - beg_of_comp_unit; -static void -dwarf2_psymtab_to_symtab (struct partial_symtab *pst) -{ - /* FIXME: This is barely more than a stub. */ - if (pst != NULL) - { - if (pst->readin) - { - warning (_("bug: psymtab for %s is already read in."), pst->filename); - } - else - { - if (info_verbose) - { - printf_filtered (_("Reading in symbols for %s..."), pst->filename); - gdb_flush (gdb_stdout); - } + cu.list_in_scope = &file_symbols; - /* Restore our global data. */ - dwarf2_per_objfile = objfile_data (pst->objfile, - dwarf2_objfile_data_key); + /* If this compilation unit was already read in, free the + cached copy in order to read it in again. This is + necessary because we skipped some symbols when we first + read in the compilation unit (see load_partial_dies). + This problem could be avoided, but the benefit is + unclear. */ + if (this_cu->cu != NULL) + free_one_cached_comp_unit (this_cu->cu); - /* If this psymtab is constructed from a debug-only objfile, the - has_section_at_zero flag will not necessarily be correct. We - can get the correct value for this flag by looking at the data - associated with the (presumably stripped) associated objfile. */ - if (pst->objfile->separate_debug_objfile_backlink) - { - struct dwarf2_per_objfile *dpo_backlink - = objfile_data (pst->objfile->separate_debug_objfile_backlink, - dwarf2_objfile_data_key); + /* Note that this is a pointer to our stack frame, being + added to a global data structure. It will be cleaned up + in free_stack_comp_unit when we finish with this + compilation unit. */ + this_cu->cu = &cu; + cu.per_cu = this_cu; - dwarf2_per_objfile->has_section_at_zero - = dpo_backlink->has_section_at_zero; - } + /* Read the abbrevs for this compilation unit into a table. */ + dwarf2_read_abbrevs (abfd, &cu); + make_cleanup (dwarf2_free_abbrev_table, &cu); - psymtab_to_symtab_1 (pst); + /* Read the compilation unit die. */ + if (this_cu->from_debug_types) + info_ptr += 8 /*signature*/ + cu.header.offset_size; + init_cu_die_reader (&reader_specs, &cu); + info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, + &has_children); - /* Finish up the debug error message. */ - if (info_verbose) - printf_filtered (_("done.\n")); - } + if (this_cu->from_debug_types) + { + /* offset,length haven't been set yet for type units. */ + this_cu->offset = cu.header.offset; + this_cu->length = cu.header.length + cu.header.initial_length_size; + } + else if (comp_unit_die->tag == DW_TAG_partial_unit) + { + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); + do_cleanups (back_to_inner); + return info_ptr; } -} - -/* Add PER_CU to the queue. */ - -static void -queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) -{ - struct dwarf2_queue_item *item; - per_cu->queued = 1; - item = xmalloc (sizeof (*item)); - item->per_cu = per_cu; - item->next = NULL; + prepare_one_comp_unit (&cu, comp_unit_die); - if (dwarf2_queue == NULL) - dwarf2_queue = item; + /* Allocate a new partial symbol table structure. */ + attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu); + if (attr == NULL || !DW_STRING (attr)) + filename = ""; else - dwarf2_queue_tail->next = item; + filename = DW_STRING (attr); + pst = start_psymtab_common (objfile, objfile->section_offsets, + filename, + /* TEXTLOW and TEXTHIGH are set below. */ + 0, + objfile->global_psymbols.next, + objfile->static_psymbols.next); - dwarf2_queue_tail = item; -} + attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu); + if (attr != NULL) + pst->dirname = DW_STRING (attr); -/* Process the queue. */ + pst->read_symtab_private = this_cu; -static void -process_queue (struct objfile *objfile) -{ - struct dwarf2_queue_item *item, *next_item; + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - /* The queue starts out with one item, but following a DIE reference - may load a new CU, adding it to the end of the queue. */ - for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item) - { - if (item->per_cu->psymtab && !item->per_cu->psymtab->readin) - process_full_comp_unit (item->per_cu); + /* Store the function that reads in the rest of the symbol table. */ + pst->read_symtab = dwarf2_psymtab_to_symtab; - item->per_cu->queued = 0; - next_item = item->next; - xfree (item); - } + this_cu->v.psymtab = pst; - dwarf2_queue_tail = NULL; -} + dwarf2_find_base_address (comp_unit_die, &cu); -/* Free all allocated queue entries. This function only releases anything if - an error was thrown; if the queue was processed then it would have been - freed as we went along. */ + /* Possibly set the default values of LOWPC and HIGHPC from + `DW_AT_ranges'. */ + has_pc_info = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, + &best_highpc, &cu, pst); + if (has_pc_info == 1 && best_lowpc < best_highpc) + /* Store the contiguous range if it is not empty; it can be empty for + CUs with no code. */ + addrmap_set_empty (objfile->psymtabs_addrmap, + best_lowpc + baseaddr, + best_highpc + baseaddr - 1, pst); -static void -dwarf2_release_queue (void *dummy) -{ - struct dwarf2_queue_item *item, *last; - - item = dwarf2_queue; - while (item) + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ + if (has_children) { - /* Anything still marked queued is likely to be in an - inconsistent state, so discard it. */ - if (item->per_cu->queued) + struct partial_die_info *first_die; + CORE_ADDR lowpc, highpc; + + lowpc = ((CORE_ADDR) -1); + highpc = ((CORE_ADDR) 0); + + first_die = load_partial_dies (abfd, buffer, info_ptr, 1, &cu); + + scan_partial_symbols (first_die, &lowpc, &highpc, + ! has_pc_info, &cu); + + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + + /* If the compilation unit didn't have an explicit address range, + then use the information extracted from its child dies. */ + if (! has_pc_info) { - if (item->per_cu->cu != NULL) - free_one_cached_comp_unit (item->per_cu->cu); - item->per_cu->queued = 0; + best_lowpc = lowpc; + best_highpc = highpc; } + } + pst->textlow = best_lowpc + baseaddr; + pst->texthigh = best_highpc + baseaddr; - last = item; - item = item->next; - xfree (last); + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = objfile->static_psymbols.next - + (objfile->static_psymbols.list + pst->statics_offset); + sort_pst_symbols (pst); + + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); + + if (this_cu->from_debug_types) + { + /* It's not clear we want to do anything with stmt lists here. + Waiting to see what gcc ultimately does. */ + } + else + { + /* Get the list of files included in the current compilation unit, + and build a psymtab for each of them. */ + dwarf2_build_include_psymtabs (&cu, comp_unit_die, pst); } - dwarf2_queue = dwarf2_queue_tail = NULL; + do_cleanups (back_to_inner); + + return info_ptr; } -/* Read in full symbols for PST, and anything it depends on. */ +/* Traversal function for htab_traverse_noresize. + Process one .debug_types comp-unit. */ -static void -psymtab_to_symtab_1 (struct partial_symtab *pst) +static int +process_type_comp_unit (void **slot, void *info) { - struct dwarf2_per_cu_data *per_cu; - struct cleanup *back_to; - int i; + struct signatured_type *entry = (struct signatured_type *) *slot; + struct objfile *objfile = (struct objfile *) info; + struct dwarf2_per_cu_data *this_cu; - for (i = 0; i < pst->number_of_dependencies; i++) - if (!pst->dependencies[i]->readin) - { - /* Inform about additional files that need to be read in. */ - if (info_verbose) - { - /* FIXME: i18n: Need to make this a single string. */ - fputs_filtered (" ", gdb_stdout); - wrap_here (""); - fputs_filtered ("and ", gdb_stdout); - wrap_here (""); - printf_filtered ("%s...", pst->dependencies[i]->filename); - wrap_here (""); /* Flush output */ - gdb_flush (gdb_stdout); - } - psymtab_to_symtab_1 (pst->dependencies[i]); - } + this_cu = &entry->per_cu; - per_cu = pst->read_symtab_private; + gdb_assert (dwarf2_per_objfile->types.readin); + process_psymtab_comp_unit (objfile, this_cu, + dwarf2_per_objfile->types.buffer, + dwarf2_per_objfile->types.buffer + entry->offset, + dwarf2_per_objfile->types.size); - if (per_cu == NULL) - { - /* It's an include file, no symbols to read for it. - Everything is in the parent symtab. */ - pst->readin = 1; - return; - } + return 1; +} - back_to = make_cleanup (dwarf2_release_queue, NULL); +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. + Build partial symbol tables for the .debug_types comp-units. */ - queue_comp_unit (per_cu, pst->objfile); +static void +build_type_psymtabs (struct objfile *objfile) +{ + if (! create_debug_types_hash_table (objfile)) + return; - if (per_cu->from_debug_types) - read_signatured_type_at_offset (pst->objfile, per_cu->offset); - else - load_full_comp_unit (per_cu, pst->objfile); + htab_traverse_noresize (dwarf2_per_objfile->signatured_types, + process_type_comp_unit, objfile); +} - process_queue (pst->objfile); +/* A cleanup function that clears objfile's psymtabs_addrmap field. */ - /* Age the cache, releasing compilation units that have not - been used recently. */ - age_cached_comp_units (); +static void +psymtabs_addrmap_cleanup (void *o) +{ + struct objfile *objfile = o; - do_cleanups (back_to); + objfile->psymtabs_addrmap = NULL; } -/* Load the DIEs associated with PER_CU into memory. */ +/* Build the partial symbol table by doing a quick pass through the + .debug_info and .debug_abbrev sections. */ static void -load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) +dwarf2_build_psymtabs_hard (struct objfile *objfile) { - bfd *abfd = objfile->obfd; - struct dwarf2_cu *cu; - unsigned int offset; - gdb_byte *info_ptr, *beg_of_comp_unit; - struct cleanup *back_to, *free_cu_cleanup; - struct attribute *attr; - - gdb_assert (! per_cu->from_debug_types); + gdb_byte *info_ptr; + struct cleanup *back_to, *addrmap_cleanup; + struct obstack temp_obstack; - /* Set local variables from the partial symbol table info. */ - offset = per_cu->offset; + dwarf2_per_objfile->reading_partial_symbols = 1; dwarf2_read_section (objfile, &dwarf2_per_objfile->info); - info_ptr = dwarf2_per_objfile->info.buffer + offset; - beg_of_comp_unit = info_ptr; + info_ptr = dwarf2_per_objfile->info.buffer; - cu = alloc_one_comp_unit (objfile); + /* Any cached compilation units will be linked by the per-objfile + read_in_chain. Make sure to free them when we're done. */ + back_to = make_cleanup (free_cached_comp_units, NULL); - /* If an error occurs while loading, release our storage. */ - free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); + build_type_psymtabs (objfile); - /* Read in the comp_unit header. */ - info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd); + create_all_comp_units (objfile); - /* Complete the cu_header. */ - cu->header.offset = offset; - cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + /* Create a temporary address map on a temporary obstack. We later + copy this to the final obstack. */ + obstack_init (&temp_obstack); + make_cleanup_obstack_free (&temp_obstack); + objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack); + addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile); - /* Read the abbrevs for this compilation unit. */ - dwarf2_read_abbrevs (abfd, cu); - back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + /* Since the objects we're extracting from .debug_info vary in + length, only the individual functions to extract them (like + read_comp_unit_head and load_partial_die) can really know whether + the buffer is large enough to hold another complete object. - /* Link this compilation unit into the compilation unit tree. */ - per_cu->cu = cu; - cu->per_cu = per_cu; - cu->type_hash = per_cu->type_hash; + At the moment, they don't actually check that. If .debug_info + holds just one extra byte after the last compilation unit's dies, + then read_comp_unit_head will happily read off the end of the + buffer. read_partial_die is similarly casual. Those functions + should be fixed. - cu->dies = read_comp_unit (info_ptr, cu); + For this loop condition, simply checking whether there's any data + left at all should be sufficient. */ - /* We try not to read any attributes in this function, because not - all objfiles needed for references have been loaded yet, and symbol - table processing isn't initialized. But we have to set the CU language, - or we won't be able to build types correctly. */ - attr = dwarf2_attr (cu->dies, DW_AT_language, cu); - if (attr) - set_cu_language (DW_UNSND (attr), cu); - else - set_cu_language (language_minimal, cu); + while (info_ptr < (dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size)) + { + struct dwarf2_per_cu_data *this_cu; - /* Similarly, if we do not read the producer, we can not apply - producer-specific interpretation. */ - attr = dwarf2_attr (cu->dies, DW_AT_producer, cu); - if (attr) - cu->producer = DW_STRING (attr); + this_cu = dwarf2_find_comp_unit (info_ptr + - dwarf2_per_objfile->info.buffer, + objfile); - /* Link this CU into read_in_chain. */ - per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; - dwarf2_per_objfile->read_in_chain = per_cu; + info_ptr = process_psymtab_comp_unit (objfile, this_cu, + dwarf2_per_objfile->info.buffer, + info_ptr, + dwarf2_per_objfile->info.size); + } - do_cleanups (back_to); + objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap, + &objfile->objfile_obstack); + discard_cleanups (addrmap_cleanup); - /* We've successfully allocated this compilation unit. Let our caller - clean it up when finished with it. */ - discard_cleanups (free_cu_cleanup); + do_cleanups (back_to); } -/* Generate full symbol information for PST and CU, whose DIEs have - already been loaded into memory. */ +/* Load the partial DIEs for a secondary CU into memory. */ static void -process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) +load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, + struct objfile *objfile) { - struct partial_symtab *pst = per_cu->psymtab; - struct dwarf2_cu *cu = per_cu->cu; - struct objfile *objfile = pst->objfile; - CORE_ADDR lowpc, highpc; - struct symtab *symtab; - struct cleanup *back_to; - CORE_ADDR baseaddr; + bfd *abfd = objfile->obfd; + gdb_byte *info_ptr, *beg_of_comp_unit; + struct die_info *comp_unit_die; + struct dwarf2_cu *cu; + struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup = NULL; + int has_children; + struct die_reader_specs reader_specs; + int read_cu = 0; - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + gdb_assert (! this_cu->from_debug_types); - buildsym_init (); - back_to = make_cleanup (really_free_pendings, NULL); + gdb_assert (dwarf2_per_objfile->info.readin); + info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; + beg_of_comp_unit = info_ptr; - cu->list_in_scope = &file_symbols; + if (this_cu->cu == NULL) + { + cu = xmalloc (sizeof (*cu)); + init_one_comp_unit (cu, objfile); - dwarf2_find_base_address (cu->dies, cu); + read_cu = 1; - /* Do line number decoding in read_file_scope () */ - process_die (cu->dies, cu); + /* If an error occurs while loading, release our storage. */ + free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); - /* Some compilers don't define a DW_AT_high_pc attribute for the - compilation unit. If the DW_AT_high_pc is missing, synthesize - it, by scanning the DIE's below the compilation unit. */ - get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu); + info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, + dwarf2_per_objfile->info.buffer, + dwarf2_per_objfile->info.size, + abfd); - symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile)); + /* Complete the cu_header. */ + cu->header.offset = this_cu->offset; + cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + + /* Link this compilation unit into the compilation unit tree. */ + this_cu->cu = cu; + cu->per_cu = this_cu; - /* Set symtab language to language from DW_AT_language. - If the compilation is from a C file generated by language preprocessors, - do not set the language if it was already deduced by start_subfile. */ - if (symtab != NULL - && !(cu->language == language_c && symtab->language != language_c)) + /* Link this CU into read_in_chain. */ + this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; + dwarf2_per_objfile->read_in_chain = this_cu; + } + else { - symtab->language = cu->language; + cu = this_cu->cu; + info_ptr += cu->header.first_die_offset; } - pst->symtab = symtab; - pst->readin = 1; - do_cleanups (back_to); -} - -/* Process a die and its children. */ + /* Read the abbrevs for this compilation unit into a table. */ + gdb_assert (cu->dwarf2_abbrevs == NULL); + dwarf2_read_abbrevs (abfd, cu); + free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu); -static void -process_die (struct die_info *die, struct dwarf2_cu *cu) -{ - switch (die->tag) - { - case DW_TAG_padding: - break; - case DW_TAG_compile_unit: - read_file_scope (die, cu); - break; - case DW_TAG_type_unit: - read_type_unit_scope (die, cu); - break; - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: - read_func_scope (die, cu); - break; - case DW_TAG_lexical_block: - case DW_TAG_try_block: - case DW_TAG_catch_block: - read_lexical_block_scope (die, cu); - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - process_structure_scope (die, cu); - break; - case DW_TAG_enumeration_type: - process_enumeration_scope (die, cu); - break; + /* Read the compilation unit die. */ + init_cu_die_reader (&reader_specs, cu); + info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, + &has_children); - /* These dies have a type, but processing them does not create - a symbol or recurse to process the children. Therefore we can - read them on-demand through read_type_die. */ - case DW_TAG_subroutine_type: - case DW_TAG_set_type: - case DW_TAG_array_type: - case DW_TAG_pointer_type: - case DW_TAG_ptr_to_member_type: - case DW_TAG_reference_type: - case DW_TAG_string_type: - break; + prepare_one_comp_unit (cu, comp_unit_die); - case DW_TAG_base_type: - case DW_TAG_subrange_type: - case DW_TAG_typedef: - /* Add a typedef symbol for the type definition, if it has a - DW_AT_name. */ - new_symbol (die, read_type_die (die, cu), cu); - break; - case DW_TAG_common_block: - read_common_block (die, cu); - break; - case DW_TAG_common_inclusion: - break; - case DW_TAG_namespace: - processing_has_namespace_info = 1; - read_namespace (die, cu); - break; - case DW_TAG_module: - processing_has_namespace_info = 1; - read_module (die, cu); - break; - case DW_TAG_imported_declaration: - case DW_TAG_imported_module: - processing_has_namespace_info = 1; - if (die->child != NULL && (die->tag == DW_TAG_imported_declaration - || cu->language != language_fortran)) - complaint (&symfile_complaints, _("Tag '%s' has unexpected children"), - dwarf_tag_name (die->tag)); - read_import_statement (die, cu); - break; - default: - new_symbol (die, NULL, cu); - break; + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ + if (has_children) + load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu); + + do_cleanups (free_abbrevs_cleanup); + + if (read_cu) + { + /* We've successfully allocated this compilation unit. Let our + caller clean it up when finished with it. */ + discard_cleanups (free_cu_cleanup); } } -/* A helper function for dwarf2_compute_name which determines whether DIE - needs to have the name of the scope prepended to the name listed in the - die. */ +/* Create a list of all compilation units in OBJFILE. We do this only + if an inter-comp-unit reference is found; presumably if there is one, + there will be many, and one will occur early in the .debug_info section. + So there's no point in building this list incrementally. */ -static int -die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu) +static void +create_all_comp_units (struct objfile *objfile) { - struct attribute *attr; + int n_allocated; + int n_comp_units; + struct dwarf2_per_cu_data **all_comp_units; + gdb_byte *info_ptr; - switch (die->tag) + dwarf2_read_section (objfile, &dwarf2_per_objfile->info); + info_ptr = dwarf2_per_objfile->info.buffer; + + n_comp_units = 0; + n_allocated = 10; + all_comp_units = xmalloc (n_allocated + * sizeof (struct dwarf2_per_cu_data *)); + + while (info_ptr < dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size) { - case DW_TAG_namespace: - case DW_TAG_typedef: - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - case DW_TAG_enumerator: - case DW_TAG_subprogram: - case DW_TAG_member: - return 1; + unsigned int length, initial_length_size; + struct dwarf2_per_cu_data *this_cu; + unsigned int offset; - case DW_TAG_variable: - /* We only need to prefix "globally" visible variables. These include - any variable marked with DW_AT_external or any variable that - lives in a namespace. [Variables in anonymous namespaces - require prefixing, but they are not DW_AT_external.] */ + offset = info_ptr - dwarf2_per_objfile->info.buffer; - if (dwarf2_attr (die, DW_AT_specification, cu)) - { - struct dwarf2_cu *spec_cu = cu; + /* Read just enough information to find out where the next + compilation unit is. */ + length = read_initial_length (objfile->obfd, info_ptr, + &initial_length_size); - return die_needs_namespace (die_specification (die, &spec_cu), - spec_cu); - } + /* Save the compilation unit for later lookup. */ + this_cu = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct dwarf2_per_cu_data)); + memset (this_cu, 0, sizeof (*this_cu)); + this_cu->offset = offset; + this_cu->length = length + initial_length_size; + this_cu->objfile = objfile; - attr = dwarf2_attr (die, DW_AT_external, cu); - if (attr == NULL && die->parent->tag != DW_TAG_namespace - && die->parent->tag != DW_TAG_module) - return 0; - /* A variable in a lexical block of some kind does not need a - namespace, even though in C++ such variables may be external - and have a mangled name. */ - if (die->parent->tag == DW_TAG_lexical_block - || die->parent->tag == DW_TAG_try_block - || die->parent->tag == DW_TAG_catch_block - || die->parent->tag == DW_TAG_subprogram) - return 0; - return 1; + if (n_comp_units == n_allocated) + { + n_allocated *= 2; + all_comp_units = xrealloc (all_comp_units, + n_allocated + * sizeof (struct dwarf2_per_cu_data *)); + } + all_comp_units[n_comp_units++] = this_cu; - default: - return 0; + info_ptr = info_ptr + this_cu->length; } -} - -/* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero, - compute the physname for the object, which include a method's - formal parameters (C++/Java) and return type (Java). - For Ada, return the DIE's linkage name rather than the fully qualified - name. PHYSNAME is ignored.. + dwarf2_per_objfile->all_comp_units + = obstack_alloc (&objfile->objfile_obstack, + n_comp_units * sizeof (struct dwarf2_per_cu_data *)); + memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units, + n_comp_units * sizeof (struct dwarf2_per_cu_data *)); + xfree (all_comp_units); + dwarf2_per_objfile->n_comp_units = n_comp_units; +} - The result is allocated on the objfile_obstack and canonicalized. */ +/* Process all loaded DIEs for compilation unit CU, starting at + FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation + unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or + DW_AT_ranges). If NEED_PC is set, then this function will set + *LOWPC and *HIGHPC to the lowest and highest PC values found in CU + and record the covered ranges in the addrmap. */ -static const char * -dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu, - int physname) +static void +scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, + CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu) { - if (name == NULL) - name = dwarf2_name (die, cu); + struct partial_die_info *pdi; - /* For Fortran GDB prefers DW_AT_*linkage_name if present but otherwise - compute it by typename_concat inside GDB. */ - if (cu->language == language_ada - || (cu->language == language_fortran && physname)) - { - /* For Ada unit, we prefer the linkage name over the name, as - the former contains the exported name, which the user expects - to be able to reference. Ideally, we want the user to be able - to reference this entity using either natural or linkage name, - but we haven't started looking at this enhancement yet. */ - struct attribute *attr; + /* Now, march along the PDI's, descending into ones which have + interesting children but skipping the children of the other ones, + until we reach the end of the compilation unit. */ - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); - if (attr && DW_STRING (attr)) - return DW_STRING (attr); - } + pdi = first_die; - /* These are the only languages we know how to qualify names in. */ - if (name != NULL - && (cu->language == language_cplus || cu->language == language_java - || cu->language == language_fortran)) + while (pdi != NULL) { - if (die_needs_namespace (die, cu)) - { - long length; - char *prefix; - struct ui_file *buf; - - prefix = determine_prefix (die, cu); - buf = mem_fileopen (); - if (*prefix != '\0') - { - char *prefixed_name = typename_concat (NULL, prefix, name, - physname, cu); - - fputs_unfiltered (prefixed_name, buf); - xfree (prefixed_name); - } - else - fputs_unfiltered (name ? name : "", buf); + fixup_partial_die (pdi, cu); - /* For Java and C++ methods, append formal parameter type - information, if PHYSNAME. */ + /* Anonymous namespaces or modules have no name but have interesting + children, so we need to look at them. Ditto for anonymous + enums. */ - if (physname && die->tag == DW_TAG_subprogram - && (cu->language == language_cplus - || cu->language == language_java)) + if (pdi->name != NULL || pdi->tag == DW_TAG_namespace + || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type) + { + switch (pdi->tag) { - struct type *type = read_type_die (die, cu); - - c_type_print_args (type, buf, 0, cu->language); - - if (cu->language == language_java) + case DW_TAG_subprogram: + add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu); + break; + case DW_TAG_constant: + case DW_TAG_variable: + case DW_TAG_typedef: + case DW_TAG_union_type: + if (!pdi->is_declaration) { - /* For java, we must append the return type to method - names. */ - if (die->tag == DW_TAG_subprogram) - java_print_type (TYPE_TARGET_TYPE (type), "", buf, - 0, 0); + add_partial_symbol (pdi, cu); } - else if (cu->language == language_cplus) + break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + if (!pdi->is_declaration) { - if (TYPE_NFIELDS (type) > 0 - && TYPE_FIELD_ARTIFICIAL (type, 0) - && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0)))) - fputs_unfiltered (" const", buf); + add_partial_symbol (pdi, cu); } + break; + case DW_TAG_enumeration_type: + if (!pdi->is_declaration) + add_partial_enumeration (pdi, cu); + break; + case DW_TAG_base_type: + case DW_TAG_subrange_type: + /* File scope base type definitions are added to the partial + symbol table. */ + add_partial_symbol (pdi, cu); + break; + case DW_TAG_namespace: + add_partial_namespace (pdi, lowpc, highpc, need_pc, cu); + break; + case DW_TAG_module: + add_partial_module (pdi, lowpc, highpc, need_pc, cu); + break; + default: + break; } + } - name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack, - &length); - ui_file_delete (buf); - - if (cu->language == language_cplus) - { - char *cname - = dwarf2_canonicalize_name (name, cu, - &cu->objfile->objfile_obstack); + /* If the die has a sibling, skip to the sibling. */ - if (cname != NULL) - name = cname; - } - } + pdi = pdi->die_sibling; } - - return name; } -/* Return the fully qualified name of DIE, based on its DW_AT_name. - If scope qualifiers are appropriate they will be added. The result - will be allocated on the objfile_obstack, or NULL if the DIE does - not have a name. NAME may either be from a previous call to - dwarf2_name or NULL. +/* Functions used to compute the fully scoped name of a partial DIE. - The output string will be canonicalized (if C++/Java). */ + Normally, this is simple. For C++, the parent DIE's fully scoped + name is concatenated with "::" and the partial DIE's name. For + Java, the same thing occurs except that "." is used instead of "::". + Enumerators are an exception; they use the scope of their parent + enumeration type, i.e. the name of the enumeration type is not + prepended to the enumerator. -static const char * -dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu) + There are two complexities. One is DW_AT_specification; in this + case "parent" means the parent of the target of the specification, + instead of the direct parent of the DIE. The other is compilers + which do not emit DW_TAG_namespace; in this case we try to guess + the fully qualified name of structure types from their members' + linkage names. This must be done using the DIE's children rather + than the children of any DW_AT_specification target. We only need + to do this for structures at the top level, i.e. if the target of + any DW_AT_specification (if any; otherwise the DIE itself) does not + have a parent. */ + +/* Compute the scope prefix associated with PDI's parent, in + compilation unit CU. The result will be allocated on CU's + comp_unit_obstack, or a copy of the already allocated PDI->NAME + field. NULL is returned if no prefix is necessary. */ +static char * +partial_die_parent_scope (struct partial_die_info *pdi, + struct dwarf2_cu *cu) { - return dwarf2_compute_name (name, die, cu, 0); -} + char *grandparent_scope; + struct partial_die_info *parent, *real_pdi; -/* Construct a physname for the given DIE in CU. NAME may either be - from a previous call to dwarf2_name or NULL. The result will be - allocated on the objfile_objstack or NULL if the DIE does not have a - name. + /* We need to look at our parent DIE; if we have a DW_AT_specification, + then this means the parent of the specification DIE. */ - The output string will be canonicalized (if C++/Java). */ + real_pdi = pdi; + while (real_pdi->has_specification) + real_pdi = find_partial_die (real_pdi->spec_offset, cu); -static const char * -dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu) -{ - return dwarf2_compute_name (name, die, cu, 1); -} + parent = real_pdi->die_parent; + if (parent == NULL) + return NULL; -/* Read the import statement specified by the given die and record it. */ + if (parent->scope_set) + return parent->scope; -static void -read_import_statement (struct die_info *die, struct dwarf2_cu *cu) -{ - struct attribute *import_attr; - struct die_info *imported_die; - struct dwarf2_cu *imported_cu; - const char *imported_name; - const char *imported_name_prefix; - const char *canonical_name; - const char *import_alias; - const char *imported_declaration = NULL; - const char *import_prefix; + fixup_partial_die (parent, cu); - char *temp; + grandparent_scope = partial_die_parent_scope (parent, cu); - import_attr = dwarf2_attr (die, DW_AT_import, cu); - if (import_attr == NULL) + /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus + DW_TAG_namespace DIEs with a name of "::" for the global namespace. + Work around this problem here. */ + if (cu->language == language_cplus + && parent->tag == DW_TAG_namespace + && strcmp (parent->name, "::") == 0 + && grandparent_scope == NULL) { - complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"), - dwarf_tag_name (die->tag)); - return; + parent->scope = NULL; + parent->scope_set = 1; + return NULL; } - imported_cu = cu; - imported_die = follow_die_ref_or_sig (die, import_attr, &imported_cu); - imported_name = dwarf2_name (imported_die, imported_cu); - if (imported_name == NULL) + if (parent->tag == DW_TAG_namespace + || parent->tag == DW_TAG_module + || parent->tag == DW_TAG_structure_type + || parent->tag == DW_TAG_class_type + || parent->tag == DW_TAG_interface_type + || parent->tag == DW_TAG_union_type + || parent->tag == DW_TAG_enumeration_type) { - /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524 - - The import in the following code: - namespace A - { - typedef int B; - } - - int main () - { - using A::B; - B b; - return b; - } + if (grandparent_scope == NULL) + parent->scope = parent->name; + else + parent->scope = typename_concat (&cu->comp_unit_obstack, + grandparent_scope, + parent->name, 0, cu); + } + else if (parent->tag == DW_TAG_enumerator) + /* Enumerators should not get the name of the enumeration as a prefix. */ + parent->scope = grandparent_scope; + else + { + /* FIXME drow/2004-04-01: What should we be doing with + function-local names? For partial symbols, we should probably be + ignoring them. */ + complaint (&symfile_complaints, + _("unhandled containing DIE tag %d for DIE at %d"), + parent->tag, pdi->offset); + parent->scope = grandparent_scope; + } - ... - <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration) - <52> DW_AT_decl_file : 1 - <53> DW_AT_decl_line : 6 - <54> DW_AT_import : <0x75> - <2><58>: Abbrev Number: 4 (DW_TAG_typedef) - <59> DW_AT_name : B - <5b> DW_AT_decl_file : 1 - <5c> DW_AT_decl_line : 2 - <5d> DW_AT_type : <0x6e> - ... - <1><75>: Abbrev Number: 7 (DW_TAG_base_type) - <76> DW_AT_byte_size : 4 - <77> DW_AT_encoding : 5 (signed) + parent->scope_set = 1; + return parent->scope; +} - imports the wrong die ( 0x75 instead of 0x58 ). - This case will be ignored until the gcc bug is fixed. */ - return; - } +/* Return the fully scoped name associated with PDI, from compilation unit + CU. The result will be allocated with malloc. */ +static char * +partial_die_full_name (struct partial_die_info *pdi, + struct dwarf2_cu *cu) +{ + char *parent_scope; - /* Figure out the local name after import. */ - import_alias = dwarf2_name (die, cu); + /* If this is a template instantiation, we can not work out the + template arguments from partial DIEs. So, unfortunately, we have + to go through the full DIEs. At least any work we do building + types here will be reused if full symbols are loaded later. */ + if (pdi->has_template_arguments) + { + fixup_partial_die (pdi, cu); - /* Figure out where the statement is being imported to. */ - import_prefix = determine_prefix (die, cu); + if (pdi->name != NULL && strchr (pdi->name, '<') == NULL) + { + struct die_info *die; + struct attribute attr; + struct dwarf2_cu *ref_cu = cu; - /* Figure out what the scope of the imported die is and prepend it - to the name of the imported die. */ - imported_name_prefix = determine_prefix (imported_die, imported_cu); + attr.name = 0; + attr.form = DW_FORM_ref_addr; + attr.u.addr = pdi->offset; + die = follow_die_ref (NULL, &attr, &ref_cu); - if (imported_die->tag != DW_TAG_namespace - && imported_die->tag != DW_TAG_module) - { - imported_declaration = imported_name; - canonical_name = imported_name_prefix; - } - else if (strlen (imported_name_prefix) > 0) - { - temp = alloca (strlen (imported_name_prefix) - + 2 + strlen (imported_name) + 1); - strcpy (temp, imported_name_prefix); - strcat (temp, "::"); - strcat (temp, imported_name); - canonical_name = temp; + return xstrdup (dwarf2_full_name (NULL, die, ref_cu)); + } } - else - canonical_name = imported_name; - cp_add_using_directive (import_prefix, - canonical_name, - import_alias, - imported_declaration, - &cu->objfile->objfile_obstack); + parent_scope = partial_die_parent_scope (pdi, cu); + if (parent_scope == NULL) + return NULL; + else + return typename_concat (NULL, parent_scope, pdi->name, 0, cu); } static void -initialize_cu_func_list (struct dwarf2_cu *cu) -{ - cu->first_fn = cu->last_fn = cu->cached_fn = NULL; -} - -static void -free_cu_line_header (void *arg) -{ - struct dwarf2_cu *cu = arg; - - free_line_header (cu->line_header); - cu->line_header = NULL; -} - -static void -read_file_scope (struct die_info *die, struct dwarf2_cu *cu) +add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; - struct cleanup *back_to = make_cleanup (null_cleanup, 0); - CORE_ADDR lowpc = ((CORE_ADDR) -1); - CORE_ADDR highpc = ((CORE_ADDR) 0); - struct attribute *attr; - char *name = NULL; - char *comp_dir = NULL; - struct die_info *child_die; - bfd *abfd = objfile->obfd; - struct line_header *line_header = 0; + CORE_ADDR addr = 0; + char *actual_name = NULL; + const struct partial_symbol *psym = NULL; CORE_ADDR baseaddr; + int built_actual_name = 0; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - get_scope_pc_bounds (die, &lowpc, &highpc, cu); + actual_name = partial_die_full_name (pdi, cu); + if (actual_name) + built_actual_name = 1; - /* If we didn't find a lowpc, set it to highpc to avoid complaints - from finish_block. */ - if (lowpc == ((CORE_ADDR) -1)) - lowpc = highpc; - lowpc += baseaddr; - highpc += baseaddr; + if (actual_name == NULL) + actual_name = pdi->name; - /* Find the filename. Do not use dwarf2_name here, since the filename - is not a source language identifier. */ - attr = dwarf2_attr (die, DW_AT_name, cu); - if (attr) + switch (pdi->tag) { - name = DW_STRING (attr); - } + case DW_TAG_subprogram: + if (pdi->is_external || cu->language == language_ada) + { + /* brobecker/2007-12-26: Normally, only "external" DIEs are part + of the global scope. But in Ada, we want to be able to access + nested procedures globally. So all Ada subprograms are stored + in the global scope. */ + /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr, + mst_text, objfile); */ + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, + cu->language, objfile); + } + else + { + /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr, + mst_file_text, objfile); */ + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, + cu->language, objfile); + } + break; + case DW_TAG_constant: + { + struct psymbol_allocation_list *list; - attr = dwarf2_attr (die, DW_AT_comp_dir, cu); - if (attr) - comp_dir = DW_STRING (attr); - else if (name != NULL && IS_ABSOLUTE_PATH (name)) - { - comp_dir = ldirname (name); - if (comp_dir != NULL) - make_cleanup (xfree, comp_dir); - } - if (comp_dir != NULL) - { - /* Irix 6.2 native cc prepends .: to the compilation - directory, get rid of it. */ - char *cp = strchr (comp_dir, ':'); + if (pdi->is_external) + list = &objfile->global_psymbols; + else + list = &objfile->static_psymbols; + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, VAR_DOMAIN, LOC_STATIC, + list, 0, 0, cu->language, objfile); + } + break; + case DW_TAG_variable: + if (pdi->locdesc) + addr = decode_locdesc (pdi->locdesc, cu); - if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/') - comp_dir = cp + 1; - } + if (pdi->locdesc + && addr == 0 + && !dwarf2_per_objfile->has_section_at_zero) + { + /* A global or static variable may also have been stripped + out by the linker if unused, in which case its address + will be nullified; do not add such variables into partial + symbol table then. */ + } + else if (pdi->is_external) + { + /* Global Variable. + Don't enter into the minimal symbol tables as there is + a minimal symbol table entry from the ELF symbols already. + Enter into partial symbol table if it has a location + descriptor or a type. + If the location descriptor is missing, new_symbol will create + a LOC_UNRESOLVED symbol, the address of the variable will then + be determined from the minimal symbol table whenever the variable + is referenced. + The address for the partial symbol table entry is not + used by GDB, but it comes in handy for debugging partial symbol + table building. */ - if (name == NULL) - name = ""; + if (pdi->locdesc || pdi->has_type) + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, + cu->language, objfile); + } + else + { + /* Static Variable. Skip symbols without location descriptors. */ + if (pdi->locdesc == NULL) + { + if (built_actual_name) + xfree (actual_name); + return; + } + /* prim_record_minimal_symbol (actual_name, addr + baseaddr, + mst_file_data, objfile); */ + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, + cu->language, objfile); + } + break; + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_subrange_type: + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu->language, objfile); + break; + case DW_TAG_namespace: + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->global_psymbols, + 0, (CORE_ADDR) 0, cu->language, objfile); + break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + /* Skip external references. The DWARF standard says in the section + about "Structure, Union, and Class Type Entries": "An incomplete + structure, union or class type is represented by a structure, + union or class entry that does not have a byte size attribute + and that has a DW_AT_declaration attribute." */ + if (!pdi->has_byte_size && pdi->is_declaration) + { + if (built_actual_name) + xfree (actual_name); + return; + } - attr = dwarf2_attr (die, DW_AT_language, cu); - if (attr) - { - set_cu_language (DW_UNSND (attr), cu); + /* NOTE: carlton/2003-10-07: See comment in new_symbol about + static vs. global. */ + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + STRUCT_DOMAIN, LOC_TYPEDEF, + (cu->language == language_cplus + || cu->language == language_java) + ? &objfile->global_psymbols + : &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu->language, objfile); + + break; + case DW_TAG_enumerator: + add_psymbol_to_list (actual_name, strlen (actual_name), + built_actual_name, + VAR_DOMAIN, LOC_CONST, + (cu->language == language_cplus + || cu->language == language_java) + ? &objfile->global_psymbols + : &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu->language, objfile); + break; + default: + break; } - attr = dwarf2_attr (die, DW_AT_producer, cu); - if (attr) - cu->producer = DW_STRING (attr); + if (built_actual_name) + xfree (actual_name); +} - /* We assume that we're processing GCC output. */ - processing_gcc_compilation = 2; +/* Read a partial die corresponding to a namespace; also, add a symbol + corresponding to that namespace to the symbol table. NAMESPACE is + the name of the enclosing namespace. */ - processing_has_namespace_info = 0; +static void +add_partial_namespace (struct partial_die_info *pdi, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + int need_pc, struct dwarf2_cu *cu) +{ + /* Add a symbol for the namespace. */ - start_symtab (name, comp_dir, lowpc); - record_debugformat ("DWARF 2"); - record_producer (cu->producer); + add_partial_symbol (pdi, cu); - initialize_cu_func_list (cu); + /* Now scan partial symbols in that namespace. */ - /* Decode line number information if present. We do this before - processing child DIEs, so that the line header table is available - for DW_AT_decl_file. */ - attr = dwarf2_attr (die, DW_AT_stmt_list, cu); - if (attr) - { - unsigned int line_offset = DW_UNSND (attr); - line_header = dwarf_decode_line_header (line_offset, abfd, cu); - if (line_header) - { - cu->line_header = line_header; - make_cleanup (free_cu_line_header, cu); - dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL); - } - } + if (pdi->has_children) + scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu); +} - /* Process all dies in compilation unit. */ - if (die->child != NULL) - { - child_die = die->child; - while (child_die && child_die->tag) - { - process_die (child_die, cu); - child_die = sibling_die (child_die); - } - } +/* Read a partial die corresponding to a Fortran module. */ - /* Decode macro information, if present. Dwarf 2 macro information - refers to information in the line number info statement program - header, so we can only read it if we've read the header - successfully. */ - attr = dwarf2_attr (die, DW_AT_macro_info, cu); - if (attr && line_header) - { - unsigned int macro_offset = DW_UNSND (attr); +static void +add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, + CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu) +{ + /* Now scan partial symbols in that module. */ - dwarf_decode_macros (line_header, macro_offset, - comp_dir, abfd, cu); - } - do_cleanups (back_to); + if (pdi->has_children) + scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu); } -/* For TUs we want to skip the first top level sibling if it's not the - actual type being defined by this TU. In this case the first top - level sibling is there to provide context only. */ +/* Read a partial die corresponding to a subprogram and create a partial + symbol for that subprogram. When the CU language allows it, this + routine also defines a partial symbol for each nested subprogram + that this subprogram contains. + + DIE my also be a lexical block, in which case we simply search + recursively for suprograms defined inside that lexical block. + Again, this is only performed when the CU language allows this + type of definitions. */ static void -read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct cleanup *back_to = make_cleanup (null_cleanup, 0); - CORE_ADDR lowpc; - struct attribute *attr; - char *name = NULL; - char *comp_dir = NULL; - struct die_info *child_die; - bfd *abfd = objfile->obfd; - - /* start_symtab needs a low pc, but we don't really have one. - Do what read_file_scope would do in the absence of such info. */ - lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - - /* Find the filename. Do not use dwarf2_name here, since the filename - is not a source language identifier. */ - attr = dwarf2_attr (die, DW_AT_name, cu); - if (attr) - name = DW_STRING (attr); - - attr = dwarf2_attr (die, DW_AT_comp_dir, cu); - if (attr) - comp_dir = DW_STRING (attr); - else if (name != NULL && IS_ABSOLUTE_PATH (name)) +add_partial_subprogram (struct partial_die_info *pdi, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + int need_pc, struct dwarf2_cu *cu) +{ + if (pdi->tag == DW_TAG_subprogram) { - comp_dir = ldirname (name); - if (comp_dir != NULL) - make_cleanup (xfree, comp_dir); - } - - if (name == NULL) - name = ""; - - attr = dwarf2_attr (die, DW_AT_language, cu); - if (attr) - set_cu_language (DW_UNSND (attr), cu); - - /* This isn't technically needed today. It is done for symmetry - with read_file_scope. */ - attr = dwarf2_attr (die, DW_AT_producer, cu); - if (attr) - cu->producer = DW_STRING (attr); - - /* We assume that we're processing GCC output. */ - processing_gcc_compilation = 2; - - processing_has_namespace_info = 0; - - start_symtab (name, comp_dir, lowpc); - record_debugformat ("DWARF 2"); - record_producer (cu->producer); + if (pdi->has_pc_info) + { + if (pdi->lowpc < *lowpc) + *lowpc = pdi->lowpc; + if (pdi->highpc > *highpc) + *highpc = pdi->highpc; + if (need_pc) + { + CORE_ADDR baseaddr; + struct objfile *objfile = cu->objfile; - /* Process the dies in the type unit. */ - if (die->child == NULL) - { - dump_die_for_error (die); - error (_("Dwarf Error: Missing children for type unit [in module %s]"), - bfd_get_filename (abfd)); + baseaddr = ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + addrmap_set_empty (objfile->psymtabs_addrmap, + pdi->lowpc + baseaddr, + pdi->highpc - 1 + baseaddr, + cu->per_cu->v.psymtab); + } + if (!pdi->is_declaration) + /* Ignore subprogram DIEs that do not have a name, they are + illegal. Do not emit a complaint at this point, we will + do so when we convert this psymtab into a symtab. */ + if (pdi->name) + add_partial_symbol (pdi, cu); + } } - child_die = die->child; + if (! pdi->has_children) + return; - while (child_die && child_die->tag) + if (cu->language == language_ada) { - process_die (child_die, cu); - - child_die = sibling_die (child_die); + pdi = pdi->die_child; + while (pdi != NULL) + { + fixup_partial_die (pdi, cu); + if (pdi->tag == DW_TAG_subprogram + || pdi->tag == DW_TAG_lexical_block) + add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu); + pdi = pdi->die_sibling; + } } - - do_cleanups (back_to); } +/* Read a partial die corresponding to an enumeration type. */ + static void -add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc, - struct dwarf2_cu *cu) +add_partial_enumeration (struct partial_die_info *enum_pdi, + struct dwarf2_cu *cu) { - struct function_range *thisfn; - - thisfn = (struct function_range *) - obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range)); - thisfn->name = name; - thisfn->lowpc = lowpc; - thisfn->highpc = highpc; - thisfn->seen_line = 0; - thisfn->next = NULL; + struct partial_die_info *pdi; - if (cu->last_fn == NULL) - cu->first_fn = thisfn; - else - cu->last_fn->next = thisfn; + if (enum_pdi->name != NULL) + add_partial_symbol (enum_pdi, cu); - cu->last_fn = thisfn; + pdi = enum_pdi->die_child; + while (pdi) + { + if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL) + complaint (&symfile_complaints, _("malformed enumerator DIE ignored")); + else + add_partial_symbol (pdi, cu); + pdi = pdi->die_sibling; + } } -/* qsort helper for inherit_abstract_dies. */ +/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU. + Return the corresponding abbrev, or NULL if the number is zero (indicating + an empty DIE). In either case *BYTES_READ will be set to the length of + the initial number. */ -static int -unsigned_int_compar (const void *ap, const void *bp) +static struct abbrev_info * +peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read, + struct dwarf2_cu *cu) { - unsigned int a = *(unsigned int *) ap; - unsigned int b = *(unsigned int *) bp; + bfd *abfd = cu->objfile->obfd; + unsigned int abbrev_number; + struct abbrev_info *abbrev; - return (a > b) - (b > a); -} + abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read); -/* DW_AT_abstract_origin inherits whole DIEs (not just their attributes). - Inherit only the children of the DW_AT_abstract_origin DIE not being already - referenced by DW_AT_abstract_origin from the children of the current DIE. */ + if (abbrev_number == 0) + return NULL; -static void -inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child_die; - unsigned die_children_count; - /* CU offsets which were referenced by children of the current DIE. */ - unsigned *offsets; - unsigned *offsets_end, *offsetp; - /* Parent of DIE - referenced by DW_AT_abstract_origin. */ - struct die_info *origin_die; - /* Iterator of the ORIGIN_DIE children. */ - struct die_info *origin_child_die; - struct cleanup *cleanups; - struct attribute *attr; + abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); + if (!abbrev) + { + error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"), + abbrev_number, bfd_get_filename (abfd)); + } - attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); - if (!attr) - return; + return abbrev; +} - origin_die = follow_die_ref (die, attr, &cu); - if (die->tag != origin_die->tag - && !(die->tag == DW_TAG_inlined_subroutine - && origin_die->tag == DW_TAG_subprogram)) - complaint (&symfile_complaints, - _("DIE 0x%x and its abstract origin 0x%x have different tags"), - die->offset, origin_die->offset); +/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. + Returns a pointer to the end of a series of DIEs, terminated by an empty + DIE. Any children of the skipped DIEs will also be skipped. */ - child_die = die->child; - die_children_count = 0; - while (child_die && child_die->tag) +static gdb_byte * +skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu) +{ + struct abbrev_info *abbrev; + unsigned int bytes_read; + + while (1) { - child_die = sibling_die (child_die); - die_children_count++; + abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); + if (abbrev == NULL) + return info_ptr + bytes_read; + else + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); } - offsets = xmalloc (sizeof (*offsets) * die_children_count); - cleanups = make_cleanup (xfree, offsets); +} - offsets_end = offsets; - child_die = die->child; - while (child_die && child_die->tag) - { - /* For each CHILD_DIE, find the corresponding child of - ORIGIN_DIE. If there is more than one layer of - DW_AT_abstract_origin, follow them all; there shouldn't be, - but GCC versions at least through 4.4 generate this (GCC PR - 40573). */ - struct die_info *child_origin_die = child_die; +/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. + INFO_PTR should point just after the initial uleb128 of a DIE, and the + abbrev corresponding to that skipped uleb128 should be passed in + ABBREV. Returns a pointer to this DIE's sibling, skipping any + children. */ - while (1) - { - attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin, cu); - if (attr == NULL) - break; - child_origin_die = follow_die_ref (child_origin_die, attr, &cu); - } +static gdb_byte * +skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr, + struct abbrev_info *abbrev, struct dwarf2_cu *cu) +{ + unsigned int bytes_read; + struct attribute attr; + bfd *abfd = cu->objfile->obfd; + unsigned int form, i; - /* According to DWARF3 3.3.8.2 #3 new entries without their abstract - counterpart may exist. */ - if (child_origin_die != child_die) + for (i = 0; i < abbrev->num_attrs; i++) + { + /* The only abbrev we care about is DW_AT_sibling. */ + if (abbrev->attrs[i].name == DW_AT_sibling) { - if (child_die->tag != child_origin_die->tag - && !(child_die->tag == DW_TAG_inlined_subroutine - && child_origin_die->tag == DW_TAG_subprogram)) - complaint (&symfile_complaints, - _("Child DIE 0x%x and its abstract origin 0x%x have " - "different tags"), child_die->offset, - child_origin_die->offset); - if (child_origin_die->parent != origin_die) + read_attribute (&attr, &abbrev->attrs[i], + abfd, info_ptr, cu); + if (attr.form == DW_FORM_ref_addr) complaint (&symfile_complaints, - _("Child DIE 0x%x and its abstract origin 0x%x have " - "different parents"), child_die->offset, - child_origin_die->offset); + _("ignoring absolute DW_AT_sibling")); else - *offsets_end++ = child_origin_die->offset; + return buffer + dwarf2_get_ref_die_offset (&attr); } - child_die = sibling_die (child_die); - } - qsort (offsets, offsets_end - offsets, sizeof (*offsets), - unsigned_int_compar); - for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) - if (offsetp[-1] == *offsetp) - complaint (&symfile_complaints, _("Multiple children of DIE 0x%x refer " - "to DIE 0x%x as their abstract origin"), - die->offset, *offsetp); - offsetp = offsets; - origin_child_die = origin_die->child; - while (origin_child_die && origin_child_die->tag) - { - /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children? */ - while (offsetp < offsets_end && *offsetp < origin_child_die->offset) - offsetp++; - if (offsetp >= offsets_end || *offsetp > origin_child_die->offset) + /* If it isn't DW_AT_sibling, skip this attribute. */ + form = abbrev->attrs[i].form; + skip_attribute: + switch (form) { - /* Found that ORIGIN_CHILD_DIE is really not referenced. */ - process_die (origin_child_die, cu); - } - origin_child_die = sibling_die (origin_child_die); - } - - do_cleanups (cleanups); -} - -static void -read_func_scope (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct context_stack *new; - CORE_ADDR lowpc; - CORE_ADDR highpc; - struct die_info *child_die; - struct attribute *attr, *call_line, *call_file; - char *name; - CORE_ADDR baseaddr; - struct block *block; - int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + case DW_FORM_ref_addr: + /* In DWARF 2, DW_FORM_ref_addr is address sized; in DWARF 3 + and later it is offset sized. */ + if (cu->header.version == 2) + info_ptr += cu->header.addr_size; + else + info_ptr += cu->header.offset_size; + break; + case DW_FORM_addr: + info_ptr += cu->header.addr_size; + break; + case DW_FORM_data1: + case DW_FORM_ref1: + case DW_FORM_flag: + info_ptr += 1; + break; + case DW_FORM_flag_present: + break; + case DW_FORM_data2: + case DW_FORM_ref2: + info_ptr += 2; + break; + case DW_FORM_data4: + case DW_FORM_ref4: + info_ptr += 4; + break; + case DW_FORM_data8: + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + info_ptr += 8; + break; + case DW_FORM_string: + read_direct_string (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_sec_offset: + case DW_FORM_strp: + info_ptr += cu->header.offset_size; + break; + case DW_FORM_exprloc: + case DW_FORM_block: + info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_block1: + info_ptr += 1 + read_1_byte (abfd, info_ptr); + break; + case DW_FORM_block2: + info_ptr += 2 + read_2_bytes (abfd, info_ptr); + break; + case DW_FORM_block4: + info_ptr += 4 + read_4_bytes (abfd, info_ptr); + break; + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + info_ptr = skip_leb128 (abfd, info_ptr); + break; + case DW_FORM_indirect: + form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + /* We need to continue parsing from here, so just go back to + the top. */ + goto skip_attribute; - if (inlined_func) - { - /* If we do not have call site information, we can't show the - caller of this inlined function. That's too confusing, so - only use the scope for local variables. */ - call_line = dwarf2_attr (die, DW_AT_call_line, cu); - call_file = dwarf2_attr (die, DW_AT_call_file, cu); - if (call_line == NULL || call_file == NULL) - { - read_lexical_block_scope (die, cu); - return; + default: + error (_("Dwarf Error: Cannot handle %s " + "in DWARF reader [in module %s]"), + dwarf_form_name (form), + bfd_get_filename (abfd)); } } - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + if (abbrev->has_children) + return skip_children (buffer, info_ptr, cu); + else + return info_ptr; +} - name = dwarf2_name (die, cu); +/* Locate ORIG_PDI's sibling. + INFO_PTR should point to the start of the next DIE after ORIG_PDI + in BUFFER. */ - /* Ignore functions with missing or empty names. These are actually - illegal according to the DWARF standard. */ - if (name == NULL) - { - complaint (&symfile_complaints, - _("missing name for subprogram DIE at %d"), die->offset); - return; - } +static gdb_byte * +locate_pdi_sibling (struct partial_die_info *orig_pdi, + gdb_byte *buffer, gdb_byte *info_ptr, + bfd *abfd, struct dwarf2_cu *cu) +{ + /* Do we know the sibling already? */ - /* Ignore functions with missing or invalid low and high pc attributes. */ - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) - { - attr = dwarf2_attr (die, DW_AT_external, cu); - if (!attr || !DW_UNSND (attr)) - complaint (&symfile_complaints, - _("cannot get low and high bounds for subprogram DIE at %d"), - die->offset); - return; - } + if (orig_pdi->sibling) + return orig_pdi->sibling; - lowpc += baseaddr; - highpc += baseaddr; + /* Are there any children to deal with? */ - /* Record the function range for dwarf_decode_lines. */ - add_to_cu_func_list (name, lowpc, highpc, cu); + if (!orig_pdi->has_children) + return info_ptr; - new = push_context (0, lowpc); - new->name = new_symbol (die, read_type_die (die, cu), cu); + /* Skip the children the long way. */ - /* If there is a location expression for DW_AT_frame_base, record - it. */ - attr = dwarf2_attr (die, DW_AT_frame_base, cu); - if (attr) - /* FIXME: cagney/2004-01-26: The DW_AT_frame_base's location - expression is being recorded directly in the function's symbol - and not in a separate frame-base object. I guess this hack is - to avoid adding some sort of frame-base adjunct/annex to the - function's symbol :-(. The problem with doing this is that it - results in a function symbol with a location expression that - has nothing to do with the location of the function, ouch! The - relationship should be: a function's symbol has-a frame base; a - frame-base has-a location expression. */ - dwarf2_symbol_mark_computed (attr, new->name, cu); + return skip_children (buffer, info_ptr, cu); +} - cu->list_in_scope = &local_symbols; +/* Expand this partial symbol table into a full symbol table. */ - if (die->child != NULL) +static void +dwarf2_psymtab_to_symtab (struct partial_symtab *pst) +{ + if (pst != NULL) { - child_die = die->child; - while (child_die && child_die->tag) + if (pst->readin) { - process_die (child_die, cu); - child_die = sibling_die (child_die); + warning (_("bug: psymtab for %s is already read in."), + pst->filename); } - } - - inherit_abstract_dies (die, cu); + else + { + if (info_verbose) + { + printf_filtered (_("Reading in symbols for %s..."), + pst->filename); + gdb_flush (gdb_stdout); + } - /* If we have a DW_AT_specification, we might need to import using - directives from the context of the specification DIE. See the - comment in determine_prefix. */ - if (cu->language == language_cplus - && dwarf2_attr (die, DW_AT_specification, cu)) - { - struct dwarf2_cu *spec_cu = cu; - struct die_info *spec_die = die_specification (die, &spec_cu); + /* Restore our global data. */ + dwarf2_per_objfile = objfile_data (pst->objfile, + dwarf2_objfile_data_key); - while (spec_die) - { - child_die = spec_die->child; - while (child_die && child_die->tag) + /* If this psymtab is constructed from a debug-only objfile, the + has_section_at_zero flag will not necessarily be correct. We + can get the correct value for this flag by looking at the data + associated with the (presumably stripped) associated objfile. */ + if (pst->objfile->separate_debug_objfile_backlink) { - if (child_die->tag == DW_TAG_imported_module) - process_die (child_die, spec_cu); - child_die = sibling_die (child_die); + struct dwarf2_per_objfile *dpo_backlink + = objfile_data (pst->objfile->separate_debug_objfile_backlink, + dwarf2_objfile_data_key); + + dwarf2_per_objfile->has_section_at_zero + = dpo_backlink->has_section_at_zero; } - /* In some cases, GCC generates specification DIEs that - themselves contain DW_AT_specification attributes. */ - spec_die = die_specification (spec_die, &spec_cu); + dwarf2_per_objfile->reading_partial_symbols = 0; + + psymtab_to_symtab_1 (pst); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered (_("done.\n")); } } +} - new = pop_context (); - /* Make a block for the local symbols within. */ - block = finish_block (new->name, &local_symbols, new->old_blocks, - lowpc, highpc, objfile); +/* Add PER_CU to the queue. */ - /* For C++, set the block's scope. */ - if (cu->language == language_cplus || cu->language == language_fortran) - cp_set_block_scope (new->name, block, &objfile->objfile_obstack, - determine_prefix (die, cu), - processing_has_namespace_info); +static void +queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) +{ + struct dwarf2_queue_item *item; - /* If we have address ranges, record them. */ - dwarf2_record_block_ranges (die, block, baseaddr, cu); + per_cu->queued = 1; + item = xmalloc (sizeof (*item)); + item->per_cu = per_cu; + item->next = NULL; - /* In C++, we can have functions nested inside functions (e.g., when - a function declares a class that has methods). This means that - when we finish processing a function scope, we may need to go - back to building a containing block's symbol lists. */ - local_symbols = new->locals; - param_symbols = new->params; - using_directives = new->using_directives; + if (dwarf2_queue == NULL) + dwarf2_queue = item; + else + dwarf2_queue_tail->next = item; - /* If we've finished processing a top-level function, subsequent - symbols go in the file symbol list. */ - if (outermost_context_p ()) - cu->list_in_scope = &file_symbols; + dwarf2_queue_tail = item; } -/* Process all the DIES contained within a lexical block scope. Start - a new scope, process the dies, and then close the scope. */ +/* Process the queue. */ static void -read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) +process_queue (struct objfile *objfile) { - struct objfile *objfile = cu->objfile; - struct context_stack *new; - CORE_ADDR lowpc, highpc; - struct die_info *child_die; - CORE_ADDR baseaddr; + struct dwarf2_queue_item *item, *next_item; - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* The queue starts out with one item, but following a DIE reference + may load a new CU, adding it to the end of the queue. */ + for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item) + { + if (dwarf2_per_objfile->using_index + ? !item->per_cu->v.quick->symtab + : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin)) + process_full_comp_unit (item->per_cu); - /* Ignore blocks with missing or invalid low and high pc attributes. */ - /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges - as multiple lexical blocks? Handling children in a sane way would - be nasty. Might be easier to properly extend generic blocks to - describe ranges. */ - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) - return; - lowpc += baseaddr; - highpc += baseaddr; + item->per_cu->queued = 0; + next_item = item->next; + xfree (item); + } - push_context (0, lowpc); - if (die->child != NULL) + dwarf2_queue_tail = NULL; +} + +/* Free all allocated queue entries. This function only releases anything if + an error was thrown; if the queue was processed then it would have been + freed as we went along. */ + +static void +dwarf2_release_queue (void *dummy) +{ + struct dwarf2_queue_item *item, *last; + + item = dwarf2_queue; + while (item) { - child_die = die->child; - while (child_die && child_die->tag) + /* Anything still marked queued is likely to be in an + inconsistent state, so discard it. */ + if (item->per_cu->queued) { - process_die (child_die, cu); - child_die = sibling_die (child_die); + if (item->per_cu->cu != NULL) + free_one_cached_comp_unit (item->per_cu->cu); + item->per_cu->queued = 0; } + + last = item; + item = item->next; + xfree (last); } - new = pop_context (); - if (local_symbols != NULL || using_directives != NULL) - { - struct block *block - = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, - highpc, objfile); + dwarf2_queue = dwarf2_queue_tail = NULL; +} - /* Note that recording ranges after traversing children, as we - do here, means that recording a parent's ranges entails - walking across all its children's ranges as they appear in - the address map, which is quadratic behavior. +/* Read in full symbols for PST, and anything it depends on. */ - It would be nicer to record the parent's ranges before - traversing its children, simply overriding whatever you find - there. But since we don't even decide whether to create a - block until after we've traversed its children, that's hard - to do. */ - dwarf2_record_block_ranges (die, block, baseaddr, cu); +static void +psymtab_to_symtab_1 (struct partial_symtab *pst) +{ + struct dwarf2_per_cu_data *per_cu; + struct cleanup *back_to; + int i; + + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + /* FIXME: i18n: Need to make this a single string. */ + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output. */ + gdb_flush (gdb_stdout); + } + psymtab_to_symtab_1 (pst->dependencies[i]); + } + + per_cu = pst->read_symtab_private; + + if (per_cu == NULL) + { + /* It's an include file, no symbols to read for it. + Everything is in the parent symtab. */ + pst->readin = 1; + return; } - local_symbols = new->locals; - using_directives = new->using_directives; + + dw2_do_instantiate_symtab (pst->objfile, per_cu); } -/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. - Return 1 if the attributes are present and valid, otherwise, return 0. - If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ +/* Load the DIEs associated with PER_CU into memory. */ -static int -dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, - CORE_ADDR *high_return, struct dwarf2_cu *cu, - struct partial_symtab *ranges_pst) +static void +load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, + struct objfile *objfile) { - struct objfile *objfile = cu->objfile; - struct comp_unit_head *cu_header = &cu->header; - bfd *obfd = objfile->obfd; - unsigned int addr_size = cu_header->addr_size; - CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); - /* Base address selection entry. */ - CORE_ADDR base; - int found_base; - unsigned int dummy; - gdb_byte *buffer; - CORE_ADDR marker; - int low_set; - CORE_ADDR low = 0; - CORE_ADDR high = 0; - CORE_ADDR baseaddr; + bfd *abfd = objfile->obfd; + struct dwarf2_cu *cu; + unsigned int offset; + gdb_byte *info_ptr, *beg_of_comp_unit; + struct cleanup *free_abbrevs_cleanup = NULL, *free_cu_cleanup = NULL; + struct attribute *attr; + int read_cu = 0; - found_base = cu->base_known; - base = cu->base_address; + gdb_assert (! per_cu->from_debug_types); - dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); - if (offset >= dwarf2_per_objfile->ranges.size) + /* Set local variables from the partial symbol table info. */ + offset = per_cu->offset; + + dwarf2_read_section (objfile, &dwarf2_per_objfile->info); + info_ptr = dwarf2_per_objfile->info.buffer + offset; + beg_of_comp_unit = info_ptr; + + if (per_cu->cu == NULL) { - complaint (&symfile_complaints, - _("Offset %d out of bounds for DW_AT_ranges attribute"), - offset); - return 0; - } - buffer = dwarf2_per_objfile->ranges.buffer + offset; + cu = xmalloc (sizeof (*cu)); + init_one_comp_unit (cu, objfile); - /* Read in the largest possible address. */ - marker = read_address (obfd, buffer, cu, &dummy); - if ((marker & mask) == mask) + read_cu = 1; + + /* If an error occurs while loading, release our storage. */ + free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); + + /* Read in the comp_unit header. */ + info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd); + + /* Complete the cu_header. */ + cu->header.offset = offset; + cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + + /* Read the abbrevs for this compilation unit. */ + dwarf2_read_abbrevs (abfd, cu); + free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu); + + /* Link this compilation unit into the compilation unit tree. */ + per_cu->cu = cu; + cu->per_cu = per_cu; + + /* Link this CU into read_in_chain. */ + per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; + dwarf2_per_objfile->read_in_chain = per_cu; + } + else { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); - buffer += 2 * addr_size; - offset += 2 * addr_size; - found_base = 1; + cu = per_cu->cu; + info_ptr += cu->header.first_die_offset; } - low_set = 0; + cu->dies = read_comp_unit (info_ptr, cu); - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* We try not to read any attributes in this function, because not + all objfiles needed for references have been loaded yet, and symbol + table processing isn't initialized. But we have to set the CU language, + or we won't be able to build types correctly. */ + prepare_one_comp_unit (cu, cu->dies); - while (1) + /* Similarly, if we do not read the producer, we can not apply + producer-specific interpretation. */ + attr = dwarf2_attr (cu->dies, DW_AT_producer, cu); + if (attr) + cu->producer = DW_STRING (attr); + + if (read_cu) { - CORE_ADDR range_beginning, range_end; + do_cleanups (free_abbrevs_cleanup); - range_beginning = read_address (obfd, buffer, cu, &dummy); - buffer += addr_size; - range_end = read_address (obfd, buffer, cu, &dummy); - buffer += addr_size; - offset += 2 * addr_size; + /* We've successfully allocated this compilation unit. Let our + caller clean it up when finished with it. */ + discard_cleanups (free_cu_cleanup); + } +} - /* An end of list marker is a pair of zero addresses. */ - if (range_beginning == 0 && range_end == 0) - /* Found the end of list entry. */ - break; +/* Add a DIE to the delayed physname list. */ - /* Each base address selection entry is a pair of 2 values. - The first is the largest possible address, the second is - the base address. Check for a base address here. */ - if ((range_beginning & mask) == mask) - { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); - found_base = 1; - continue; - } +static void +add_to_method_list (struct type *type, int fnfield_index, int index, + const char *name, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct delayed_method_info mi; + mi.type = type; + mi.fnfield_index = fnfield_index; + mi.index = index; + mi.name = name; + mi.die = die; + VEC_safe_push (delayed_method_info, cu->method_list, &mi); +} - if (!found_base) - { - /* We have no valid base address for the ranges - data. */ - complaint (&symfile_complaints, - _("Invalid .debug_ranges data (no base address)")); - return 0; - } +/* A cleanup for freeing the delayed method list. */ - range_beginning += base; - range_end += base; +static void +free_delayed_list (void *ptr) +{ + struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr; + if (cu->method_list != NULL) + { + VEC_free (delayed_method_info, cu->method_list); + cu->method_list = NULL; + } +} - if (ranges_pst != NULL && range_beginning < range_end) - addrmap_set_empty (objfile->psymtabs_addrmap, - range_beginning + baseaddr, range_end - 1 + baseaddr, - ranges_pst); +/* Compute the physnames of any methods on the CU's method list. - /* FIXME: This is recording everything as a low-high - segment of consecutive addresses. We should have a - data structure for discontiguous block ranges - instead. */ - if (! low_set) - { - low = range_beginning; - high = range_end; - low_set = 1; - } - else - { - if (range_beginning < low) - low = range_beginning; - if (range_end > high) - high = range_end; - } - } - - if (! low_set) - /* If the first entry is an end-of-list marker, the range - describes an empty scope, i.e. no instructions. */ - return 0; - - if (low_return) - *low_return = low; - if (high_return) - *high_return = high; - return 1; -} + The computation of method physnames is delayed in order to avoid the + (bad) condition that one of the method's formal parameters is of an as yet + incomplete type. */ -/* Get low and high pc attributes from a die. Return 1 if the attributes - are present and valid, otherwise, return 0. Return -1 if the range is - discontinuous, i.e. derived from DW_AT_ranges information. */ -static int -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, - CORE_ADDR *highpc, struct dwarf2_cu *cu, - struct partial_symtab *pst) +static void +compute_delayed_physnames (struct dwarf2_cu *cu) { - struct attribute *attr; - CORE_ADDR low = 0; - CORE_ADDR high = 0; - int ret = 0; - - attr = dwarf2_attr (die, DW_AT_high_pc, cu); - if (attr) - { - high = DW_ADDR (attr); - attr = dwarf2_attr (die, DW_AT_low_pc, cu); - if (attr) - low = DW_ADDR (attr); - else - /* Found high w/o low attribute. */ - return 0; - - /* Found consecutive range of addresses. */ - ret = 1; - } - else + int i; + struct delayed_method_info *mi; + for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i) { - attr = dwarf2_attr (die, DW_AT_ranges, cu); - if (attr != NULL) - { - /* Value of the DW_AT_ranges attribute is the offset in the - .debug_ranges section. */ - if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, pst)) - return 0; - /* Found discontinuous range of addresses. */ - ret = -1; - } + char *physname; + struct fn_fieldlist *fn_flp + = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index); + physname = (char *) dwarf2_physname ((char *) mi->name, mi->die, cu); + fn_flp->fn_fields[mi->index].physname = physname ? physname : ""; } - - if (high < low) - return 0; - - /* When using the GNU linker, .gnu.linkonce. sections are used to - eliminate duplicate copies of functions and vtables and such. - The linker will arbitrarily choose one and discard the others. - The AT_*_pc values for such functions refer to local labels in - these sections. If the section from that file was discarded, the - labels are not in the output, so the relocs get a value of 0. - If this is a discarded function, mark the pc bounds as invalid, - so that GDB will ignore it. */ - if (low == 0 && !dwarf2_per_objfile->has_section_at_zero) - return 0; - - *lowpc = low; - *highpc = high; - return ret; } -/* Assuming that DIE represents a subprogram DIE or a lexical block, get - its low and high PC addresses. Do nothing if these addresses could not - be determined. Otherwise, set LOWPC to the low address if it is smaller, - and HIGHPC to the high address if greater than HIGHPC. */ +/* Check for GCC >= 4.0. */ -static void -dwarf2_get_subprogram_pc_bounds (struct die_info *die, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - struct dwarf2_cu *cu) +static int +producer_is_gcc_ge_4_0 (struct dwarf2_cu *cu) { - CORE_ADDR low, high; - struct die_info *child = die->child; + const char *cs; + int major, minor; - if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL)) + if (cu->producer == NULL) { - *lowpc = min (*lowpc, low); - *highpc = max (*highpc, high); - } - - /* If the language does not allow nested subprograms (either inside - subprograms or lexical blocks), we're done. */ - if (cu->language != language_ada) - return; + /* For unknown compilers expect their behavior is not compliant. For GCC + this case can also happen for -gdwarf-4 type units supported since + gcc-4.5. */ - /* Check all the children of the given DIE. If it contains nested - subprograms, then check their pc bounds. Likewise, we need to - check lexical blocks as well, as they may also contain subprogram - definitions. */ - while (child && child->tag) - { - if (child->tag == DW_TAG_subprogram - || child->tag == DW_TAG_lexical_block) - dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu); - child = sibling_die (child); + return 0; } -} - -/* Get the low and high pc's represented by the scope DIE, and store - them in *LOWPC and *HIGHPC. If the correct values can't be - determined, set *LOWPC to -1 and *HIGHPC to 0. */ -static void -get_scope_pc_bounds (struct die_info *die, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - struct dwarf2_cu *cu) -{ - CORE_ADDR best_low = (CORE_ADDR) -1; - CORE_ADDR best_high = (CORE_ADDR) 0; - CORE_ADDR current_low, current_high; + /* Skip any identifier after "GNU " - such as "C++" or "Java". */ - if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)) + if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0) { - best_low = current_low; - best_high = current_high; + /* For non-GCC compilers expect their behavior is not compliant. */ + + return 0; } - else + cs = &cu->producer[strlen ("GNU ")]; + while (*cs && !isdigit (*cs)) + cs++; + if (sscanf (cs, "%d.%d", &major, &minor) != 2) { - struct die_info *child = die->child; - - while (child && child->tag) - { - switch (child->tag) { - case DW_TAG_subprogram: - dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu); - break; - case DW_TAG_namespace: - case DW_TAG_module: - /* FIXME: carlton/2004-01-16: Should we do this for - DW_TAG_class_type/DW_TAG_structure_type, too? I think - that current GCC's always emit the DIEs corresponding - to definitions of methods of classes as children of a - DW_TAG_compile_unit or DW_TAG_namespace (as opposed to - the DIEs giving the declarations, which could be - anywhere). But I don't see any reason why the - standards says that they have to be there. */ - get_scope_pc_bounds (child, ¤t_low, ¤t_high, cu); - - if (current_low != ((CORE_ADDR) -1)) - { - best_low = min (best_low, current_low); - best_high = max (best_high, current_high); - } - break; - default: - /* Ignore. */ - break; - } + /* Not recognized as GCC. */ - child = sibling_die (child); - } + return 0; } - *lowpc = best_low; - *highpc = best_high; + return major >= 4; } -/* Record the address ranges for BLOCK, offset by BASEADDR, as given - in DIE. */ +/* Generate full symbol information for PST and CU, whose DIEs have + already been loaded into memory. */ + static void -dwarf2_record_block_ranges (struct die_info *die, struct block *block, - CORE_ADDR baseaddr, struct dwarf2_cu *cu) +process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) { - struct attribute *attr; + struct dwarf2_cu *cu = per_cu->cu; + struct objfile *objfile = per_cu->objfile; + CORE_ADDR lowpc, highpc; + struct symtab *symtab; + struct cleanup *back_to, *delayed_list_cleanup; + CORE_ADDR baseaddr; - attr = dwarf2_attr (die, DW_AT_high_pc, cu); - if (attr) - { - CORE_ADDR high = DW_ADDR (attr); + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - attr = dwarf2_attr (die, DW_AT_low_pc, cu); - if (attr) - { - CORE_ADDR low = DW_ADDR (attr); + buildsym_init (); + back_to = make_cleanup (really_free_pendings, NULL); + delayed_list_cleanup = make_cleanup (free_delayed_list, cu); - record_block_range (block, baseaddr + low, baseaddr + high - 1); - } - } + cu->list_in_scope = &file_symbols; - attr = dwarf2_attr (die, DW_AT_ranges, cu); - if (attr) - { - bfd *obfd = cu->objfile->obfd; + dwarf2_find_base_address (cu->dies, cu); - /* The value of the DW_AT_ranges attribute is the offset of the - address range list in the .debug_ranges section. */ - unsigned long offset = DW_UNSND (attr); - gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset; + /* Do line number decoding in read_file_scope () */ + process_die (cu->dies, cu); - /* For some target architectures, but not others, the - read_address function sign-extends the addresses it returns. - To recognize base address selection entries, we need a - mask. */ - unsigned int addr_size = cu->header.addr_size; - CORE_ADDR base_select_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); + /* Now that we have processed all the DIEs in the CU, all the types + should be complete, and it should now be safe to compute all of the + physnames. */ + compute_delayed_physnames (cu); + do_cleanups (delayed_list_cleanup); - /* The base address, to which the next pair is relative. Note - that this 'base' is a DWARF concept: most entries in a range - list are relative, to reduce the number of relocs against the - debugging information. This is separate from this function's - 'baseaddr' argument, which GDB uses to relocate debugging - information from a shared library based on the address at - which the library was loaded. */ - CORE_ADDR base = cu->base_address; - int base_known = cu->base_known; + /* Some compilers don't define a DW_AT_high_pc attribute for the + compilation unit. If the DW_AT_high_pc is missing, synthesize + it, by scanning the DIE's below the compilation unit. */ + get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu); - gdb_assert (dwarf2_per_objfile->ranges.readin); - if (offset >= dwarf2_per_objfile->ranges.size) - { - complaint (&symfile_complaints, - _("Offset %lu out of bounds for DW_AT_ranges attribute"), - offset); - return; - } + symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile)); - for (;;) - { - unsigned int bytes_read; - CORE_ADDR start, end; + if (symtab != NULL) + { + /* Set symtab language to language from DW_AT_language. If the + compilation is from a C file generated by language preprocessors, do + not set the language if it was already deduced by start_subfile. */ + if (!(cu->language == language_c && symtab->language != language_c)) + symtab->language = cu->language; - start = read_address (obfd, buffer, cu, &bytes_read); - buffer += bytes_read; - end = read_address (obfd, buffer, cu, &bytes_read); - buffer += bytes_read; + /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can + produce DW_AT_location with location lists but it can be possibly + invalid without -fvar-tracking. - /* Did we find the end of the range list? */ - if (start == 0 && end == 0) - break; + For -gdwarf-4 type units LOCATIONS_VALID indication is fortunately not + needed, it would be wrong due to missing DW_AT_producer there. - /* Did we find a base address selection entry? */ - else if ((start & base_select_mask) == base_select_mask) - { - base = end; - base_known = 1; - } + Still one can confuse GDB by using non-standard GCC compilation + options - this waits on GCC PR other/32998 (-frecord-gcc-switches). + */ + if (cu->has_loclist && producer_is_gcc_ge_4_0 (cu)) + symtab->locations_valid = 1; + } - /* We found an ordinary address range. */ - else - { - if (!base_known) - { - complaint (&symfile_complaints, - _("Invalid .debug_ranges data (no base address)")); - return; - } - - record_block_range (block, - baseaddr + base + start, - baseaddr + base + end - 1); - } - } + if (dwarf2_per_objfile->using_index) + per_cu->v.quick->symtab = symtab; + else + { + struct partial_symtab *pst = per_cu->v.psymtab; + pst->symtab = symtab; + pst->readin = 1; } + + do_cleanups (back_to); } -/* Add an aggregate field to the field list. */ +/* Process a die and its children. */ static void -dwarf2_add_field (struct field_info *fip, struct die_info *die, - struct dwarf2_cu *cu) +process_die (struct die_info *die, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct nextfield *new_field; - struct attribute *attr; - struct field *fp; - char *fieldname = ""; + switch (die->tag) + { + case DW_TAG_padding: + break; + case DW_TAG_compile_unit: + read_file_scope (die, cu); + break; + case DW_TAG_type_unit: + read_type_unit_scope (die, cu); + break; + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + read_func_scope (die, cu); + break; + case DW_TAG_lexical_block: + case DW_TAG_try_block: + case DW_TAG_catch_block: + read_lexical_block_scope (die, cu); + break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + process_structure_scope (die, cu); + break; + case DW_TAG_enumeration_type: + process_enumeration_scope (die, cu); + break; - /* Allocate a new field list entry and link it in. */ - new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield)); - make_cleanup (xfree, new_field); - memset (new_field, 0, sizeof (struct nextfield)); + /* These dies have a type, but processing them does not create + a symbol or recurse to process the children. Therefore we can + read them on-demand through read_type_die. */ + case DW_TAG_subroutine_type: + case DW_TAG_set_type: + case DW_TAG_array_type: + case DW_TAG_pointer_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_reference_type: + case DW_TAG_string_type: + break; - if (die->tag == DW_TAG_inheritance) - { - new_field->next = fip->baseclasses; - fip->baseclasses = new_field; - } - else - { - new_field->next = fip->fields; - fip->fields = new_field; + case DW_TAG_base_type: + case DW_TAG_subrange_type: + case DW_TAG_typedef: + /* Add a typedef symbol for the type definition, if it has a + DW_AT_name. */ + new_symbol (die, read_type_die (die, cu), cu); + break; + case DW_TAG_common_block: + read_common_block (die, cu); + break; + case DW_TAG_common_inclusion: + break; + case DW_TAG_namespace: + processing_has_namespace_info = 1; + read_namespace (die, cu); + break; + case DW_TAG_module: + processing_has_namespace_info = 1; + read_module (die, cu); + break; + case DW_TAG_imported_declaration: + case DW_TAG_imported_module: + processing_has_namespace_info = 1; + if (die->child != NULL && (die->tag == DW_TAG_imported_declaration + || cu->language != language_fortran)) + complaint (&symfile_complaints, _("Tag '%s' has unexpected children"), + dwarf_tag_name (die->tag)); + read_import_statement (die, cu); + break; + default: + new_symbol (die, NULL, cu); + break; } - fip->nfields++; - - /* Handle accessibility and virtuality of field. - The default accessibility for members is public, the default - accessibility for inheritance is private. */ - if (die->tag != DW_TAG_inheritance) - new_field->accessibility = DW_ACCESS_public; - else - new_field->accessibility = DW_ACCESS_private; - new_field->virtuality = DW_VIRTUALITY_none; +} - attr = dwarf2_attr (die, DW_AT_accessibility, cu); - if (attr) - new_field->accessibility = DW_UNSND (attr); - if (new_field->accessibility != DW_ACCESS_public) - fip->non_public_fields = 1; - attr = dwarf2_attr (die, DW_AT_virtuality, cu); - if (attr) - new_field->virtuality = DW_UNSND (attr); +/* A helper function for dwarf2_compute_name which determines whether DIE + needs to have the name of the scope prepended to the name listed in the + die. */ - fp = &new_field->field; +static int +die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; - if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu)) + switch (die->tag) { - /* Data member other than a C++ static data member. */ - - /* Get type of field. */ - fp->type = die_type (die, cu); + case DW_TAG_namespace: + case DW_TAG_typedef: + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + case DW_TAG_enumerator: + case DW_TAG_subprogram: + case DW_TAG_member: + return 1; - SET_FIELD_BITPOS (*fp, 0); + case DW_TAG_variable: + case DW_TAG_constant: + /* We only need to prefix "globally" visible variables. These include + any variable marked with DW_AT_external or any variable that + lives in a namespace. [Variables in anonymous namespaces + require prefixing, but they are not DW_AT_external.] */ - /* Get bit size of field (zero if none). */ - attr = dwarf2_attr (die, DW_AT_bit_size, cu); - if (attr) - { - FIELD_BITSIZE (*fp) = DW_UNSND (attr); - } - else + if (dwarf2_attr (die, DW_AT_specification, cu)) { - FIELD_BITSIZE (*fp) = 0; + struct dwarf2_cu *spec_cu = cu; + + return die_needs_namespace (die_specification (die, &spec_cu), + spec_cu); } - /* Get bit offset of field. */ - attr = dwarf2_attr (die, DW_AT_data_member_location, cu); - if (attr) - { - int byte_offset = 0; + attr = dwarf2_attr (die, DW_AT_external, cu); + if (attr == NULL && die->parent->tag != DW_TAG_namespace + && die->parent->tag != DW_TAG_module) + return 0; + /* A variable in a lexical block of some kind does not need a + namespace, even though in C++ such variables may be external + and have a mangled name. */ + if (die->parent->tag == DW_TAG_lexical_block + || die->parent->tag == DW_TAG_try_block + || die->parent->tag == DW_TAG_catch_block + || die->parent->tag == DW_TAG_subprogram) + return 0; + return 1; - if (attr_form_is_section_offset (attr)) - dwarf2_complex_location_expr_complaint (); - else if (attr_form_is_constant (attr)) - byte_offset = dwarf2_get_attr_constant_value (attr, 0); - else if (attr_form_is_block (attr)) - byte_offset = decode_locdesc (DW_BLOCK (attr), cu); - else - dwarf2_complex_location_expr_complaint (); + default: + return 0; + } +} - SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte); - } - attr = dwarf2_attr (die, DW_AT_bit_offset, cu); - if (attr) - { - if (gdbarch_bits_big_endian (gdbarch)) - { - /* For big endian bits, the DW_AT_bit_offset gives the - additional bit offset from the MSB of the containing - anonymous object to the MSB of the field. We don't - have to do anything special since we don't need to - know the size of the anonymous object. */ - FIELD_BITPOS (*fp) += DW_UNSND (attr); - } - else - { - /* For little endian bits, compute the bit offset to the - MSB of the anonymous object, subtract off the number of - bits from the MSB of the field to the MSB of the - object, and then subtract off the number of bits of - the field itself. The result is the bit offset of - the LSB of the field. */ - int anonymous_size; - int bit_offset = DW_UNSND (attr); +/* Retrieve the last character from a mem_file. */ - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - { - /* The size of the anonymous object containing - the bit field is explicit, so use the - indicated size (in bytes). */ - anonymous_size = DW_UNSND (attr); - } - else - { - /* The size of the anonymous object containing - the bit field must be inferred from the type - attribute of the data member containing the - bit field. */ - anonymous_size = TYPE_LENGTH (fp->type); - } - FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte - - bit_offset - FIELD_BITSIZE (*fp); - } - } +static void +do_ui_file_peek_last (void *object, const char *buffer, long length) +{ + char *last_char_p = (char *) object; - /* Get name of field. */ - fieldname = dwarf2_name (die, cu); - if (fieldname == NULL) - fieldname = ""; + if (length > 0) + *last_char_p = buffer[length - 1]; +} - /* The name is already allocated along with this objfile, so we don't - need to duplicate it for the type. */ - fp->name = fieldname; +/* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero, + compute the physname for the object, which include a method's + formal parameters (C++/Java) and return type (Java). - /* Change accessibility for artificial fields (e.g. virtual table - pointer or virtual base class pointer) to private. */ - if (dwarf2_attr (die, DW_AT_artificial, cu)) - { - FIELD_ARTIFICIAL (*fp) = 1; - new_field->accessibility = DW_ACCESS_private; - fip->non_public_fields = 1; - } - } - else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable) - { - /* C++ static member. */ - - /* NOTE: carlton/2002-11-05: It should be a DW_TAG_member that - is a declaration, but all versions of G++ as of this writing - (so through at least 3.2.1) incorrectly generate - DW_TAG_variable tags. */ - - char *physname; + For Ada, return the DIE's linkage name rather than the fully qualified + name. PHYSNAME is ignored.. - /* Get name of field. */ - fieldname = dwarf2_name (die, cu); - if (fieldname == NULL) - return; + The result is allocated on the objfile_obstack and canonicalized. */ - attr = dwarf2_attr (die, DW_AT_const_value, cu); - if (attr - /* Only create a symbol if this is an external value. - new_symbol checks this and puts the value in the global symbol - table, which we want. If it is not external, new_symbol - will try to put the value in cu->list_in_scope which is wrong. */ - && dwarf2_flag_true_p (die, DW_AT_external, cu)) - { - /* A static const member, not much different than an enum as far as - we're concerned, except that we can support more types. */ - new_symbol (die, NULL, cu); - } +static const char * +dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu, + int physname) +{ + if (name == NULL) + name = dwarf2_name (die, cu); - /* Get physical name. */ - physname = (char *) dwarf2_physname (fieldname, die, cu); + /* For Fortran GDB prefers DW_AT_*linkage_name if present but otherwise + compute it by typename_concat inside GDB. */ + if (cu->language == language_ada + || (cu->language == language_fortran && physname)) + { + /* For Ada unit, we prefer the linkage name over the name, as + the former contains the exported name, which the user expects + to be able to reference. Ideally, we want the user to be able + to reference this entity using either natural or linkage name, + but we haven't started looking at this enhancement yet. */ + struct attribute *attr; - /* The name is already allocated along with this objfile, so we don't - need to duplicate it for the type. */ - SET_FIELD_PHYSNAME (*fp, physname ? physname : ""); - FIELD_TYPE (*fp) = die_type (die, cu); - FIELD_NAME (*fp) = fieldname; + attr = dwarf2_attr (die, DW_AT_linkage_name, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); } - else if (die->tag == DW_TAG_inheritance) + + /* These are the only languages we know how to qualify names in. */ + if (name != NULL + && (cu->language == language_cplus || cu->language == language_java + || cu->language == language_fortran)) { - /* C++ base class field. */ - attr = dwarf2_attr (die, DW_AT_data_member_location, cu); - if (attr) + if (die_needs_namespace (die, cu)) { - int byte_offset = 0; + long length; + char *prefix; + struct ui_file *buf; - if (attr_form_is_section_offset (attr)) - dwarf2_complex_location_expr_complaint (); - else if (attr_form_is_constant (attr)) - byte_offset = dwarf2_get_attr_constant_value (attr, 0); - else if (attr_form_is_block (attr)) - byte_offset = decode_locdesc (DW_BLOCK (attr), cu); + prefix = determine_prefix (die, cu); + buf = mem_fileopen (); + if (*prefix != '\0') + { + char *prefixed_name = typename_concat (NULL, prefix, name, + physname, cu); + + fputs_unfiltered (prefixed_name, buf); + xfree (prefixed_name); + } else - dwarf2_complex_location_expr_complaint (); + fputs_unfiltered (name, buf); + + /* Template parameters may be specified in the DIE's DW_AT_name, or + as children with DW_TAG_template_type_param or + DW_TAG_value_type_param. If the latter, add them to the name + here. If the name already has template parameters, then + skip this step; some versions of GCC emit both, and + it is more efficient to use the pre-computed name. + + Something to keep in mind about this process: it is very + unlikely, or in some cases downright impossible, to produce + something that will match the mangled name of a function. + If the definition of the function has the same debug info, + we should be able to match up with it anyway. But fallbacks + using the minimal symbol, for instance to find a method + implemented in a stripped copy of libstdc++, will not work. + If we do not have debug info for the definition, we will have to + match them up some other way. + + When we do name matching there is a related problem with function + templates; two instantiated function templates are allowed to + differ only by their return types, which we do not add here. */ + + if (cu->language == language_cplus && strchr (name, '<') == NULL) + { + struct attribute *attr; + struct die_info *child; + int first = 1; - SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte); - } - FIELD_BITSIZE (*fp) = 0; - FIELD_TYPE (*fp) = die_type (die, cu); - FIELD_NAME (*fp) = type_name_no_tag (fp->type); - fip->nbaseclasses++; - } -} + die->building_fullname = 1; -/* Add a typedef defined in the scope of the FIP's class. */ + for (child = die->child; child != NULL; child = child->sibling) + { + struct type *type; + long value; + gdb_byte *bytes; + struct dwarf2_locexpr_baton *baton; + struct value *v; -static void -dwarf2_add_typedef (struct field_info *fip, struct die_info *die, - struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct typedef_field_list *new_field; - struct attribute *attr; - struct typedef_field *fp; - char *fieldname = ""; + if (child->tag != DW_TAG_template_type_param + && child->tag != DW_TAG_template_value_param) + continue; - /* Allocate a new field list entry and link it in. */ - new_field = xzalloc (sizeof (*new_field)); - make_cleanup (xfree, new_field); + if (first) + { + fputs_unfiltered ("<", buf); + first = 0; + } + else + fputs_unfiltered (", ", buf); - gdb_assert (die->tag == DW_TAG_typedef); + attr = dwarf2_attr (child, DW_AT_type, cu); + if (attr == NULL) + { + complaint (&symfile_complaints, + _("template parameter missing DW_AT_type")); + fputs_unfiltered ("UNKNOWN_TYPE", buf); + continue; + } + type = die_type (child, cu); - fp = &new_field->field; + if (child->tag == DW_TAG_template_type_param) + { + c_print_type (type, "", buf, -1, 0); + continue; + } - /* Get name of field. */ - fp->name = dwarf2_name (die, cu); - if (fp->name == NULL) - return; + attr = dwarf2_attr (child, DW_AT_const_value, cu); + if (attr == NULL) + { + complaint (&symfile_complaints, + _("template parameter missing " + "DW_AT_const_value")); + fputs_unfiltered ("UNKNOWN_VALUE", buf); + continue; + } - fp->type = read_type_die (die, cu); + dwarf2_const_value_attr (attr, type, name, + &cu->comp_unit_obstack, cu, + &value, &bytes, &baton); - new_field->next = fip->typedef_field_list; - fip->typedef_field_list = new_field; - fip->typedef_field_list_count++; -} + if (TYPE_NOSIGN (type)) + /* GDB prints characters as NUMBER 'CHAR'. If that's + changed, this can use value_print instead. */ + c_printchar (value, type, buf); + else + { + struct value_print_options opts; + + if (baton != NULL) + v = dwarf2_evaluate_loc_desc (type, NULL, + baton->data, + baton->size, + baton->per_cu); + else if (bytes != NULL) + { + v = allocate_value (type); + memcpy (value_contents_writeable (v), bytes, + TYPE_LENGTH (type)); + } + else + v = value_from_longest (type, value); + + /* Specify decimal so that we do not depend on + the radix. */ + get_formatted_print_options (&opts, 'd'); + opts.raw = 1; + value_print (v, buf, &opts); + release_value (v); + value_free (v); + } + } -/* Create the vector of fields, and attach it to the type. */ + die->building_fullname = 0; -static void -dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type, - struct dwarf2_cu *cu) -{ - int nfields = fip->nfields; + if (!first) + { + /* Close the argument list, with a space if necessary + (nested templates). */ + char last_char = '\0'; + ui_file_put (buf, do_ui_file_peek_last, &last_char); + if (last_char == '>') + fputs_unfiltered (" >", buf); + else + fputs_unfiltered (">", buf); + } + } - /* Record the field count, allocate space for the array of fields, - and create blank accessibility bitfields if necessary. */ - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) - TYPE_ALLOC (type, sizeof (struct field) * nfields); - memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); + /* For Java and C++ methods, append formal parameter type + information, if PHYSNAME. */ - if (fip->non_public_fields && cu->language != language_ada) - { - ALLOCATE_CPLUS_STRUCT_TYPE (type); + if (physname && die->tag == DW_TAG_subprogram + && (cu->language == language_cplus + || cu->language == language_java)) + { + struct type *type = read_type_die (die, cu); - TYPE_FIELD_PRIVATE_BITS (type) = - (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); - B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); + c_type_print_args (type, buf, 1, cu->language); - TYPE_FIELD_PROTECTED_BITS (type) = - (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); - B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); + if (cu->language == language_java) + { + /* For java, we must append the return type to method + names. */ + if (die->tag == DW_TAG_subprogram) + java_print_type (TYPE_TARGET_TYPE (type), "", buf, + 0, 0); + } + else if (cu->language == language_cplus) + { + /* Assume that an artificial first parameter is + "this", but do not crash if it is not. RealView + marks unnamed (and thus unused) parameters as + artificial; there is no way to differentiate + the two cases. */ + if (TYPE_NFIELDS (type) > 0 + && TYPE_FIELD_ARTIFICIAL (type, 0) + && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR + && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, + 0)))) + fputs_unfiltered (" const", buf); + } + } - TYPE_FIELD_IGNORE_BITS (type) = - (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); - B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); - } + name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack, + &length); + ui_file_delete (buf); - /* If the type has baseclasses, allocate and clear a bit vector for - TYPE_FIELD_VIRTUAL_BITS. */ - if (fip->nbaseclasses && cu->language != language_ada) - { - int num_bytes = B_BYTES (fip->nbaseclasses); - unsigned char *pointer; + if (cu->language == language_cplus) + { + char *cname + = dwarf2_canonicalize_name (name, cu, + &cu->objfile->objfile_obstack); - ALLOCATE_CPLUS_STRUCT_TYPE (type); - pointer = TYPE_ALLOC (type, num_bytes); - TYPE_FIELD_VIRTUAL_BITS (type) = pointer; - B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses); - TYPE_N_BASECLASSES (type) = fip->nbaseclasses; + if (cname != NULL) + name = cname; + } + } } - /* Copy the saved-up fields into the field vector. Start from the head - of the list, adding to the tail of the field array, so that they end - up in the same order in the array in which they were added to the list. */ - while (nfields-- > 0) - { - struct nextfield *fieldp; + return name; +} - if (fip->fields) +/* Return the fully qualified name of DIE, based on its DW_AT_name. + If scope qualifiers are appropriate they will be added. The result + will be allocated on the objfile_obstack, or NULL if the DIE does + not have a name. NAME may either be from a previous call to + dwarf2_name or NULL. + + The output string will be canonicalized (if C++/Java). */ + +static const char * +dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu) +{ + return dwarf2_compute_name (name, die, cu, 0); +} + +/* Construct a physname for the given DIE in CU. NAME may either be + from a previous call to dwarf2_name or NULL. The result will be + allocated on the objfile_objstack or NULL if the DIE does not have a + name. + + The output string will be canonicalized (if C++/Java). */ + +static const char * +dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; + const char *retval, *mangled = NULL, *canon = NULL; + struct cleanup *back_to; + int need_copy = 1; + + /* In this case dwarf2_compute_name is just a shortcut not building anything + on its own. */ + if (!die_needs_namespace (die, cu)) + return dwarf2_compute_name (name, die, cu, 1); + + back_to = make_cleanup (null_cleanup, NULL); + + attr = dwarf2_attr (die, DW_AT_linkage_name, cu); + if (!attr) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + + /* DW_AT_linkage_name is missing in some cases - depend on what GDB + has computed. */ + if (attr && DW_STRING (attr)) + { + char *demangled; + + mangled = DW_STRING (attr); + + /* Use DMGL_RET_DROP for C++ template functions to suppress their return + type. It is easier for GDB users to search for such functions as + `name(params)' than `long name(params)'. In such case the minimal + symbol names do not match the full symbol names but for template + functions there is never a need to look up their definition from their + declaration so the only disadvantage remains the minimal symbol + variant `long name(params)' does not have the proper inferior type. + */ + + demangled = cplus_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI + | (cu->language == language_java + ? DMGL_JAVA | DMGL_RET_POSTFIX + : DMGL_RET_DROP))); + if (demangled) { - fieldp = fip->fields; - fip->fields = fieldp->next; + make_cleanup (xfree, demangled); + canon = demangled; } else { - fieldp = fip->baseclasses; - fip->baseclasses = fieldp->next; + canon = mangled; + need_copy = 0; } + } - TYPE_FIELD (type, nfields) = fieldp->field; - switch (fieldp->accessibility) + if (canon == NULL || check_physname) + { + const char *physname = dwarf2_compute_name (name, die, cu, 1); + + if (canon != NULL && strcmp (physname, canon) != 0) { - case DW_ACCESS_private: - if (cu->language != language_ada) - SET_TYPE_FIELD_PRIVATE (type, nfields); - break; + /* It may not mean a bug in GDB. The compiler could also + compute DW_AT_linkage_name incorrectly. But in such case + GDB would need to be bug-to-bug compatible. */ - case DW_ACCESS_protected: - if (cu->language != language_ada) - SET_TYPE_FIELD_PROTECTED (type, nfields); - break; + complaint (&symfile_complaints, + _("Computed physname <%s> does not match demangled <%s> " + "(from linkage <%s>) - DIE at 0x%x [in module %s]"), + physname, canon, mangled, die->offset, cu->objfile->name); - case DW_ACCESS_public: - break; + /* Prefer DW_AT_linkage_name (in the CANON form) - when it + is available here - over computed PHYSNAME. It is safer + against both buggy GDB and buggy compilers. */ - default: - /* Unknown accessibility. Complain and treat it as public. */ - { - complaint (&symfile_complaints, _("unsupported accessibility %d"), - fieldp->accessibility); - } - break; + retval = canon; } - if (nfields < fip->nbaseclasses) + else { - switch (fieldp->virtuality) - { - case DW_VIRTUALITY_virtual: - case DW_VIRTUALITY_pure_virtual: - if (cu->language == language_ada) - error ("unexpected virtuality in component of Ada type"); - SET_TYPE_FIELD_VIRTUAL (type, nfields); - break; - } + retval = physname; + need_copy = 0; } } + else + retval = canon; + + if (need_copy) + retval = obsavestring (retval, strlen (retval), + &cu->objfile->objfile_obstack); + + do_cleanups (back_to); + return retval; } -/* Add a member function to the proper fieldlist. */ +/* Read the import statement specified by the given die and record it. */ static void -dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, - struct type *type, struct dwarf2_cu *cu) +read_import_statement (struct die_info *die, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - struct attribute *attr; - struct fnfieldlist *flp; - int i; - struct fn_field *fnp; - char *fieldname; - char *physname; - struct nextfnfield *new_fnfield; - struct type *this_type; - - if (cu->language == language_ada) - error ("unexpected member function in Ada type"); - - /* Get name of member function. */ - fieldname = dwarf2_name (die, cu); - if (fieldname == NULL) - return; + struct attribute *import_attr; + struct die_info *imported_die; + struct dwarf2_cu *imported_cu; + const char *imported_name; + const char *imported_name_prefix; + const char *canonical_name; + const char *import_alias; + const char *imported_declaration = NULL; + const char *import_prefix; - /* Get the mangled name. */ - physname = (char *) dwarf2_physname (fieldname, die, cu); + char *temp; - /* Look up member function name in fieldlist. */ - for (i = 0; i < fip->nfnfields; i++) + import_attr = dwarf2_attr (die, DW_AT_import, cu); + if (import_attr == NULL) { - if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) - break; + complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"), + dwarf_tag_name (die->tag)); + return; } - /* Create new list element if necessary. */ - if (i < fip->nfnfields) - flp = &fip->fnfieldlists[i]; - else + imported_cu = cu; + imported_die = follow_die_ref_or_sig (die, import_attr, &imported_cu); + imported_name = dwarf2_name (imported_die, imported_cu); + if (imported_name == NULL) { - if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0) - { - fip->fnfieldlists = (struct fnfieldlist *) - xrealloc (fip->fnfieldlists, - (fip->nfnfields + DW_FIELD_ALLOC_CHUNK) - * sizeof (struct fnfieldlist)); - if (fip->nfnfields == 0) - make_cleanup (free_current_contents, &fip->fnfieldlists); - } - flp = &fip->fnfieldlists[fip->nfnfields]; - flp->name = fieldname; - flp->length = 0; - flp->head = NULL; - fip->nfnfields++; + /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524 + + The import in the following code: + namespace A + { + typedef int B; + } + + int main () + { + using A::B; + B b; + return b; + } + + ... + <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration) + <52> DW_AT_decl_file : 1 + <53> DW_AT_decl_line : 6 + <54> DW_AT_import : <0x75> + <2><58>: Abbrev Number: 4 (DW_TAG_typedef) + <59> DW_AT_name : B + <5b> DW_AT_decl_file : 1 + <5c> DW_AT_decl_line : 2 + <5d> DW_AT_type : <0x6e> + ... + <1><75>: Abbrev Number: 7 (DW_TAG_base_type) + <76> DW_AT_byte_size : 4 + <77> DW_AT_encoding : 5 (signed) + + imports the wrong die ( 0x75 instead of 0x58 ). + This case will be ignored until the gcc bug is fixed. */ + return; } - /* Create a new member function field and chain it to the field list - entry. */ - new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield)); - make_cleanup (xfree, new_fnfield); - memset (new_fnfield, 0, sizeof (struct nextfnfield)); - new_fnfield->next = flp->head; - flp->head = new_fnfield; - flp->length++; + /* Figure out the local name after import. */ + import_alias = dwarf2_name (die, cu); - /* Fill in the member function field info. */ - fnp = &new_fnfield->fnfield; - /* The name is already allocated along with this objfile, so we don't - need to duplicate it for the type. */ - fnp->physname = physname ? physname : ""; - fnp->type = alloc_type (objfile); - this_type = read_type_die (die, cu); - if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) - { - int nparams = TYPE_NFIELDS (this_type); + /* Figure out where the statement is being imported to. */ + import_prefix = determine_prefix (die, cu); - /* TYPE is the domain of this method, and THIS_TYPE is the type - of the method itself (TYPE_CODE_METHOD). */ - smash_to_method_type (fnp->type, type, - TYPE_TARGET_TYPE (this_type), - TYPE_FIELDS (this_type), - TYPE_NFIELDS (this_type), - TYPE_VARARGS (this_type)); + /* Figure out what the scope of the imported die is and prepend it + to the name of the imported die. */ + imported_name_prefix = determine_prefix (imported_die, imported_cu); - /* Handle static member functions. - Dwarf2 has no clean way to discern C++ static and non-static - member functions. G++ helps GDB by marking the first - parameter for non-static member functions (which is the - this pointer) as artificial. We obtain this information - from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */ - if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0) - fnp->voffset = VOFFSET_STATIC; + if (imported_die->tag != DW_TAG_namespace + && imported_die->tag != DW_TAG_module) + { + imported_declaration = imported_name; + canonical_name = imported_name_prefix; + } + else if (strlen (imported_name_prefix) > 0) + { + temp = alloca (strlen (imported_name_prefix) + + 2 + strlen (imported_name) + 1); + strcpy (temp, imported_name_prefix); + strcat (temp, "::"); + strcat (temp, imported_name); + canonical_name = temp; } else - complaint (&symfile_complaints, _("member function type missing for '%s'"), - physname); + canonical_name = imported_name; - /* Get fcontext from DW_AT_containing_type if present. */ - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) - fnp->fcontext = die_containing_type (die, cu); + cp_add_using_directive (import_prefix, + canonical_name, + import_alias, + imported_declaration, + &cu->objfile->objfile_obstack); +} - /* dwarf2 doesn't have stubbed physical names, so the setting of is_const - and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ +static void +initialize_cu_func_list (struct dwarf2_cu *cu) +{ + cu->first_fn = cu->last_fn = cu->cached_fn = NULL; +} - /* Get accessibility. */ - attr = dwarf2_attr (die, DW_AT_accessibility, cu); +/* Cleanup function for read_file_scope. */ + +static void +free_cu_line_header (void *arg) +{ + struct dwarf2_cu *cu = arg; + + free_line_header (cu->line_header); + cu->line_header = NULL; +} + +static void +find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu, + char **name, char **comp_dir) +{ + struct attribute *attr; + + *name = NULL; + *comp_dir = NULL; + + /* Find the filename. Do not use dwarf2_name here, since the filename + is not a source language identifier. */ + attr = dwarf2_attr (die, DW_AT_name, cu); if (attr) { - switch (DW_UNSND (attr)) - { - case DW_ACCESS_private: - fnp->is_private = 1; - break; - case DW_ACCESS_protected: - fnp->is_protected = 1; - break; - } + *name = DW_STRING (attr); } - /* Check for artificial methods. */ - attr = dwarf2_attr (die, DW_AT_artificial, cu); - if (attr && DW_UNSND (attr) != 0) - fnp->is_artificial = 1; - - /* Get index in virtual function table if it is a virtual member - function. For older versions of GCC, this is an offset in the - appropriate virtual table, as specified by DW_AT_containing_type. - For everyone else, it is an expression to be evaluated relative - to the object address. */ - - attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu); + attr = dwarf2_attr (die, DW_AT_comp_dir, cu); if (attr) + *comp_dir = DW_STRING (attr); + else if (*name != NULL && IS_ABSOLUTE_PATH (*name)) { - if (attr_form_is_block (attr) && DW_BLOCK (attr)->size > 0) - { - if (DW_BLOCK (attr)->data[0] == DW_OP_constu) - { - /* Old-style GCC. */ - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; - } - else if (DW_BLOCK (attr)->data[0] == DW_OP_deref - || (DW_BLOCK (attr)->size > 1 - && DW_BLOCK (attr)->data[0] == DW_OP_deref_size - && DW_BLOCK (attr)->data[1] == cu->header.addr_size)) - { - struct dwarf_block blk; - int offset; + *comp_dir = ldirname (*name); + if (*comp_dir != NULL) + make_cleanup (xfree, *comp_dir); + } + if (*comp_dir != NULL) + { + /* Irix 6.2 native cc prepends .: to the compilation + directory, get rid of it. */ + char *cp = strchr (*comp_dir, ':'); - offset = (DW_BLOCK (attr)->data[0] == DW_OP_deref - ? 1 : 2); - blk.size = DW_BLOCK (attr)->size - offset; - blk.data = DW_BLOCK (attr)->data + offset; - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu); - if ((fnp->voffset % cu->header.addr_size) != 0) - dwarf2_complex_location_expr_complaint (); - else - fnp->voffset /= cu->header.addr_size; - fnp->voffset += 2; - } - else - dwarf2_complex_location_expr_complaint (); + if (cp && cp != *comp_dir && cp[-1] == '.' && cp[1] == '/') + *comp_dir = cp + 1; + } - if (!fnp->fcontext) - fnp->fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0)); - } - else if (attr_form_is_section_offset (attr)) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location", - fieldname); - } - } - else - { - attr = dwarf2_attr (die, DW_AT_virtuality, cu); - if (attr && DW_UNSND (attr)) - { - /* GCC does this, as of 2008-08-25; PR debug/37237. */ - complaint (&symfile_complaints, - _("Member function \"%s\" (offset %d) is virtual but the vtable offset is not specified"), - fieldname, die->offset); - ALLOCATE_CPLUS_STRUCT_TYPE (type); - TYPE_CPLUS_DYNAMIC (type) = 1; - } - } + if (*name == NULL) + *name = ""; } -/* Create the vector of member function fields, and attach it to the type. */ +/* Process DW_TAG_compile_unit. */ static void -dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type, - struct dwarf2_cu *cu) +read_file_scope (struct die_info *die, struct dwarf2_cu *cu) { - struct fnfieldlist *flp; - int total_length = 0; - int i; + struct objfile *objfile = cu->objfile; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); + CORE_ADDR lowpc = ((CORE_ADDR) -1); + CORE_ADDR highpc = ((CORE_ADDR) 0); + struct attribute *attr; + char *name = NULL; + char *comp_dir = NULL; + struct die_info *child_die; + bfd *abfd = objfile->obfd; + struct line_header *line_header = 0; + CORE_ADDR baseaddr; - if (cu->language == language_ada) - error ("unexpected member functions in Ada type"); + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - ALLOCATE_CPLUS_STRUCT_TYPE (type); - TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *) - TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields); + get_scope_pc_bounds (die, &lowpc, &highpc, cu); - for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++) - { - struct nextfnfield *nfp = flp->head; - struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i); - int k; + /* If we didn't find a lowpc, set it to highpc to avoid complaints + from finish_block. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + lowpc += baseaddr; + highpc += baseaddr; - TYPE_FN_FIELDLIST_NAME (type, i) = flp->name; - TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length; - fn_flp->fn_fields = (struct fn_field *) - TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length); - for (k = flp->length; (k--, nfp); nfp = nfp->next) - fn_flp->fn_fields[k] = nfp->fnfield; + find_file_and_directory (die, cu, &name, &comp_dir); - total_length += flp->length; + attr = dwarf2_attr (die, DW_AT_language, cu); + if (attr) + { + set_cu_language (DW_UNSND (attr), cu); } - TYPE_NFN_FIELDS (type) = fip->nfnfields; - TYPE_NFN_FIELDS_TOTAL (type) = total_length; -} - -/* Returns non-zero if NAME is the name of a vtable member in CU's - language, zero otherwise. */ -static int -is_vtable_name (const char *name, struct dwarf2_cu *cu) -{ - static const char vptr[] = "_vptr"; - static const char vtable[] = "vtable"; - - /* Look for the C++ and Java forms of the vtable. */ - if ((cu->language == language_java - && strncmp (name, vtable, sizeof (vtable) - 1) == 0) - || (strncmp (name, vptr, sizeof (vptr) - 1) == 0 - && is_cplus_marker (name[sizeof (vptr) - 1]))) - return 1; + attr = dwarf2_attr (die, DW_AT_producer, cu); + if (attr) + cu->producer = DW_STRING (attr); - return 0; -} + /* The XLCL doesn't generate DW_LANG_OpenCL because this attribute is not + standardised yet. As a workaround for the language detection we fall + back to the DW_AT_producer string. */ + if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL") != NULL) + cu->language = language_opencl; -/* GCC outputs unnamed structures that are really pointers to member - functions, with the ABI-specified layout. If TYPE describes - such a structure, smash it into a member function type. + /* We assume that we're processing GCC output. */ + processing_gcc_compilation = 2; - GCC shouldn't do this; it should just output pointer to member DIEs. - This is GCC PR debug/28767. */ + processing_has_namespace_info = 0; -static void -quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile) -{ - struct type *pfn_type, *domain_type, *new_type; + start_symtab (name, comp_dir, lowpc); + record_debugformat ("DWARF 2"); + record_producer (cu->producer); - /* Check for a structure with no name and two children. */ - if (TYPE_CODE (type) != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 2) - return; + initialize_cu_func_list (cu); - /* Check for __pfn and __delta members. */ - if (TYPE_FIELD_NAME (type, 0) == NULL - || strcmp (TYPE_FIELD_NAME (type, 0), "__pfn") != 0 - || TYPE_FIELD_NAME (type, 1) == NULL - || strcmp (TYPE_FIELD_NAME (type, 1), "__delta") != 0) - return; + /* Decode line number information if present. We do this before + processing child DIEs, so that the line header table is available + for DW_AT_decl_file. */ + attr = dwarf2_attr (die, DW_AT_stmt_list, cu); + if (attr) + { + unsigned int line_offset = DW_UNSND (attr); + line_header = dwarf_decode_line_header (line_offset, abfd, cu); + if (line_header) + { + cu->line_header = line_header; + make_cleanup (free_cu_line_header, cu); + dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL); + } + } - /* Find the type of the method. */ - pfn_type = TYPE_FIELD_TYPE (type, 0); - if (pfn_type == NULL - || TYPE_CODE (pfn_type) != TYPE_CODE_PTR - || TYPE_CODE (TYPE_TARGET_TYPE (pfn_type)) != TYPE_CODE_FUNC) - return; + /* Process all dies in compilation unit. */ + if (die->child != NULL) + { + child_die = die->child; + while (child_die && child_die->tag) + { + process_die (child_die, cu); + child_die = sibling_die (child_die); + } + } - /* Look for the "this" argument. */ - pfn_type = TYPE_TARGET_TYPE (pfn_type); - if (TYPE_NFIELDS (pfn_type) == 0 - /* || TYPE_FIELD_TYPE (pfn_type, 0) == NULL */ - || TYPE_CODE (TYPE_FIELD_TYPE (pfn_type, 0)) != TYPE_CODE_PTR) - return; + /* Decode macro information, if present. Dwarf 2 macro information + refers to information in the line number info statement program + header, so we can only read it if we've read the header + successfully. */ + attr = dwarf2_attr (die, DW_AT_macro_info, cu); + if (attr && line_header) + { + unsigned int macro_offset = DW_UNSND (attr); - domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0)); - new_type = alloc_type (objfile); - smash_to_method_type (new_type, domain_type, TYPE_TARGET_TYPE (pfn_type), - TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), - TYPE_VARARGS (pfn_type)); - smash_to_methodptr_type (type, new_type); + dwarf_decode_macros (line_header, macro_offset, + comp_dir, abfd, cu); + } + do_cleanups (back_to); } -/* Called when we find the DIE that starts a structure or union scope - (definition) to process all dies that define the members of the - structure or union. - - NOTE: we need to call struct_type regardless of whether or not the - DIE has an at_name attribute, since it might be an anonymous - structure or union. This gets the type entered into our set of - user defined types. - - However, if the structure is incomplete (an opaque struct/union) - then suppress creating a symbol table entry for it since gdb only - wants to find the one with the complete definition. Note that if - it is complete, we just call new_symbol, which does it's own - checking about whether the struct/union is anonymous or not (and - suppresses creating a symbol table entry itself). */ +/* Process DW_TAG_type_unit. + For TUs we want to skip the first top level sibling if it's not the + actual type being defined by this TU. In this case the first top + level sibling is there to provide context only. */ -static struct type * -read_structure_type (struct die_info *die, struct dwarf2_cu *cu) +static void +read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; - struct type *type; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); + CORE_ADDR lowpc; struct attribute *attr; - char *name; - struct cleanup *back_to; + char *name = NULL; + char *comp_dir = NULL; + struct die_info *child_die; + bfd *abfd = objfile->obfd; - /* If the definition of this type lives in .debug_types, read that type. - Don't follow DW_AT_specification though, that will take us back up - the chain and we want to go down. */ - attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); + /* start_symtab needs a low pc, but we don't really have one. + Do what read_file_scope would do in the absence of such info. */ + lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + /* Find the filename. Do not use dwarf2_name here, since the filename + is not a source language identifier. */ + attr = dwarf2_attr (die, DW_AT_name, cu); if (attr) - { - struct dwarf2_cu *type_cu = cu; - struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); + name = DW_STRING (attr); - /* We could just recurse on read_structure_type, but we need to call - get_die_type to ensure only one type for this DIE is created. - This is important, for example, because for c++ classes we need - TYPE_NAME set which is only done by new_symbol. Blech. */ - type = read_type_die (type_die, type_cu); - return set_die_type (die, type, cu); + attr = dwarf2_attr (die, DW_AT_comp_dir, cu); + if (attr) + comp_dir = DW_STRING (attr); + else if (name != NULL && IS_ABSOLUTE_PATH (name)) + { + comp_dir = ldirname (name); + if (comp_dir != NULL) + make_cleanup (xfree, comp_dir); } - back_to = make_cleanup (null_cleanup, 0); + if (name == NULL) + name = ""; - type = alloc_type (objfile); - INIT_CPLUS_SPECIFIC (type); + attr = dwarf2_attr (die, DW_AT_language, cu); + if (attr) + set_cu_language (DW_UNSND (attr), cu); - name = dwarf2_name (die, cu); - if (name != NULL) - { - if (cu->language == language_cplus - || cu->language == language_java) - { - TYPE_TAG_NAME (type) = (char *) dwarf2_full_name (name, die, cu); - if (die->tag == DW_TAG_structure_type - || die->tag == DW_TAG_class_type) - TYPE_NAME (type) = TYPE_TAG_NAME (type); - } - else - { - /* The name is already allocated along with this objfile, so - we don't need to duplicate it for the type. */ - TYPE_TAG_NAME (type) = (char *) name; - if (die->tag == DW_TAG_class_type) - TYPE_NAME (type) = TYPE_TAG_NAME (type); - } - } + /* This isn't technically needed today. It is done for symmetry + with read_file_scope. */ + attr = dwarf2_attr (die, DW_AT_producer, cu); + if (attr) + cu->producer = DW_STRING (attr); - if (die->tag == DW_TAG_structure_type) - { - TYPE_CODE (type) = TYPE_CODE_STRUCT; - } - else if (die->tag == DW_TAG_union_type) - { - TYPE_CODE (type) = TYPE_CODE_UNION; - } - else - { - TYPE_CODE (type) = TYPE_CODE_CLASS; - } + /* We assume that we're processing GCC output. */ + processing_gcc_compilation = 2; - if (cu->language == language_cplus && die->tag == DW_TAG_class_type) - TYPE_DECLARED_CLASS (type) = 1; + processing_has_namespace_info = 0; - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - { - TYPE_LENGTH (type) = DW_UNSND (attr); - } - else + start_symtab (name, comp_dir, lowpc); + record_debugformat ("DWARF 2"); + record_producer (cu->producer); + + /* Process the dies in the type unit. */ + if (die->child == NULL) { - TYPE_LENGTH (type) = 0; + dump_die_for_error (die); + error (_("Dwarf Error: Missing children for type unit [in module %s]"), + bfd_get_filename (abfd)); } - TYPE_STUB_SUPPORTED (type) = 1; - if (die_is_declaration (die, cu)) - TYPE_STUB (type) = 1; - else if (attr == NULL && die->child == NULL - && producer_is_realview (cu->producer)) - /* RealView does not output the required DW_AT_declaration - on incomplete types. */ - TYPE_STUB (type) = 1; - - /* We need to add the type field to the die immediately so we don't - infinitely recurse when dealing with pointers to the structure - type within the structure itself. */ - set_die_type (die, type, cu); - - /* set_die_type should be already done. */ - set_descriptive_type (type, die, cu); + child_die = die->child; - if (die->child != NULL && ! die_is_declaration (die, cu)) + while (child_die && child_die->tag) { - struct field_info fi; - struct die_info *child_die; - - memset (&fi, 0, sizeof (struct field_info)); - - child_die = die->child; - - while (child_die && child_die->tag) - { - if (child_die->tag == DW_TAG_member - || child_die->tag == DW_TAG_variable) - { - /* NOTE: carlton/2002-11-05: A C++ static data member - should be a DW_TAG_member that is a declaration, but - all versions of G++ as of this writing (so through at - least 3.2.1) incorrectly generate DW_TAG_variable - tags for them instead. */ - dwarf2_add_field (&fi, child_die, cu); - } - else if (child_die->tag == DW_TAG_subprogram) - { - /* C++ member function. */ - dwarf2_add_member_fn (&fi, child_die, type, cu); - } - else if (child_die->tag == DW_TAG_inheritance) - { - /* C++ base class field. */ - dwarf2_add_field (&fi, child_die, cu); - } - else if (child_die->tag == DW_TAG_typedef) - dwarf2_add_typedef (&fi, child_die, cu); - child_die = sibling_die (child_die); - } - - /* Attach fields and member functions to the type. */ - if (fi.nfields) - dwarf2_attach_fields_to_type (&fi, type, cu); - if (fi.nfnfields) - { - dwarf2_attach_fn_fields_to_type (&fi, type, cu); - - /* Get the type which refers to the base class (possibly this - class itself) which contains the vtable pointer for the current - class from the DW_AT_containing_type attribute. This use of - DW_AT_containing_type is a GNU extension. */ + process_die (child_die, cu); - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) - { - struct type *t = die_containing_type (die, cu); + child_die = sibling_die (child_die); + } - TYPE_VPTR_BASETYPE (type) = t; - if (type == t) - { - int i; + do_cleanups (back_to); +} - /* Our own class provides vtbl ptr. */ - for (i = TYPE_NFIELDS (t) - 1; - i >= TYPE_N_BASECLASSES (t); - --i) - { - char *fieldname = TYPE_FIELD_NAME (t, i); +static void +add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc, + struct dwarf2_cu *cu) +{ + struct function_range *thisfn; - if (is_vtable_name (fieldname, cu)) - { - TYPE_VPTR_FIELDNO (type) = i; - break; - } - } + thisfn = (struct function_range *) + obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range)); + thisfn->name = name; + thisfn->lowpc = lowpc; + thisfn->highpc = highpc; + thisfn->seen_line = 0; + thisfn->next = NULL; - /* Complain if virtual function table field not found. */ - if (i < TYPE_N_BASECLASSES (t)) - complaint (&symfile_complaints, - _("virtual function table pointer not found when defining class '%s'"), - TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : - ""); - } - else - { - TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t); - } - } - else if (cu->producer - && strncmp (cu->producer, - "IBM(R) XL C/C++ Advanced Edition", 32) == 0) - { - /* The IBM XLC compiler does not provide direct indication - of the containing type, but the vtable pointer is - always named __vfp. */ + if (cu->last_fn == NULL) + cu->first_fn = thisfn; + else + cu->last_fn->next = thisfn; - int i; + cu->last_fn = thisfn; +} - for (i = TYPE_NFIELDS (type) - 1; - i >= TYPE_N_BASECLASSES (type); - --i) - { - if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0) - { - TYPE_VPTR_FIELDNO (type) = i; - TYPE_VPTR_BASETYPE (type) = type; - break; - } - } - } - } +/* qsort helper for inherit_abstract_dies. */ - /* Copy fi.typedef_field_list linked list elements content into the - allocated array TYPE_TYPEDEF_FIELD_ARRAY (type). */ - if (fi.typedef_field_list) - { - int i = fi.typedef_field_list_count; +static int +unsigned_int_compar (const void *ap, const void *bp) +{ + unsigned int a = *(unsigned int *) ap; + unsigned int b = *(unsigned int *) bp; - ALLOCATE_CPLUS_STRUCT_TYPE (type); - TYPE_TYPEDEF_FIELD_ARRAY (type) - = TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i); - TYPE_TYPEDEF_FIELD_COUNT (type) = i; + return (a > b) - (b > a); +} - /* Reverse the list order to keep the debug info elements order. */ - while (--i >= 0) - { - struct typedef_field *dest, *src; +/* DW_AT_abstract_origin inherits whole DIEs (not just their attributes). + Inherit only the children of the DW_AT_abstract_origin DIE not being + already referenced by DW_AT_abstract_origin from the children of the + current DIE. */ - dest = &TYPE_TYPEDEF_FIELD (type, i); - src = &fi.typedef_field_list->field; - fi.typedef_field_list = fi.typedef_field_list->next; - *dest = *src; - } - } - } +static void +inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) +{ + struct die_info *child_die; + unsigned die_children_count; + /* CU offsets which were referenced by children of the current DIE. */ + unsigned *offsets; + unsigned *offsets_end, *offsetp; + /* Parent of DIE - referenced by DW_AT_abstract_origin. */ + struct die_info *origin_die; + /* Iterator of the ORIGIN_DIE children. */ + struct die_info *origin_child_die; + struct cleanup *cleanups; + struct attribute *attr; + struct dwarf2_cu *origin_cu; + struct pending **origin_previous_list_in_scope; - quirk_gcc_member_function_pointer (type, cu->objfile); + attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); + if (!attr) + return; - do_cleanups (back_to); - return type; -} + /* Note that following die references may follow to a die in a + different cu. */ -static void -process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child_die = die->child; - struct type *this_type; + origin_cu = cu; + origin_die = follow_die_ref (die, attr, &origin_cu); - this_type = get_die_type (die, cu); - if (this_type == NULL) - this_type = read_structure_type (die, cu); + /* We're inheriting ORIGIN's children into the scope we'd put DIE's + symbols in. */ + origin_previous_list_in_scope = origin_cu->list_in_scope; + origin_cu->list_in_scope = cu->list_in_scope; - /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its - snapshots) has been known to create a die giving a declaration - for a class that has, as a child, a die giving a definition for a - nested class. So we have to process our children even if the - current die is a declaration. Normally, of course, a declaration - won't have any children at all. */ + if (die->tag != origin_die->tag + && !(die->tag == DW_TAG_inlined_subroutine + && origin_die->tag == DW_TAG_subprogram)) + complaint (&symfile_complaints, + _("DIE 0x%x and its abstract origin 0x%x have different tags"), + die->offset, origin_die->offset); - while (child_die != NULL && child_die->tag) + child_die = die->child; + die_children_count = 0; + while (child_die && child_die->tag) { - if (child_die->tag == DW_TAG_member - || child_die->tag == DW_TAG_variable - || child_die->tag == DW_TAG_inheritance) - { - /* Do nothing. */ - } - else - process_die (child_die, cu); - child_die = sibling_die (child_die); + die_children_count++; } + offsets = xmalloc (sizeof (*offsets) * die_children_count); + cleanups = make_cleanup (xfree, offsets); - /* Do not consider external references. According to the DWARF standard, - these DIEs are identified by the fact that they have no byte_size - attribute, and a declaration attribute. */ - if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL - || !die_is_declaration (die, cu)) - new_symbol (die, this_type, cu); -} + offsets_end = offsets; + child_die = die->child; + while (child_die && child_die->tag) + { + /* For each CHILD_DIE, find the corresponding child of + ORIGIN_DIE. If there is more than one layer of + DW_AT_abstract_origin, follow them all; there shouldn't be, + but GCC versions at least through 4.4 generate this (GCC PR + 40573). */ + struct die_info *child_origin_die = child_die; + struct dwarf2_cu *child_origin_cu = cu; -/* Given a DW_AT_enumeration_type die, set its type. We do not - complete the type's fields yet, or create any symbols. */ + while (1) + { + attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin, + child_origin_cu); + if (attr == NULL) + break; + child_origin_die = follow_die_ref (child_origin_die, attr, + &child_origin_cu); + } -static struct type * -read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) + /* According to DWARF3 3.3.8.2 #3 new entries without their abstract + counterpart may exist. */ + if (child_origin_die != child_die) + { + if (child_die->tag != child_origin_die->tag + && !(child_die->tag == DW_TAG_inlined_subroutine + && child_origin_die->tag == DW_TAG_subprogram)) + complaint (&symfile_complaints, + _("Child DIE 0x%x and its abstract origin 0x%x have " + "different tags"), child_die->offset, + child_origin_die->offset); + if (child_origin_die->parent != origin_die) + complaint (&symfile_complaints, + _("Child DIE 0x%x and its abstract origin 0x%x have " + "different parents"), child_die->offset, + child_origin_die->offset); + else + *offsets_end++ = child_origin_die->offset; + } + child_die = sibling_die (child_die); + } + qsort (offsets, offsets_end - offsets, sizeof (*offsets), + unsigned_int_compar); + for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) + if (offsetp[-1] == *offsetp) + complaint (&symfile_complaints, + _("Multiple children of DIE 0x%x refer " + "to DIE 0x%x as their abstract origin"), + die->offset, *offsetp); + + offsetp = offsets; + origin_child_die = origin_die->child; + while (origin_child_die && origin_child_die->tag) + { + /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children? */ + while (offsetp < offsets_end && *offsetp < origin_child_die->offset) + offsetp++; + if (offsetp >= offsets_end || *offsetp > origin_child_die->offset) + { + /* Found that ORIGIN_CHILD_DIE is really not referenced. */ + process_die (origin_child_die, origin_cu); + } + origin_child_die = sibling_die (origin_child_die); + } + origin_cu->list_in_scope = origin_previous_list_in_scope; + + do_cleanups (cleanups); +} + +static void +read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; - struct type *type; - struct attribute *attr; - const char *name; + struct context_stack *new; + CORE_ADDR lowpc; + CORE_ADDR highpc; + struct die_info *child_die; + struct attribute *attr, *call_line, *call_file; + char *name; + CORE_ADDR baseaddr; + struct block *block; + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + VEC (symbolp) *template_args = NULL; + struct template_symbol *templ_func = NULL; - /* If the definition of this type lives in .debug_types, read that type. - Don't follow DW_AT_specification though, that will take us back up - the chain and we want to go down. */ - attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); - if (attr) + if (inlined_func) { - struct dwarf2_cu *type_cu = cu; - struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); - - type = read_type_die (type_die, type_cu); - return set_die_type (die, type, cu); + /* If we do not have call site information, we can't show the + caller of this inlined function. That's too confusing, so + only use the scope for local variables. */ + call_line = dwarf2_attr (die, DW_AT_call_line, cu); + call_file = dwarf2_attr (die, DW_AT_call_file, cu); + if (call_line == NULL || call_file == NULL) + { + read_lexical_block_scope (die, cu); + return; + } } - type = alloc_type (objfile); + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - TYPE_CODE (type) = TYPE_CODE_ENUM; - name = dwarf2_full_name (NULL, die, cu); - if (name != NULL) - TYPE_TAG_NAME (type) = (char *) name; + name = dwarf2_name (die, cu); - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) + /* Ignore functions with missing or empty names. These are actually + illegal according to the DWARF standard. */ + if (name == NULL) { - TYPE_LENGTH (type) = DW_UNSND (attr); + complaint (&symfile_complaints, + _("missing name for subprogram DIE at %d"), die->offset); + return; } - else + + /* Ignore functions with missing or invalid low and high pc attributes. */ + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) { - TYPE_LENGTH (type) = 0; + attr = dwarf2_attr (die, DW_AT_external, cu); + if (!attr || !DW_UNSND (attr)) + complaint (&symfile_complaints, + _("cannot get low and high bounds " + "for subprogram DIE at %d"), + die->offset); + return; } - /* The enumeration DIE can be incomplete. In Ada, any type can be - declared as private in the package spec, and then defined only - inside the package body. Such types are known as Taft Amendment - Types. When another package uses such a type, an incomplete DIE - may be generated by the compiler. */ - if (die_is_declaration (die, cu)) - TYPE_STUB (type) = 1; + lowpc += baseaddr; + highpc += baseaddr; - return set_die_type (die, type, cu); -} + /* Record the function range for dwarf_decode_lines. */ + add_to_cu_func_list (name, lowpc, highpc, cu); -/* Given a pointer to a die which begins an enumeration, process all - the dies that define the members of the enumeration, and create the - symbol for the enumeration type. + /* If we have any template arguments, then we must allocate a + different sort of symbol. */ + for (child_die = die->child; child_die; child_die = sibling_die (child_die)) + { + if (child_die->tag == DW_TAG_template_type_param + || child_die->tag == DW_TAG_template_value_param) + { + templ_func = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct template_symbol); + templ_func->base.is_cplus_template_function = 1; + break; + } + } - NOTE: We reverse the order of the element list. */ + new = push_context (0, lowpc); + new->name = new_symbol_full (die, read_type_die (die, cu), cu, + (struct symbol *) templ_func); -static void -process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child_die; - struct field *fields; - struct symbol *sym; - int num_fields; - int unsigned_enum = 1; - char *name; - struct type *this_type; + /* If there is a location expression for DW_AT_frame_base, record + it. */ + attr = dwarf2_attr (die, DW_AT_frame_base, cu); + if (attr) + /* FIXME: cagney/2004-01-26: The DW_AT_frame_base's location + expression is being recorded directly in the function's symbol + and not in a separate frame-base object. I guess this hack is + to avoid adding some sort of frame-base adjunct/annex to the + function's symbol :-(. The problem with doing this is that it + results in a function symbol with a location expression that + has nothing to do with the location of the function, ouch! The + relationship should be: a function's symbol has-a frame base; a + frame-base has-a location expression. */ + dwarf2_symbol_mark_computed (attr, new->name, cu); + + cu->list_in_scope = &local_symbols; - num_fields = 0; - fields = NULL; - this_type = get_die_type (die, cu); - if (this_type == NULL) - this_type = read_enumeration_type (die, cu); if (die->child != NULL) { child_die = die->child; while (child_die && child_die->tag) { - if (child_die->tag != DW_TAG_enumerator) + if (child_die->tag == DW_TAG_template_type_param + || child_die->tag == DW_TAG_template_value_param) { - process_die (child_die, cu); + struct symbol *arg = new_symbol (child_die, NULL, cu); + + if (arg != NULL) + VEC_safe_push (symbolp, template_args, arg); } else - { - name = dwarf2_name (child_die, cu); - if (name) - { - sym = new_symbol (child_die, this_type, cu); - if (SYMBOL_VALUE (sym) < 0) - unsigned_enum = 0; + process_die (child_die, cu); + child_die = sibling_die (child_die); + } + } - if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) - { - fields = (struct field *) - xrealloc (fields, - (num_fields + DW_FIELD_ALLOC_CHUNK) - * sizeof (struct field)); - } + inherit_abstract_dies (die, cu); - FIELD_NAME (fields[num_fields]) = SYMBOL_LINKAGE_NAME (sym); - FIELD_TYPE (fields[num_fields]) = NULL; - SET_FIELD_BITPOS (fields[num_fields], SYMBOL_VALUE (sym)); - FIELD_BITSIZE (fields[num_fields]) = 0; + /* If we have a DW_AT_specification, we might need to import using + directives from the context of the specification DIE. See the + comment in determine_prefix. */ + if (cu->language == language_cplus + && dwarf2_attr (die, DW_AT_specification, cu)) + { + struct dwarf2_cu *spec_cu = cu; + struct die_info *spec_die = die_specification (die, &spec_cu); - num_fields++; - } + while (spec_die) + { + child_die = spec_die->child; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_imported_module) + process_die (child_die, spec_cu); + child_die = sibling_die (child_die); } - child_die = sibling_die (child_die); - } - - if (num_fields) - { - TYPE_NFIELDS (this_type) = num_fields; - TYPE_FIELDS (this_type) = (struct field *) - TYPE_ALLOC (this_type, sizeof (struct field) * num_fields); - memcpy (TYPE_FIELDS (this_type), fields, - sizeof (struct field) * num_fields); - xfree (fields); + /* In some cases, GCC generates specification DIEs that + themselves contain DW_AT_specification attributes. */ + spec_die = die_specification (spec_die, &spec_cu); } - if (unsigned_enum) - TYPE_UNSIGNED (this_type) = 1; } - new_symbol (die, this_type, cu); -} + new = pop_context (); + /* Make a block for the local symbols within. */ + block = finish_block (new->name, &local_symbols, new->old_blocks, + lowpc, highpc, objfile); -/* Extract all information from a DW_TAG_array_type DIE and put it in - the DIE's type field. For now, this only handles one dimensional - arrays. */ + /* For C++, set the block's scope. */ + if (cu->language == language_cplus || cu->language == language_fortran) + cp_set_block_scope (new->name, block, &objfile->objfile_obstack, + determine_prefix (die, cu), + processing_has_namespace_info); -static struct type * -read_array_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct die_info *child_die; - struct type *type; - struct type *element_type, *range_type, *index_type; - struct type **range_types = NULL; - struct attribute *attr; - int ndim = 0; - struct cleanup *back_to; - char *name; - - element_type = die_type (die, cu); - - /* The die_type call above may have already set the type for this DIE. */ - type = get_die_type (die, cu); - if (type) - return type; - - /* Irix 6.2 native cc creates array types without children for - arrays with unspecified length. */ - if (die->child == NULL) - { - index_type = objfile_type (objfile)->builtin_int; - range_type = create_range_type (NULL, index_type, 0, -1); - type = create_array_type (NULL, element_type, range_type); - return set_die_type (die, type, cu); - } + /* If we have address ranges, record them. */ + dwarf2_record_block_ranges (die, block, baseaddr, cu); - back_to = make_cleanup (null_cleanup, NULL); - child_die = die->child; - while (child_die && child_die->tag) + /* Attach template arguments to function. */ + if (! VEC_empty (symbolp, template_args)) { - if (child_die->tag == DW_TAG_subrange_type) - { - struct type *child_type = read_type_die (child_die, cu); + gdb_assert (templ_func != NULL); - if (child_type != NULL) - { - /* The range type was succesfully read. Save it for - the array type creation. */ - if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0) - { - range_types = (struct type **) - xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK) - * sizeof (struct type *)); - if (ndim == 0) - make_cleanup (free_current_contents, &range_types); - } - range_types[ndim++] = child_type; - } - } - child_die = sibling_die (child_die); + templ_func->n_template_arguments = VEC_length (symbolp, template_args); + templ_func->template_arguments + = obstack_alloc (&objfile->objfile_obstack, + (templ_func->n_template_arguments + * sizeof (struct symbol *))); + memcpy (templ_func->template_arguments, + VEC_address (symbolp, template_args), + (templ_func->n_template_arguments * sizeof (struct symbol *))); + VEC_free (symbolp, template_args); } - /* Dwarf2 dimensions are output from left to right, create the - necessary array types in backwards order. */ + /* In C++, we can have functions nested inside functions (e.g., when + a function declares a class that has methods). This means that + when we finish processing a function scope, we may need to go + back to building a containing block's symbol lists. */ + local_symbols = new->locals; + param_symbols = new->params; + using_directives = new->using_directives; - type = element_type; + /* If we've finished processing a top-level function, subsequent + symbols go in the file symbol list. */ + if (outermost_context_p ()) + cu->list_in_scope = &file_symbols; +} - if (read_array_order (die, cu) == DW_ORD_col_major) - { - int i = 0; +/* Process all the DIES contained within a lexical block scope. Start + a new scope, process the dies, and then close the scope. */ - while (i < ndim) - type = create_array_type (NULL, type, range_types[i++]); - } - else - { - while (ndim-- > 0) - type = create_array_type (NULL, type, range_types[ndim]); - } +static void +read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct context_stack *new; + CORE_ADDR lowpc, highpc; + struct die_info *child_die; + CORE_ADDR baseaddr; - /* Understand Dwarf2 support for vector types (like they occur on - the PowerPC w/ AltiVec). Gcc just adds another attribute to the - array type. This is not part of the Dwarf2/3 standard yet, but a - custom vendor extension. The main difference between a regular - array and the vector variant is that vectors are passed by value - to functions. */ - attr = dwarf2_attr (die, DW_AT_GNU_vector, cu); - if (attr) - make_vector_type (type); + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - name = dwarf2_name (die, cu); - if (name) - TYPE_NAME (type) = name; + /* Ignore blocks with missing or invalid low and high pc attributes. */ + /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges + as multiple lexical blocks? Handling children in a sane way would + be nasty. Might be easier to properly extend generic blocks to + describe ranges. */ + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + return; + lowpc += baseaddr; + highpc += baseaddr; - /* Install the type in the die. */ - set_die_type (die, type, cu); + push_context (0, lowpc); + if (die->child != NULL) + { + child_die = die->child; + while (child_die && child_die->tag) + { + process_die (child_die, cu); + child_die = sibling_die (child_die); + } + } + new = pop_context (); - /* set_die_type should be already done. */ - set_descriptive_type (type, die, cu); + if (local_symbols != NULL || using_directives != NULL) + { + struct block *block + = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, + highpc, objfile); - do_cleanups (back_to); + /* Note that recording ranges after traversing children, as we + do here, means that recording a parent's ranges entails + walking across all its children's ranges as they appear in + the address map, which is quadratic behavior. - return type; + It would be nicer to record the parent's ranges before + traversing its children, simply overriding whatever you find + there. But since we don't even decide whether to create a + block until after we've traversed its children, that's hard + to do. */ + dwarf2_record_block_ranges (die, block, baseaddr, cu); + } + local_symbols = new->locals; + using_directives = new->using_directives; } -static enum dwarf_array_dim_ordering -read_array_order (struct die_info *die, struct dwarf2_cu *cu) -{ - struct attribute *attr; - - attr = dwarf2_attr (die, DW_AT_ordering, cu); - - if (attr) return DW_SND (attr); +/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. + Return 1 if the attributes are present and valid, otherwise, return 0. + If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ - /* - GNU F77 is a special case, as at 08/2004 array type info is the - opposite order to the dwarf2 specification, but data is still - laid out as per normal fortran. +static int +dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, + CORE_ADDR *high_return, struct dwarf2_cu *cu, + struct partial_symtab *ranges_pst) +{ + struct objfile *objfile = cu->objfile; + struct comp_unit_head *cu_header = &cu->header; + bfd *obfd = objfile->obfd; + unsigned int addr_size = cu_header->addr_size; + CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); + /* Base address selection entry. */ + CORE_ADDR base; + int found_base; + unsigned int dummy; + gdb_byte *buffer; + CORE_ADDR marker; + int low_set; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + CORE_ADDR baseaddr; - FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need - version checking. - */ + found_base = cu->base_known; + base = cu->base_address; - if (cu->language == language_fortran - && cu->producer && strstr (cu->producer, "GNU F77")) + dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); + if (offset >= dwarf2_per_objfile->ranges.size) { - return DW_ORD_row_major; + complaint (&symfile_complaints, + _("Offset %d out of bounds for DW_AT_ranges attribute"), + offset); + return 0; } + buffer = dwarf2_per_objfile->ranges.buffer + offset; - switch (cu->language_defn->la_array_ordering) + /* Read in the largest possible address. */ + marker = read_address (obfd, buffer, cu, &dummy); + if ((marker & mask) == mask) { - case array_column_major: - return DW_ORD_col_major; - case array_row_major: - default: - return DW_ORD_row_major; - }; -} + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, cu, &dummy); + buffer += 2 * addr_size; + offset += 2 * addr_size; + found_base = 1; + } -/* Extract all information from a DW_TAG_set_type DIE and put it in - the DIE's type field. */ + low_set = 0; -static struct type * -read_set_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *domain_type, *set_type; - struct attribute *attr; + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - domain_type = die_type (die, cu); + while (1) + { + CORE_ADDR range_beginning, range_end; - /* The die_type call above may have already set the type for this DIE. */ - set_type = get_die_type (die, cu); - if (set_type) - return set_type; + range_beginning = read_address (obfd, buffer, cu, &dummy); + buffer += addr_size; + range_end = read_address (obfd, buffer, cu, &dummy); + buffer += addr_size; + offset += 2 * addr_size; - set_type = create_set_type (NULL, domain_type); + /* An end of list marker is a pair of zero addresses. */ + if (range_beginning == 0 && range_end == 0) + /* Found the end of list entry. */ + break; - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - TYPE_LENGTH (set_type) = DW_UNSND (attr); + /* Each base address selection entry is a pair of 2 values. + The first is the largest possible address, the second is + the base address. Check for a base address here. */ + if ((range_beginning & mask) == mask) + { + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, cu, &dummy); + found_base = 1; + continue; + } - return set_die_type (die, set_type, cu); -} + if (!found_base) + { + /* We have no valid base address for the ranges + data. */ + complaint (&symfile_complaints, + _("Invalid .debug_ranges data (no base address)")); + return 0; + } -/* First cut: install each common block member as a global variable. */ + if (range_beginning > range_end) + { + /* Inverted range entries are invalid. */ + complaint (&symfile_complaints, + _("Invalid .debug_ranges data (inverted range)")); + return 0; + } -static void -read_common_block (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child_die; - struct attribute *attr; - struct symbol *sym; - CORE_ADDR base = (CORE_ADDR) 0; + /* Empty range entries have no effect. */ + if (range_beginning == range_end) + continue; - attr = dwarf2_attr (die, DW_AT_location, cu); - if (attr) - { - /* Support the .debug_loc offsets */ - if (attr_form_is_block (attr)) - { - base = decode_locdesc (DW_BLOCK (attr), cu); - } - else if (attr_form_is_section_offset (attr)) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_location", - "common block member"); - } - } - if (die->child != NULL) - { - child_die = die->child; - while (child_die && child_die->tag) - { - sym = new_symbol (child_die, NULL, cu); - attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu); - if (attr) - { - CORE_ADDR byte_offset = 0; + range_beginning += base; + range_end += base; - if (attr_form_is_section_offset (attr)) - dwarf2_complex_location_expr_complaint (); - else if (attr_form_is_constant (attr)) - byte_offset = dwarf2_get_attr_constant_value (attr, 0); - else if (attr_form_is_block (attr)) - byte_offset = decode_locdesc (DW_BLOCK (attr), cu); - else - dwarf2_complex_location_expr_complaint (); + if (ranges_pst != NULL) + addrmap_set_empty (objfile->psymtabs_addrmap, + range_beginning + baseaddr, + range_end - 1 + baseaddr, + ranges_pst); - SYMBOL_VALUE_ADDRESS (sym) = base + byte_offset; - add_symbol_to_list (sym, &global_symbols); - } - child_die = sibling_die (child_die); + /* FIXME: This is recording everything as a low-high + segment of consecutive addresses. We should have a + data structure for discontiguous block ranges + instead. */ + if (! low_set) + { + low = range_beginning; + high = range_end; + low_set = 1; + } + else + { + if (range_beginning < low) + low = range_beginning; + if (range_end > high) + high = range_end; } } -} - -/* Create a type for a C++ namespace. */ - -static struct type * -read_namespace_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - const char *previous_prefix, *name; - int is_anonymous; - struct type *type; - - /* For extensions, reuse the type of the original namespace. */ - if (dwarf2_attr (die, DW_AT_extension, cu) != NULL) - { - struct die_info *ext_die; - struct dwarf2_cu *ext_cu = cu; - - ext_die = dwarf2_extension (die, &ext_cu); - type = read_type_die (ext_die, ext_cu); - return set_die_type (die, type, cu); - } - - name = namespace_name (die, &is_anonymous, cu); - - /* Now build the name of the current namespace. */ - previous_prefix = determine_prefix (die, cu); - if (previous_prefix[0] != '\0') - name = typename_concat (&objfile->objfile_obstack, - previous_prefix, name, 0, cu); - - /* Create the type. */ - type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL, - objfile); - TYPE_NAME (type) = (char *) name; - TYPE_TAG_NAME (type) = TYPE_NAME (type); + if (! low_set) + /* If the first entry is an end-of-list marker, the range + describes an empty scope, i.e. no instructions. */ + return 0; - return set_die_type (die, type, cu); + if (low_return) + *low_return = low; + if (high_return) + *high_return = high; + return 1; } -/* Read a C++ namespace. */ - -static void -read_namespace (struct die_info *die, struct dwarf2_cu *cu) +/* Get low and high pc attributes from a die. Return 1 if the attributes + are present and valid, otherwise, return 0. Return -1 if the range is + discontinuous, i.e. derived from DW_AT_ranges information. */ +static int +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, + CORE_ADDR *highpc, struct dwarf2_cu *cu, + struct partial_symtab *pst) { - struct objfile *objfile = cu->objfile; - const char *name; - int is_anonymous; - - /* Add a symbol associated to this if we haven't seen the namespace - before. Also, add a using directive if it's an anonymous - namespace. */ + struct attribute *attr; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + int ret = 0; - if (dwarf2_attr (die, DW_AT_extension, cu) == NULL) + attr = dwarf2_attr (die, DW_AT_high_pc, cu); + if (attr) { - struct type *type; - - type = read_type_die (die, cu); - new_symbol (die, type, cu); - - name = namespace_name (die, &is_anonymous, cu); - if (is_anonymous) - { - const char *previous_prefix = determine_prefix (die, cu); + high = DW_ADDR (attr); + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + if (attr) + low = DW_ADDR (attr); + else + /* Found high w/o low attribute. */ + return 0; - cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL, - NULL, &objfile->objfile_obstack); - } + /* Found consecutive range of addresses. */ + ret = 1; } - - if (die->child != NULL) + else { - struct die_info *child_die = die->child; - - while (child_die && child_die->tag) + attr = dwarf2_attr (die, DW_AT_ranges, cu); + if (attr != NULL) { - process_die (child_die, cu); - child_die = sibling_die (child_die); + /* Value of the DW_AT_ranges attribute is the offset in the + .debug_ranges section. */ + if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, pst)) + return 0; + /* Found discontinuous range of addresses. */ + ret = -1; } } -} - -/* Read a Fortran module as type. This DIE can be only a declaration used for - imported module. Still we need that type as local Fortran "use ... only" - declaration imports depend on the created type in determine_prefix. */ - -static struct type * -read_module_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - char *module_name; - struct type *type; - module_name = dwarf2_name (die, cu); - if (!module_name) - complaint (&symfile_complaints, _("DW_TAG_module has no name, offset 0x%x"), - die->offset); - type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile); + /* read_partial_die has also the strict LOW < HIGH requirement. */ + if (high <= low) + return 0; - /* determine_prefix uses TYPE_TAG_NAME. */ - TYPE_TAG_NAME (type) = TYPE_NAME (type); + /* When using the GNU linker, .gnu.linkonce. sections are used to + eliminate duplicate copies of functions and vtables and such. + The linker will arbitrarily choose one and discard the others. + The AT_*_pc values for such functions refer to local labels in + these sections. If the section from that file was discarded, the + labels are not in the output, so the relocs get a value of 0. + If this is a discarded function, mark the pc bounds as invalid, + so that GDB will ignore it. */ + if (low == 0 && !dwarf2_per_objfile->has_section_at_zero) + return 0; - return set_die_type (die, type, cu); + *lowpc = low; + *highpc = high; + return ret; } -/* Read a Fortran module. */ +/* Assuming that DIE represents a subprogram DIE or a lexical block, get + its low and high PC addresses. Do nothing if these addresses could not + be determined. Otherwise, set LOWPC to the low address if it is smaller, + and HIGHPC to the high address if greater than HIGHPC. */ static void -read_module (struct die_info *die, struct dwarf2_cu *cu) +dwarf2_get_subprogram_pc_bounds (struct die_info *die, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + struct dwarf2_cu *cu) { - struct die_info *child_die = die->child; + CORE_ADDR low, high; + struct die_info *child = die->child; - while (child_die && child_die->tag) + if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL)) { - process_die (child_die, cu); - child_die = sibling_die (child_die); + *lowpc = min (*lowpc, low); + *highpc = max (*highpc, high); } -} - -/* Return the name of the namespace represented by DIE. Set - *IS_ANONYMOUS to tell whether or not the namespace is an anonymous - namespace. */ - -static const char * -namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) -{ - struct die_info *current_die; - const char *name = NULL; - /* Loop through the extensions until we find a name. */ + /* If the language does not allow nested subprograms (either inside + subprograms or lexical blocks), we're done. */ + if (cu->language != language_ada) + return; - for (current_die = die; - current_die != NULL; - current_die = dwarf2_extension (die, &cu)) + /* Check all the children of the given DIE. If it contains nested + subprograms, then check their pc bounds. Likewise, we need to + check lexical blocks as well, as they may also contain subprogram + definitions. */ + while (child && child->tag) { - name = dwarf2_name (current_die, cu); - if (name != NULL) - break; + if (child->tag == DW_TAG_subprogram + || child->tag == DW_TAG_lexical_block) + dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu); + child = sibling_die (child); } - - /* Is it an anonymous namespace? */ - - *is_anonymous = (name == NULL); - if (*is_anonymous) - name = "(anonymous namespace)"; - - return name; } -/* Extract all information from a DW_TAG_pointer_type DIE and add to - the user defined type vector. */ +/* Get the low and high pc's represented by the scope DIE, and store + them in *LOWPC and *HIGHPC. If the correct values can't be + determined, set *LOWPC to -1 and *HIGHPC to 0. */ -static struct type * -read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) +static void +get_scope_pc_bounds (struct die_info *die, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + struct dwarf2_cu *cu) { - struct gdbarch *gdbarch = get_objfile_arch (cu->objfile); - struct comp_unit_head *cu_header = &cu->header; - struct type *type; - struct attribute *attr_byte_size; - struct attribute *attr_address_class; - int byte_size, addr_class; - struct type *target_type; + CORE_ADDR best_low = (CORE_ADDR) -1; + CORE_ADDR best_high = (CORE_ADDR) 0; + CORE_ADDR current_low, current_high; - target_type = die_type (die, cu); + if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)) + { + best_low = current_low; + best_high = current_high; + } + else + { + struct die_info *child = die->child; - /* The die_type call above may have already set the type for this DIE. */ - type = get_die_type (die, cu); - if (type) - return type; + while (child && child->tag) + { + switch (child->tag) { + case DW_TAG_subprogram: + dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu); + break; + case DW_TAG_namespace: + case DW_TAG_module: + /* FIXME: carlton/2004-01-16: Should we do this for + DW_TAG_class_type/DW_TAG_structure_type, too? I think + that current GCC's always emit the DIEs corresponding + to definitions of methods of classes as children of a + DW_TAG_compile_unit or DW_TAG_namespace (as opposed to + the DIEs giving the declarations, which could be + anywhere). But I don't see any reason why the + standards says that they have to be there. */ + get_scope_pc_bounds (child, ¤t_low, ¤t_high, cu); - type = lookup_pointer_type (target_type); + if (current_low != ((CORE_ADDR) -1)) + { + best_low = min (best_low, current_low); + best_high = max (best_high, current_high); + } + break; + default: + /* Ignore. */ + break; + } - attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr_byte_size) - byte_size = DW_UNSND (attr_byte_size); - else - byte_size = cu_header->addr_size; + child = sibling_die (child); + } + } - attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu); - if (attr_address_class) - addr_class = DW_UNSND (attr_address_class); - else - addr_class = DW_ADDR_none; + *lowpc = best_low; + *highpc = best_high; +} - /* If the pointer size or address class is different than the - default, create a type variant marked as such and set the - length accordingly. */ - if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none) +/* Record the address ranges for BLOCK, offset by BASEADDR, as given + in DIE. */ +static void +dwarf2_record_block_ranges (struct die_info *die, struct block *block, + CORE_ADDR baseaddr, struct dwarf2_cu *cu) +{ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_high_pc, cu); + if (attr) { - if (gdbarch_address_class_type_flags_p (gdbarch)) - { - int type_flags; + CORE_ADDR high = DW_ADDR (attr); - type_flags = gdbarch_address_class_type_flags - (gdbarch, byte_size, addr_class); - gdb_assert ((type_flags & ~TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL) - == 0); - type = make_type_with_address_space (type, type_flags); - } - else if (TYPE_LENGTH (type) != byte_size) - { - complaint (&symfile_complaints, _("invalid pointer size %d"), byte_size); - } - else - { - /* Should we also complain about unhandled address classes? */ - } + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + if (attr) + { + CORE_ADDR low = DW_ADDR (attr); + + record_block_range (block, baseaddr + low, baseaddr + high - 1); + } } - TYPE_LENGTH (type) = byte_size; - return set_die_type (die, type, cu); -} + attr = dwarf2_attr (die, DW_AT_ranges, cu); + if (attr) + { + bfd *obfd = cu->objfile->obfd; -/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to - the user defined type vector. */ + /* The value of the DW_AT_ranges attribute is the offset of the + address range list in the .debug_ranges section. */ + unsigned long offset = DW_UNSND (attr); + gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset; -static struct type * -read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *type; - struct type *to_type; - struct type *domain; + /* For some target architectures, but not others, the + read_address function sign-extends the addresses it returns. + To recognize base address selection entries, we need a + mask. */ + unsigned int addr_size = cu->header.addr_size; + CORE_ADDR base_select_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); - to_type = die_type (die, cu); - domain = die_containing_type (die, cu); + /* The base address, to which the next pair is relative. Note + that this 'base' is a DWARF concept: most entries in a range + list are relative, to reduce the number of relocs against the + debugging information. This is separate from this function's + 'baseaddr' argument, which GDB uses to relocate debugging + information from a shared library based on the address at + which the library was loaded. */ + CORE_ADDR base = cu->base_address; + int base_known = cu->base_known; - /* The calls above may have already set the type for this DIE. */ - type = get_die_type (die, cu); - if (type) - return type; + gdb_assert (dwarf2_per_objfile->ranges.readin); + if (offset >= dwarf2_per_objfile->ranges.size) + { + complaint (&symfile_complaints, + _("Offset %lu out of bounds for DW_AT_ranges attribute"), + offset); + return; + } - if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD) - type = lookup_methodptr_type (to_type); - else - type = lookup_memberptr_type (to_type, domain); + for (;;) + { + unsigned int bytes_read; + CORE_ADDR start, end; - return set_die_type (die, type, cu); + start = read_address (obfd, buffer, cu, &bytes_read); + buffer += bytes_read; + end = read_address (obfd, buffer, cu, &bytes_read); + buffer += bytes_read; + + /* Did we find the end of the range list? */ + if (start == 0 && end == 0) + break; + + /* Did we find a base address selection entry? */ + else if ((start & base_select_mask) == base_select_mask) + { + base = end; + base_known = 1; + } + + /* We found an ordinary address range. */ + else + { + if (!base_known) + { + complaint (&symfile_complaints, + _("Invalid .debug_ranges data " + "(no base address)")); + return; + } + + if (start > end) + { + /* Inverted range entries are invalid. */ + complaint (&symfile_complaints, + _("Invalid .debug_ranges data " + "(inverted range)")); + return; + } + + /* Empty range entries have no effect. */ + if (start == end) + continue; + + record_block_range (block, + baseaddr + base + start, + baseaddr + base + end - 1); + } + } + } } -/* Extract all information from a DW_TAG_reference_type DIE and add to - the user defined type vector. */ +/* Check for GCC PR debug/45124 fix which is not present in any G++ version up + to 4.5.any while it is present already in G++ 4.6.0 - the PR has been fixed + during 4.6.0 experimental. */ -static struct type * -read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu) +static int +producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu) { - struct comp_unit_head *cu_header = &cu->header; - struct type *type, *target_type; - struct attribute *attr; + const char *cs; + int major, minor, release; - target_type = die_type (die, cu); + if (cu->producer == NULL) + { + /* For unknown compilers expect their behavior is DWARF version + compliant. - /* The die_type call above may have already set the type for this DIE. */ - type = get_die_type (die, cu); - if (type) - return type; + GCC started to support .debug_types sections by -gdwarf-4 since + gcc-4.5.x. As the .debug_types sections are missing DW_AT_producer + for their space efficiency GDB cannot workaround gcc-4.5.x -gdwarf-4 + combination. gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility + interpreted incorrectly by GDB now - GCC PR debug/48229. */ - type = lookup_reference_type (target_type); - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) + return 0; + } + + /* Skip any identifier after "GNU " - such as "C++" or "Java". */ + + if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0) { - TYPE_LENGTH (type) = DW_UNSND (attr); + /* For non-GCC compilers expect their behavior is DWARF version + compliant. */ + + return 0; } - else + cs = &cu->producer[strlen ("GNU ")]; + while (*cs && !isdigit (*cs)) + cs++; + if (sscanf (cs, "%d.%d.%d", &major, &minor, &release) != 3) { - TYPE_LENGTH (type) = cu_header->addr_size; + /* Not recognized as GCC. */ + + return 0; } - return set_die_type (die, type, cu); + + return major < 4 || (major == 4 && minor < 6); } -static struct type * -read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *base_type, *cv_type; +/* Return the default accessibility type if it is not overriden by + DW_AT_accessibility. */ - base_type = die_type (die, cu); +static enum dwarf_access_attribute +dwarf2_default_access_attribute (struct die_info *die, struct dwarf2_cu *cu) +{ + if (cu->header.version < 3 || producer_is_gxx_lt_4_6 (cu)) + { + /* The default DWARF 2 accessibility for members is public, the default + accessibility for inheritance is private. */ - /* The die_type call above may have already set the type for this DIE. */ - cv_type = get_die_type (die, cu); - if (cv_type) - return cv_type; + if (die->tag != DW_TAG_inheritance) + return DW_ACCESS_public; + else + return DW_ACCESS_private; + } + else + { + /* DWARF 3+ defines the default accessibility a different way. The same + rules apply now for DW_TAG_inheritance as for the members and it only + depends on the container kind. */ - cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0); - return set_die_type (die, cv_type, cu); + if (die->parent->tag == DW_TAG_class_type) + return DW_ACCESS_private; + else + return DW_ACCESS_public; + } } -static struct type * -read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *base_type, *cv_type; +/* Look for DW_AT_data_member_location. Set *OFFSET to the byte + offset. If the attribute was not found return 0, otherwise return + 1. If it was found but could not properly be handled, set *OFFSET + to 0. */ - base_type = die_type (die, cu); +static int +handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, + LONGEST *offset) +{ + struct attribute *attr; - /* The die_type call above may have already set the type for this DIE. */ - cv_type = get_die_type (die, cu); - if (cv_type) - return cv_type; + attr = dwarf2_attr (die, DW_AT_data_member_location, cu); + if (attr != NULL) + { + *offset = 0; - cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0); - return set_die_type (die, cv_type, cu); + /* Note that we do not check for a section offset first here. + This is because DW_AT_data_member_location is new in DWARF 4, + so if we see it, we can assume that a constant form is really + a constant and not a section offset. */ + if (attr_form_is_constant (attr)) + *offset = dwarf2_get_attr_constant_value (attr, 0); + else if (attr_form_is_section_offset (attr)) + dwarf2_complex_location_expr_complaint (); + else if (attr_form_is_block (attr)) + *offset = decode_locdesc (DW_BLOCK (attr), cu); + else + dwarf2_complex_location_expr_complaint (); + + return 1; + } + + return 0; } -/* Extract all information from a DW_TAG_string_type DIE and add to - the user defined type vector. It isn't really a user defined type, - but it behaves like one, with other DIE's using an AT_user_def_type - attribute to reference it. */ +/* Add an aggregate field to the field list. */ -static struct type * -read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) +static void +dwarf2_add_field (struct field_info *fip, struct die_info *die, + struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct type *type, *range_type, *index_type, *char_type; + struct nextfield *new_field; struct attribute *attr; - unsigned int length; + struct field *fp; + char *fieldname = ""; - attr = dwarf2_attr (die, DW_AT_string_length, cu); - if (attr) + /* Allocate a new field list entry and link it in. */ + new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield)); + make_cleanup (xfree, new_field); + memset (new_field, 0, sizeof (struct nextfield)); + + if (die->tag == DW_TAG_inheritance) { - length = DW_UNSND (attr); + new_field->next = fip->baseclasses; + fip->baseclasses = new_field; } else { - /* check for the DW_AT_byte_size attribute */ - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - { - length = DW_UNSND (attr); - } - else - { - length = 1; - } + new_field->next = fip->fields; + fip->fields = new_field; } + fip->nfields++; - index_type = objfile_type (objfile)->builtin_int; - range_type = create_range_type (NULL, index_type, 1, length); - char_type = language_string_char_type (cu->language_defn, gdbarch); - type = create_string_type (NULL, char_type, range_type); - - return set_die_type (die, type, cu); -} - -/* Handle DIES due to C code like: - - struct foo - { - int (*funcp)(int a, long l); - int b; - }; - - ('funcp' generates a DW_TAG_subroutine_type DIE) - */ - -static struct type * -read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *type; /* Type that this function returns */ - struct type *ftype; /* Function that returns above type */ - struct attribute *attr; - - type = die_type (die, cu); + attr = dwarf2_attr (die, DW_AT_accessibility, cu); + if (attr) + new_field->accessibility = DW_UNSND (attr); + else + new_field->accessibility = dwarf2_default_access_attribute (die, cu); + if (new_field->accessibility != DW_ACCESS_public) + fip->non_public_fields = 1; - /* The die_type call above may have already set the type for this DIE. */ - ftype = get_die_type (die, cu); - if (ftype) - return ftype; + attr = dwarf2_attr (die, DW_AT_virtuality, cu); + if (attr) + new_field->virtuality = DW_UNSND (attr); + else + new_field->virtuality = DW_VIRTUALITY_none; - ftype = lookup_function_type (type); + fp = &new_field->field; - /* All functions in C++, Pascal and Java have prototypes. */ - attr = dwarf2_attr (die, DW_AT_prototyped, cu); - if ((attr && (DW_UNSND (attr) != 0)) - || cu->language == language_cplus - || cu->language == language_java - || cu->language == language_pascal) - TYPE_PROTOTYPED (ftype) = 1; - else if (producer_is_realview (cu->producer)) - /* RealView does not emit DW_AT_prototyped. We can not - distinguish prototyped and unprototyped functions; default to - prototyped, since that is more common in modern code (and - RealView warns about unprototyped functions). */ - TYPE_PROTOTYPED (ftype) = 1; + if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu)) + { + LONGEST offset; - /* Store the calling convention in the type if it's available in - the subroutine die. Otherwise set the calling convention to - the default value DW_CC_normal. */ - attr = dwarf2_attr (die, DW_AT_calling_convention, cu); - TYPE_CALLING_CONVENTION (ftype) = attr ? DW_UNSND (attr) : DW_CC_normal; + /* Data member other than a C++ static data member. */ - /* We need to add the subroutine type to the die immediately so - we don't infinitely recurse when dealing with parameters - declared as the same subroutine type. */ - set_die_type (die, ftype, cu); + /* Get type of field. */ + fp->type = die_type (die, cu); - if (die->child != NULL) - { - struct type *void_type = objfile_type (cu->objfile)->builtin_void; - struct die_info *child_die; - int nparams, iparams; + SET_FIELD_BITPOS (*fp, 0); - /* Count the number of parameters. - FIXME: GDB currently ignores vararg functions, but knows about - vararg member functions. */ - nparams = 0; - child_die = die->child; - while (child_die && child_die->tag) + /* Get bit size of field (zero if none). */ + attr = dwarf2_attr (die, DW_AT_bit_size, cu); + if (attr) { - if (child_die->tag == DW_TAG_formal_parameter) - nparams++; - else if (child_die->tag == DW_TAG_unspecified_parameters) - TYPE_VARARGS (ftype) = 1; - child_die = sibling_die (child_die); + FIELD_BITSIZE (*fp) = DW_UNSND (attr); + } + else + { + FIELD_BITSIZE (*fp) = 0; } - /* Allocate storage for parameters and fill them in. */ - TYPE_NFIELDS (ftype) = nparams; - TYPE_FIELDS (ftype) = (struct field *) - TYPE_ZALLOC (ftype, nparams * sizeof (struct field)); - - /* TYPE_FIELD_TYPE must never be NULL. Pre-fill the array to ensure it - even if we error out during the parameters reading below. */ - for (iparams = 0; iparams < nparams; iparams++) - TYPE_FIELD_TYPE (ftype, iparams) = void_type; - - iparams = 0; - child_die = die->child; - while (child_die && child_die->tag) + /* Get bit offset of field. */ + if (handle_data_member_location (die, cu, &offset)) + SET_FIELD_BITPOS (*fp, offset * bits_per_byte); + attr = dwarf2_attr (die, DW_AT_bit_offset, cu); + if (attr) { - if (child_die->tag == DW_TAG_formal_parameter) + if (gdbarch_bits_big_endian (gdbarch)) { - /* Dwarf2 has no clean way to discern C++ static and non-static - member functions. G++ helps GDB by marking the first - parameter for non-static member functions (which is the - this pointer) as artificial. We pass this information - to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */ - attr = dwarf2_attr (child_die, DW_AT_artificial, cu); + /* For big endian bits, the DW_AT_bit_offset gives the + additional bit offset from the MSB of the containing + anonymous object to the MSB of the field. We don't + have to do anything special since we don't need to + know the size of the anonymous object. */ + FIELD_BITPOS (*fp) += DW_UNSND (attr); + } + else + { + /* For little endian bits, compute the bit offset to the + MSB of the anonymous object, subtract off the number of + bits from the MSB of the field to the MSB of the + object, and then subtract off the number of bits of + the field itself. The result is the bit offset of + the LSB of the field. */ + int anonymous_size; + int bit_offset = DW_UNSND (attr); + + attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr) - TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size = DW_UNSND (attr); + } else { - TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; - - /* GCC/43521: In java, the formal parameter - "this" is sometimes not marked with DW_AT_artificial. */ - if (cu->language == language_java) - { - const char *name = dwarf2_name (child_die, cu); - - if (name && !strcmp (name, "this")) - TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 1; - } + /* The size of the anonymous object containing + the bit field must be inferred from the type + attribute of the data member containing the + bit field. */ + anonymous_size = TYPE_LENGTH (fp->type); } - TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, cu); - iparams++; + FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte + - bit_offset - FIELD_BITSIZE (*fp); } - child_die = sibling_die (child_die); } - } - return ftype; -} + /* Get name of field. */ + fieldname = dwarf2_name (die, cu); + if (fieldname == NULL) + fieldname = ""; -static struct type * -read_typedef (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - const char *name = NULL; - struct type *this_type; + /* The name is already allocated along with this objfile, so we don't + need to duplicate it for the type. */ + fp->name = fieldname; - name = dwarf2_full_name (NULL, die, cu); - this_type = init_type (TYPE_CODE_TYPEDEF, 0, - TYPE_FLAG_TARGET_STUB, NULL, objfile); - TYPE_NAME (this_type) = (char *) name; - set_die_type (die, this_type, cu); - TYPE_TARGET_TYPE (this_type) = die_type (die, cu); - return this_type; -} + /* Change accessibility for artificial fields (e.g. virtual table + pointer or virtual base class pointer) to private. */ + if (dwarf2_attr (die, DW_AT_artificial, cu)) + { + FIELD_ARTIFICIAL (*fp) = 1; + new_field->accessibility = DW_ACCESS_private; + fip->non_public_fields = 1; + } + } + else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable) + { + /* C++ static member. */ -/* Find a representation of a given base type and install - it in the TYPE field of the die. */ + /* NOTE: carlton/2002-11-05: It should be a DW_TAG_member that + is a declaration, but all versions of G++ as of this writing + (so through at least 3.2.1) incorrectly generate + DW_TAG_variable tags. */ -static struct type * -read_base_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct type *type; - struct attribute *attr; - int encoding = 0, size = 0; - char *name; - enum type_code code = TYPE_CODE_INT; - int type_flags = 0; - struct type *target_type = NULL; + char *physname; - attr = dwarf2_attr (die, DW_AT_encoding, cu); - if (attr) - { - encoding = DW_UNSND (attr); - } - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - { - size = DW_UNSND (attr); + /* Get name of field. */ + fieldname = dwarf2_name (die, cu); + if (fieldname == NULL) + return; + + attr = dwarf2_attr (die, DW_AT_const_value, cu); + if (attr + /* Only create a symbol if this is an external value. + new_symbol checks this and puts the value in the global symbol + table, which we want. If it is not external, new_symbol + will try to put the value in cu->list_in_scope which is wrong. */ + && dwarf2_flag_true_p (die, DW_AT_external, cu)) + { + /* A static const member, not much different than an enum as far as + we're concerned, except that we can support more types. */ + new_symbol (die, NULL, cu); + } + + /* Get physical name. */ + physname = (char *) dwarf2_physname (fieldname, die, cu); + + /* The name is already allocated along with this objfile, so we don't + need to duplicate it for the type. */ + SET_FIELD_PHYSNAME (*fp, physname ? physname : ""); + FIELD_TYPE (*fp) = die_type (die, cu); + FIELD_NAME (*fp) = fieldname; } - name = dwarf2_name (die, cu); - if (!name) + else if (die->tag == DW_TAG_inheritance) { - complaint (&symfile_complaints, - _("DW_AT_name missing from DW_TAG_base_type")); + LONGEST offset; + + /* C++ base class field. */ + if (handle_data_member_location (die, cu, &offset)) + SET_FIELD_BITPOS (*fp, offset * bits_per_byte); + FIELD_BITSIZE (*fp) = 0; + FIELD_TYPE (*fp) = die_type (die, cu); + FIELD_NAME (*fp) = type_name_no_tag (fp->type); + fip->nbaseclasses++; } +} - switch (encoding) - { - case DW_ATE_address: - /* Turn DW_ATE_address into a void * pointer. */ - code = TYPE_CODE_PTR; - type_flags |= TYPE_FLAG_UNSIGNED; - target_type = init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile); - break; - case DW_ATE_boolean: - code = TYPE_CODE_BOOL; - type_flags |= TYPE_FLAG_UNSIGNED; - break; - case DW_ATE_complex_float: - code = TYPE_CODE_COMPLEX; - target_type = init_type (TYPE_CODE_FLT, size / 2, 0, NULL, objfile); - break; - case DW_ATE_decimal_float: - code = TYPE_CODE_DECFLOAT; - break; - case DW_ATE_float: - code = TYPE_CODE_FLT; - break; - case DW_ATE_signed: - break; - case DW_ATE_unsigned: - type_flags |= TYPE_FLAG_UNSIGNED; - break; - case DW_ATE_signed_char: - if (cu->language == language_ada || cu->language == language_m2 - || cu->language == language_pascal) - code = TYPE_CODE_CHAR; - break; - case DW_ATE_unsigned_char: - if (cu->language == language_ada || cu->language == language_m2 - || cu->language == language_pascal) - code = TYPE_CODE_CHAR; - type_flags |= TYPE_FLAG_UNSIGNED; - break; - case DW_ATE_UTF: - /* We just treat this as an integer and then recognize the - type by name elsewhere. */ - break; +/* Add a typedef defined in the scope of the FIP's class. */ - default: - complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"), - dwarf_type_encoding_name (encoding)); - break; - } +static void +dwarf2_add_typedef (struct field_info *fip, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct typedef_field_list *new_field; + struct attribute *attr; + struct typedef_field *fp; + char *fieldname = ""; - type = init_type (code, size, type_flags, NULL, objfile); - TYPE_NAME (type) = name; - TYPE_TARGET_TYPE (type) = target_type; + /* Allocate a new field list entry and link it in. */ + new_field = xzalloc (sizeof (*new_field)); + make_cleanup (xfree, new_field); - if (name && strcmp (name, "char") == 0) - TYPE_NOSIGN (type) = 1; + gdb_assert (die->tag == DW_TAG_typedef); - return set_die_type (die, type, cu); + fp = &new_field->field; + + /* Get name of field. */ + fp->name = dwarf2_name (die, cu); + if (fp->name == NULL) + return; + + fp->type = read_type_die (die, cu); + + new_field->next = fip->typedef_field_list; + fip->typedef_field_list = new_field; + fip->typedef_field_list_count++; } -/* Read the given DW_AT_subrange DIE. */ +/* Create the vector of fields, and attach it to the type. */ -static struct type * -read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) +static void +dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type, + struct dwarf2_cu *cu) { - struct gdbarch *gdbarch = get_objfile_arch (cu->objfile); - struct type *base_type; - struct type *range_type; - struct attribute *attr; - LONGEST low = 0; - LONGEST high = -1; - char *name; - LONGEST negative_mask; - - base_type = die_type (die, cu); + int nfields = fip->nfields; - /* The die_type call above may have already set the type for this DIE. */ - range_type = get_die_type (die, cu); - if (range_type) - return range_type; + /* Record the field count, allocate space for the array of fields, + and create blank accessibility bitfields if necessary. */ + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * nfields); + memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); - if (cu->language == language_fortran) + if (fip->non_public_fields && cu->language != language_ada) { - /* FORTRAN implies a lower bound of 1, if not given. */ - low = 1; - } + ALLOCATE_CPLUS_STRUCT_TYPE (type); - /* FIXME: For variable sized arrays either of these could be - a variable rather than a constant value. We'll allow it, - but we don't know how to handle it. */ - attr = dwarf2_attr (die, DW_AT_lower_bound, cu); - if (attr) - low = dwarf2_get_attr_constant_value (attr, 0); + TYPE_FIELD_PRIVATE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); - attr = dwarf2_attr (die, DW_AT_upper_bound, cu); - if (attr) - { - if (attr->form == DW_FORM_block1 || is_ref_attr (attr)) - { - /* GCC encodes arrays with unspecified or dynamic length - with a DW_FORM_block1 attribute or a reference attribute. - FIXME: GDB does not yet know how to handle dynamic - arrays properly, treat them as arrays with unspecified - length for now. + TYPE_FIELD_PROTECTED_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); - FIXME: jimb/2003-09-22: GDB does not really know - how to handle arrays of unspecified length - either; we just represent them as zero-length - arrays. Choose an appropriate upper bound given - the lower bound we've computed above. */ - high = low - 1; - } - else - high = dwarf2_get_attr_constant_value (attr, 1); + TYPE_FIELD_IGNORE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); } - else + + /* If the type has baseclasses, allocate and clear a bit vector for + TYPE_FIELD_VIRTUAL_BITS. */ + if (fip->nbaseclasses && cu->language != language_ada) { - attr = dwarf2_attr (die, DW_AT_count, cu); - if (attr) - { - int count = dwarf2_get_attr_constant_value (attr, 1); - high = low + count - 1; - } + int num_bytes = B_BYTES (fip->nbaseclasses); + unsigned char *pointer; + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + pointer = TYPE_ALLOC (type, num_bytes); + TYPE_FIELD_VIRTUAL_BITS (type) = pointer; + B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses); + TYPE_N_BASECLASSES (type) = fip->nbaseclasses; } - /* Dwarf-2 specifications explicitly allows to create subrange types - without specifying a base type. - In that case, the base type must be set to the type of - the lower bound, upper bound or count, in that order, if any of these - three attributes references an object that has a type. - If no base type is found, the Dwarf-2 specifications say that - a signed integer type of size equal to the size of an address should - be used. - For the following C code: `extern char gdb_int [];' - GCC produces an empty range DIE. - FIXME: muller/2010-05-28: Possible references to object for low bound, - high bound or count are not yet handled by this code. - */ - if (TYPE_CODE (base_type) == TYPE_CODE_VOID) + /* Copy the saved-up fields into the field vector. Start from the head of + the list, adding to the tail of the field array, so that they end up in + the same order in the array in which they were added to the list. */ + while (nfields-- > 0) { - struct objfile *objfile = cu->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - int addr_size = gdbarch_addr_bit (gdbarch) /8; - struct type *int_type = objfile_type (objfile)->builtin_int; + struct nextfield *fieldp; - /* Test "int", "long int", and "long long int" objfile types, - and select the first one having a size above or equal to the - architecture address size. */ - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; + if (fip->fields) + { + fieldp = fip->fields; + fip->fields = fieldp->next; + } else { - int_type = objfile_type (objfile)->builtin_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; - } + fieldp = fip->baseclasses; + fip->baseclasses = fieldp->next; } - } - - negative_mask = - (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1); - if (!TYPE_UNSIGNED (base_type) && (low & negative_mask)) - low |= negative_mask; - if (!TYPE_UNSIGNED (base_type) && (high & negative_mask)) - high |= negative_mask; - - range_type = create_range_type (NULL, base_type, low, high); - - /* Mark arrays with dynamic length at least as an array of unspecified - length. GDB could check the boundary but before it gets implemented at - least allow accessing the array elements. */ - if (attr && attr->form == DW_FORM_block1) - TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; - - name = dwarf2_name (die, cu); - if (name) - TYPE_NAME (range_type) = name; - - attr = dwarf2_attr (die, DW_AT_byte_size, cu); - if (attr) - TYPE_LENGTH (range_type) = DW_UNSND (attr); - - set_die_type (die, range_type, cu); - - /* set_die_type should be already done. */ - set_descriptive_type (range_type, die, cu); - - return range_type; -} - -static struct type * -read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct type *type; - - /* For now, we only support the C meaning of an unspecified type: void. */ - - type = init_type (TYPE_CODE_VOID, 0, 0, NULL, cu->objfile); - TYPE_NAME (type) = dwarf2_name (die, cu); - - return set_die_type (die, type, cu); -} - -/* Trivial hash function for die_info: the hash value of a DIE - is its offset in .debug_info for this objfile. */ - -static hashval_t -die_hash (const void *item) -{ - const struct die_info *die = item; - return die->offset; -} + TYPE_FIELD (type, nfields) = fieldp->field; + switch (fieldp->accessibility) + { + case DW_ACCESS_private: + if (cu->language != language_ada) + SET_TYPE_FIELD_PRIVATE (type, nfields); + break; -/* Trivial comparison function for die_info structures: two DIEs - are equal if they have the same offset. */ + case DW_ACCESS_protected: + if (cu->language != language_ada) + SET_TYPE_FIELD_PROTECTED (type, nfields); + break; -static int -die_eq (const void *item_lhs, const void *item_rhs) -{ - const struct die_info *die_lhs = item_lhs; - const struct die_info *die_rhs = item_rhs; + case DW_ACCESS_public: + break; - return die_lhs->offset == die_rhs->offset; + default: + /* Unknown accessibility. Complain and treat it as public. */ + { + complaint (&symfile_complaints, _("unsupported accessibility %d"), + fieldp->accessibility); + } + break; + } + if (nfields < fip->nbaseclasses) + { + switch (fieldp->virtuality) + { + case DW_VIRTUALITY_virtual: + case DW_VIRTUALITY_pure_virtual: + if (cu->language == language_ada) + error (_("unexpected virtuality in component of Ada type")); + SET_TYPE_FIELD_VIRTUAL (type, nfields); + break; + } + } + } } -/* Read a whole compilation unit into a linked list of dies. */ +/* Add a member function to the proper fieldlist. */ -static struct die_info * -read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu) +static void +dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + struct type *type, struct dwarf2_cu *cu) { - struct die_reader_specs reader_specs; - - gdb_assert (cu->die_hash == NULL); - cu->die_hash - = htab_create_alloc_ex (cu->header.length / 12, - die_hash, - die_eq, - NULL, - &cu->comp_unit_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); - - init_cu_die_reader (&reader_specs, cu); - - return read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL); -} + struct objfile *objfile = cu->objfile; + struct attribute *attr; + struct fnfieldlist *flp; + int i; + struct fn_field *fnp; + char *fieldname; + struct nextfnfield *new_fnfield; + struct type *this_type; + enum dwarf_access_attribute accessibility; -/* Main entry point for reading a DIE and all children. - Read the DIE and dump it if requested. */ + if (cu->language == language_ada) + error (_("unexpected member function in Ada type")); -static struct die_info * -read_die_and_children (const struct die_reader_specs *reader, - gdb_byte *info_ptr, - gdb_byte **new_info_ptr, - struct die_info *parent) -{ - struct die_info *result = read_die_and_children_1 (reader, info_ptr, - new_info_ptr, parent); + /* Get name of member function. */ + fieldname = dwarf2_name (die, cu); + if (fieldname == NULL) + return; - if (dwarf2_die_debug) + /* Look up member function name in fieldlist. */ + for (i = 0; i < fip->nfnfields; i++) { - fprintf_unfiltered (gdb_stdlog, - "\nRead die from %s of %s:\n", - reader->buffer == dwarf2_per_objfile->info.buffer - ? ".debug_info" - : reader->buffer == dwarf2_per_objfile->types.buffer - ? ".debug_types" - : "unknown section", - reader->abfd->filename); - dump_die (result, dwarf2_die_debug); + if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) + break; } - return result; -} + /* Create new list element if necessary. */ + if (i < fip->nfnfields) + flp = &fip->fnfieldlists[i]; + else + { + if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fip->fnfieldlists = (struct fnfieldlist *) + xrealloc (fip->fnfieldlists, + (fip->nfnfields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct fnfieldlist)); + if (fip->nfnfields == 0) + make_cleanup (free_current_contents, &fip->fnfieldlists); + } + flp = &fip->fnfieldlists[fip->nfnfields]; + flp->name = fieldname; + flp->length = 0; + flp->head = NULL; + i = fip->nfnfields++; + } -/* Read a single die and all its descendents. Set the die's sibling - field to NULL; set other fields in the die correctly, and set all - of the descendents' fields correctly. Set *NEW_INFO_PTR to the - location of the info_ptr after reading all of those dies. PARENT - is the parent of the die in question. */ + /* Create a new member function field and chain it to the field list + entry. */ + new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield)); + make_cleanup (xfree, new_fnfield); + memset (new_fnfield, 0, sizeof (struct nextfnfield)); + new_fnfield->next = flp->head; + flp->head = new_fnfield; + flp->length++; -static struct die_info * -read_die_and_children_1 (const struct die_reader_specs *reader, - gdb_byte *info_ptr, - gdb_byte **new_info_ptr, - struct die_info *parent) -{ - struct die_info *die; - gdb_byte *cur_ptr; - int has_children; + /* Fill in the member function field info. */ + fnp = &new_fnfield->fnfield; - cur_ptr = read_full_die (reader, &die, info_ptr, &has_children); - if (die == NULL) + /* Delay processing of the physname until later. */ + if (cu->language == language_cplus || cu->language == language_java) { - *new_info_ptr = cur_ptr; - return NULL; + add_to_method_list (type, i, flp->length - 1, fieldname, + die, cu); } - store_in_ref_table (die, reader->cu); - - if (has_children) - die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die); else { - die->child = NULL; - *new_info_ptr = cur_ptr; + char *physname = (char *) dwarf2_physname (fieldname, die, cu); + fnp->physname = physname ? physname : ""; } - die->sibling = NULL; - die->parent = parent; - return die; -} + fnp->type = alloc_type (objfile); + this_type = read_type_die (die, cu); + if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) + { + int nparams = TYPE_NFIELDS (this_type); -/* Read a die, all of its descendents, and all of its siblings; set - all of the fields of all of the dies correctly. Arguments are as - in read_die_and_children. */ + /* TYPE is the domain of this method, and THIS_TYPE is the type + of the method itself (TYPE_CODE_METHOD). */ + smash_to_method_type (fnp->type, type, + TYPE_TARGET_TYPE (this_type), + TYPE_FIELDS (this_type), + TYPE_NFIELDS (this_type), + TYPE_VARARGS (this_type)); -static struct die_info * -read_die_and_siblings (const struct die_reader_specs *reader, - gdb_byte *info_ptr, - gdb_byte **new_info_ptr, - struct die_info *parent) -{ - struct die_info *first_die, *last_sibling; - gdb_byte *cur_ptr; + /* Handle static member functions. + Dwarf2 has no clean way to discern C++ static and non-static + member functions. G++ helps GDB by marking the first + parameter for non-static member functions (which is the this + pointer) as artificial. We obtain this information from + read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */ + if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0) + fnp->voffset = VOFFSET_STATIC; + } + else + complaint (&symfile_complaints, _("member function type missing for '%s'"), + dwarf2_full_name (fieldname, die, cu)); - cur_ptr = info_ptr; - first_die = last_sibling = NULL; + /* Get fcontext from DW_AT_containing_type if present. */ + if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) + fnp->fcontext = die_containing_type (die, cu); - while (1) - { - struct die_info *die - = read_die_and_children_1 (reader, cur_ptr, &cur_ptr, parent); + /* dwarf2 doesn't have stubbed physical names, so the setting of is_const and + is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ - if (die == NULL) - { - *new_info_ptr = cur_ptr; - return first_die; - } + /* Get accessibility. */ + attr = dwarf2_attr (die, DW_AT_accessibility, cu); + if (attr) + accessibility = DW_UNSND (attr); + else + accessibility = dwarf2_default_access_attribute (die, cu); + switch (accessibility) + { + case DW_ACCESS_private: + fnp->is_private = 1; + break; + case DW_ACCESS_protected: + fnp->is_protected = 1; + break; + } - if (!first_die) - first_die = die; - else - last_sibling->sibling = die; + /* Check for artificial methods. */ + attr = dwarf2_attr (die, DW_AT_artificial, cu); + if (attr && DW_UNSND (attr) != 0) + fnp->is_artificial = 1; - last_sibling = die; + /* Get index in virtual function table if it is a virtual member + function. For older versions of GCC, this is an offset in the + appropriate virtual table, as specified by DW_AT_containing_type. + For everyone else, it is an expression to be evaluated relative + to the object address. */ + + attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu); + if (attr) + { + if (attr_form_is_block (attr) && DW_BLOCK (attr)->size > 0) + { + if (DW_BLOCK (attr)->data[0] == DW_OP_constu) + { + /* Old-style GCC. */ + fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; + } + else if (DW_BLOCK (attr)->data[0] == DW_OP_deref + || (DW_BLOCK (attr)->size > 1 + && DW_BLOCK (attr)->data[0] == DW_OP_deref_size + && DW_BLOCK (attr)->data[1] == cu->header.addr_size)) + { + struct dwarf_block blk; + int offset; + + offset = (DW_BLOCK (attr)->data[0] == DW_OP_deref + ? 1 : 2); + blk.size = DW_BLOCK (attr)->size - offset; + blk.data = DW_BLOCK (attr)->data + offset; + fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu); + if ((fnp->voffset % cu->header.addr_size) != 0) + dwarf2_complex_location_expr_complaint (); + else + fnp->voffset /= cu->header.addr_size; + fnp->voffset += 2; + } + else + dwarf2_complex_location_expr_complaint (); + + if (!fnp->fcontext) + fnp->fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0)); + } + else if (attr_form_is_section_offset (attr)) + { + dwarf2_complex_location_expr_complaint (); + } + else + { + dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location", + fieldname); + } + } + else + { + attr = dwarf2_attr (die, DW_AT_virtuality, cu); + if (attr && DW_UNSND (attr)) + { + /* GCC does this, as of 2008-08-25; PR debug/37237. */ + complaint (&symfile_complaints, + _("Member function \"%s\" (offset %d) is virtual " + "but the vtable offset is not specified"), + fieldname, die->offset); + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_CPLUS_DYNAMIC (type) = 1; + } } } -/* Read the die from the .debug_info section buffer. Set DIEP to - point to a newly allocated die with its information, except for its - child, sibling, and parent fields. Set HAS_CHILDREN to tell - whether the die has children or not. */ +/* Create the vector of member function fields, and attach it to the type. */ -static gdb_byte * -read_full_die (const struct die_reader_specs *reader, - struct die_info **diep, gdb_byte *info_ptr, - int *has_children) +static void +dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type, + struct dwarf2_cu *cu) { - unsigned int abbrev_number, bytes_read, i, offset; - struct abbrev_info *abbrev; - struct die_info *die; - struct dwarf2_cu *cu = reader->cu; - bfd *abfd = reader->abfd; + struct fnfieldlist *flp; + int total_length = 0; + int i; - offset = info_ptr - reader->buffer; - abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - if (!abbrev_number) + if (cu->language == language_ada) + error (_("unexpected member functions in Ada type")); + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *) + TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields); + + for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++) { - *diep = NULL; - *has_children = 0; - return info_ptr; - } + struct nextfnfield *nfp = flp->head; + struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i); + int k; - abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); - if (!abbrev) - error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), - abbrev_number, - bfd_get_filename (abfd)); + TYPE_FN_FIELDLIST_NAME (type, i) = flp->name; + TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length; + fn_flp->fn_fields = (struct fn_field *) + TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length); + for (k = flp->length; (k--, nfp); nfp = nfp->next) + fn_flp->fn_fields[k] = nfp->fnfield; - die = dwarf_alloc_die (cu, abbrev->num_attrs); - die->offset = offset; - die->tag = abbrev->tag; - die->abbrev = abbrev_number; + total_length += flp->length; + } - die->num_attrs = abbrev->num_attrs; + TYPE_NFN_FIELDS (type) = fip->nfnfields; + TYPE_NFN_FIELDS_TOTAL (type) = total_length; +} - for (i = 0; i < abbrev->num_attrs; ++i) - info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i], - abfd, info_ptr, cu); +/* Returns non-zero if NAME is the name of a vtable member in CU's + language, zero otherwise. */ +static int +is_vtable_name (const char *name, struct dwarf2_cu *cu) +{ + static const char vptr[] = "_vptr"; + static const char vtable[] = "vtable"; - *diep = die; - *has_children = abbrev->has_children; - return info_ptr; + /* Look for the C++ and Java forms of the vtable. */ + if ((cu->language == language_java + && strncmp (name, vtable, sizeof (vtable) - 1) == 0) + || (strncmp (name, vptr, sizeof (vptr) - 1) == 0 + && is_cplus_marker (name[sizeof (vptr) - 1]))) + return 1; + + return 0; } -/* In DWARF version 2, the description of the debugging information is - stored in a separate .debug_abbrev section. Before we read any - dies from a section we read in all abbreviations and install them - in a hash table. This function also sets flags in CU describing - the data found in the abbrev table. */ +/* GCC outputs unnamed structures that are really pointers to member + functions, with the ABI-specified layout. If TYPE describes + such a structure, smash it into a member function type. + + GCC shouldn't do this; it should just output pointer to member DIEs. + This is GCC PR debug/28767. */ static void -dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu) +quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile) { - struct comp_unit_head *cu_header = &cu->header; - gdb_byte *abbrev_ptr; - struct abbrev_info *cur_abbrev; - unsigned int abbrev_number, bytes_read, abbrev_name; - unsigned int abbrev_form, hash_number; - struct attr_abbrev *cur_attrs; - unsigned int allocated_attrs; + struct type *pfn_type, *domain_type, *new_type; - /* Initialize dwarf2 abbrevs */ - obstack_init (&cu->abbrev_obstack); - cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack, - (ABBREV_HASH_SIZE - * sizeof (struct abbrev_info *))); - memset (cu->dwarf2_abbrevs, 0, - ABBREV_HASH_SIZE * sizeof (struct abbrev_info *)); + /* Check for a structure with no name and two children. */ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 2) + return; - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->abbrev); - abbrev_ptr = dwarf2_per_objfile->abbrev.buffer + cu_header->abbrev_offset; - abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; + /* Check for __pfn and __delta members. */ + if (TYPE_FIELD_NAME (type, 0) == NULL + || strcmp (TYPE_FIELD_NAME (type, 0), "__pfn") != 0 + || TYPE_FIELD_NAME (type, 1) == NULL + || strcmp (TYPE_FIELD_NAME (type, 1), "__delta") != 0) + return; - allocated_attrs = ATTR_ALLOC_CHUNK; - cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev)); + /* Find the type of the method. */ + pfn_type = TYPE_FIELD_TYPE (type, 0); + if (pfn_type == NULL + || TYPE_CODE (pfn_type) != TYPE_CODE_PTR + || TYPE_CODE (TYPE_TARGET_TYPE (pfn_type)) != TYPE_CODE_FUNC) + return; - /* loop until we reach an abbrev number of 0 */ - while (abbrev_number) - { - cur_abbrev = dwarf_alloc_abbrev (cu); + /* Look for the "this" argument. */ + pfn_type = TYPE_TARGET_TYPE (pfn_type); + if (TYPE_NFIELDS (pfn_type) == 0 + /* || TYPE_FIELD_TYPE (pfn_type, 0) == NULL */ + || TYPE_CODE (TYPE_FIELD_TYPE (pfn_type, 0)) != TYPE_CODE_PTR) + return; - /* read in abbrev header */ - cur_abbrev->number = abbrev_number; - cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr); - abbrev_ptr += 1; + domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0)); + new_type = alloc_type (objfile); + smash_to_method_type (new_type, domain_type, TYPE_TARGET_TYPE (pfn_type), + TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), + TYPE_VARARGS (pfn_type)); + smash_to_methodptr_type (type, new_type); +} - if (cur_abbrev->tag == DW_TAG_namespace) - cu->has_namespace_info = 1; +/* Called when we find the DIE that starts a structure or union scope + (definition) to create a type for the structure or union. Fill in + the type's name and general properties; the members will not be + processed until process_structure_type. - /* now read in declarations */ - abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - while (abbrev_name) - { - if (cur_abbrev->num_attrs == allocated_attrs) - { - allocated_attrs += ATTR_ALLOC_CHUNK; - cur_attrs - = xrealloc (cur_attrs, (allocated_attrs - * sizeof (struct attr_abbrev))); - } + NOTE: we need to call these functions regardless of whether or not the + DIE has a DW_AT_name attribute, since it might be an anonymous + structure or union. This gets the type entered into our set of + user defined types. - /* Record whether this compilation unit might have - inter-compilation-unit references. If we don't know what form - this attribute will have, then it might potentially be a - DW_FORM_ref_addr, so we conservatively expect inter-CU - references. */ - - if (abbrev_form == DW_FORM_ref_addr - || abbrev_form == DW_FORM_indirect) - cu->has_form_ref_addr = 1; + However, if the structure is incomplete (an opaque struct/union) + then suppress creating a symbol table entry for it since gdb only + wants to find the one with the complete definition. Note that if + it is complete, we just call new_symbol, which does it's own + checking about whether the struct/union is anonymous or not (and + suppresses creating a symbol table entry itself). */ - cur_attrs[cur_abbrev->num_attrs].name = abbrev_name; - cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form; - abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - } +static struct type * +read_structure_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct type *type; + struct attribute *attr; + char *name; - cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack, - (cur_abbrev->num_attrs - * sizeof (struct attr_abbrev))); - memcpy (cur_abbrev->attrs, cur_attrs, - cur_abbrev->num_attrs * sizeof (struct attr_abbrev)); + /* If the definition of this type lives in .debug_types, read that type. + Don't follow DW_AT_specification though, that will take us back up + the chain and we want to go down. */ + attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); + if (attr) + { + struct dwarf2_cu *type_cu = cu; + struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); - hash_number = abbrev_number % ABBREV_HASH_SIZE; - cur_abbrev->next = cu->dwarf2_abbrevs[hash_number]; - cu->dwarf2_abbrevs[hash_number] = cur_abbrev; + /* We could just recurse on read_structure_type, but we need to call + get_die_type to ensure only one type for this DIE is created. + This is important, for example, because for c++ classes we need + TYPE_NAME set which is only done by new_symbol. Blech. */ + type = read_type_die (type_die, type_cu); - /* Get next abbreviation. - Under Irix6 the abbreviations for a compilation unit are not - always properly terminated with an abbrev number of 0. - Exit loop if we encounter an abbreviation which we have - already read (which means we are about to read the abbreviations - for the next compile unit) or if the end of the abbreviation - table is reached. */ - if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev.buffer) - >= dwarf2_per_objfile->abbrev.size) - break; - abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL) - break; + /* TYPE_CU may not be the same as CU. + Ensure TYPE is recorded in CU's type_hash table. */ + return set_die_type (die, type, cu); } - xfree (cur_attrs); -} - -/* Release the memory used by the abbrev table for a compilation unit. */ - -static void -dwarf2_free_abbrev_table (void *ptr_to_cu) -{ - struct dwarf2_cu *cu = ptr_to_cu; - - obstack_free (&cu->abbrev_obstack, NULL); - cu->dwarf2_abbrevs = NULL; -} + type = alloc_type (objfile); + INIT_CPLUS_SPECIFIC (type); -/* Lookup an abbrev_info structure in the abbrev hash table. */ + name = dwarf2_name (die, cu); + if (name != NULL) + { + if (cu->language == language_cplus + || cu->language == language_java) + { + char *full_name = (char *) dwarf2_full_name (name, die, cu); -static struct abbrev_info * -dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu) -{ - unsigned int hash_number; - struct abbrev_info *abbrev; + /* dwarf2_full_name might have already finished building the DIE's + type. If so, there is no need to continue. */ + if (get_die_type (die, cu) != NULL) + return get_die_type (die, cu); - hash_number = number % ABBREV_HASH_SIZE; - abbrev = cu->dwarf2_abbrevs[hash_number]; + TYPE_TAG_NAME (type) = full_name; + if (die->tag == DW_TAG_structure_type + || die->tag == DW_TAG_class_type) + TYPE_NAME (type) = TYPE_TAG_NAME (type); + } + else + { + /* The name is already allocated along with this objfile, so + we don't need to duplicate it for the type. */ + TYPE_TAG_NAME (type) = (char *) name; + if (die->tag == DW_TAG_class_type) + TYPE_NAME (type) = TYPE_TAG_NAME (type); + } + } - while (abbrev) + if (die->tag == DW_TAG_structure_type) { - if (abbrev->number == number) - return abbrev; - else - abbrev = abbrev->next; + TYPE_CODE (type) = TYPE_CODE_STRUCT; + } + else if (die->tag == DW_TAG_union_type) + { + TYPE_CODE (type) = TYPE_CODE_UNION; + } + else + { + TYPE_CODE (type) = TYPE_CODE_CLASS; } - return NULL; -} -/* Returns nonzero if TAG represents a type that we might generate a partial - symbol for. */ + if (cu->language == language_cplus && die->tag == DW_TAG_class_type) + TYPE_DECLARED_CLASS (type) = 1; -static int -is_type_tag_for_partial (int tag) -{ - switch (tag) + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) { -#if 0 - /* Some types that would be reasonable to generate partial symbols for, - that we don't at present. */ - case DW_TAG_array_type: - case DW_TAG_file_type: - case DW_TAG_ptr_to_member_type: - case DW_TAG_set_type: - case DW_TAG_string_type: - case DW_TAG_subroutine_type: -#endif - case DW_TAG_base_type: - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_enumeration_type: - case DW_TAG_structure_type: - case DW_TAG_subrange_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - return 1; - default: - return 0; + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = 0; } -} -/* Load all DIEs that are interesting for partial symbols into memory. */ + TYPE_STUB_SUPPORTED (type) = 1; + if (die_is_declaration (die, cu)) + TYPE_STUB (type) = 1; + else if (attr == NULL && die->child == NULL + && producer_is_realview (cu->producer)) + /* RealView does not output the required DW_AT_declaration + on incomplete types. */ + TYPE_STUB (type) = 1; -static struct partial_die_info * -load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr, - int building_psymtab, struct dwarf2_cu *cu) -{ - struct partial_die_info *part_die; - struct partial_die_info *parent_die, *last_die, *first_die = NULL; - struct abbrev_info *abbrev; - unsigned int bytes_read; - unsigned int load_all = 0; + /* We need to add the type field to the die immediately so we don't + infinitely recurse when dealing with pointers to the structure + type within the structure itself. */ + set_die_type (die, type, cu); - int nesting_level = 1; + /* set_die_type should be already done. */ + set_descriptive_type (type, die, cu); - parent_die = NULL; - last_die = NULL; + return type; +} - if (cu->per_cu && cu->per_cu->load_all_dies) - load_all = 1; +/* Finish creating a structure or union type, including filling in + its members and creating a symbol for it. */ - cu->partial_dies - = htab_create_alloc_ex (cu->header.length / 12, - partial_die_hash, - partial_die_eq, - NULL, - &cu->comp_unit_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); +static void +process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct die_info *child_die = die->child; + struct type *type; - part_die = obstack_alloc (&cu->comp_unit_obstack, - sizeof (struct partial_die_info)); + type = get_die_type (die, cu); + if (type == NULL) + type = read_structure_type (die, cu); - while (1) + if (die->child != NULL && ! die_is_declaration (die, cu)) { - abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); + struct field_info fi; + struct die_info *child_die; + VEC (symbolp) *template_args = NULL; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); - /* A NULL abbrev means the end of a series of children. */ - if (abbrev == NULL) + memset (&fi, 0, sizeof (struct field_info)); + + child_die = die->child; + + while (child_die && child_die->tag) { - if (--nesting_level == 0) + if (child_die->tag == DW_TAG_member + || child_die->tag == DW_TAG_variable) { - /* PART_DIE was probably the last thing allocated on the - comp_unit_obstack, so we could call obstack_free - here. We don't do that because the waste is small, - and will be cleaned up when we're done with this - compilation unit. This way, we're also more robust - against other users of the comp_unit_obstack. */ - return first_die; + /* NOTE: carlton/2002-11-05: A C++ static data member + should be a DW_TAG_member that is a declaration, but + all versions of G++ as of this writing (so through at + least 3.2.1) incorrectly generate DW_TAG_variable + tags for them instead. */ + dwarf2_add_field (&fi, child_die, cu); } - info_ptr += bytes_read; - last_die = parent_die; - parent_die = parent_die->die_parent; - continue; + else if (child_die->tag == DW_TAG_subprogram) + { + /* C++ member function. */ + dwarf2_add_member_fn (&fi, child_die, type, cu); + } + else if (child_die->tag == DW_TAG_inheritance) + { + /* C++ base class field. */ + dwarf2_add_field (&fi, child_die, cu); + } + else if (child_die->tag == DW_TAG_typedef) + dwarf2_add_typedef (&fi, child_die, cu); + else if (child_die->tag == DW_TAG_template_type_param + || child_die->tag == DW_TAG_template_value_param) + { + struct symbol *arg = new_symbol (child_die, NULL, cu); + + if (arg != NULL) + VEC_safe_push (symbolp, template_args, arg); + } + + child_die = sibling_die (child_die); } - /* Check whether this DIE is interesting enough to save. Normally - we would not be interested in members here, but there may be - later variables referencing them via DW_AT_specification (for - static members). */ - if (!load_all - && !is_type_tag_for_partial (abbrev->tag) - && abbrev->tag != DW_TAG_enumerator - && abbrev->tag != DW_TAG_subprogram - && abbrev->tag != DW_TAG_lexical_block - && abbrev->tag != DW_TAG_variable - && abbrev->tag != DW_TAG_namespace - && abbrev->tag != DW_TAG_module - && abbrev->tag != DW_TAG_member) - { - /* Otherwise we skip to the next sibling, if any. */ - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); - continue; - } - - info_ptr = read_partial_die (part_die, abbrev, bytes_read, abfd, - buffer, info_ptr, cu); - - /* This two-pass algorithm for processing partial symbols has a - high cost in cache pressure. Thus, handle some simple cases - here which cover the majority of C partial symbols. DIEs - which neither have specification tags in them, nor could have - specification tags elsewhere pointing at them, can simply be - processed and discarded. - - This segment is also optional; scan_partial_symbols and - add_partial_symbol will handle these DIEs if we chain - them in normally. When compilers which do not emit large - quantities of duplicate debug information are more common, - this code can probably be removed. */ - - /* Any complete simple types at the top level (pretty much all - of them, for a language without namespaces), can be processed - directly. */ - if (parent_die == NULL - && part_die->has_specification == 0 - && part_die->is_declaration == 0 - && (part_die->tag == DW_TAG_typedef - || part_die->tag == DW_TAG_base_type - || part_die->tag == DW_TAG_subrange_type)) + /* Attach template arguments to type. */ + if (! VEC_empty (symbolp, template_args)) { - if (building_psymtab && part_die->name != NULL) - add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, - VAR_DOMAIN, LOC_TYPEDEF, - &cu->objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, cu->objfile); - info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); - continue; + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_N_TEMPLATE_ARGUMENTS (type) + = VEC_length (symbolp, template_args); + TYPE_TEMPLATE_ARGUMENTS (type) + = obstack_alloc (&objfile->objfile_obstack, + (TYPE_N_TEMPLATE_ARGUMENTS (type) + * sizeof (struct symbol *))); + memcpy (TYPE_TEMPLATE_ARGUMENTS (type), + VEC_address (symbolp, template_args), + (TYPE_N_TEMPLATE_ARGUMENTS (type) + * sizeof (struct symbol *))); + VEC_free (symbolp, template_args); } - /* If we're at the second level, and we're an enumerator, and - our parent has no specification (meaning possibly lives in a - namespace elsewhere), then we can add the partial symbol now - instead of queueing it. */ - if (part_die->tag == DW_TAG_enumerator - && parent_die != NULL - && parent_die->die_parent == NULL - && parent_die->tag == DW_TAG_enumeration_type - && parent_die->has_specification == 0) + /* Attach fields and member functions to the type. */ + if (fi.nfields) + dwarf2_attach_fields_to_type (&fi, type, cu); + if (fi.nfnfields) { - if (part_die->name == NULL) - complaint (&symfile_complaints, _("malformed enumerator DIE ignored")); - else if (building_psymtab) - add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, - VAR_DOMAIN, LOC_CONST, - (cu->language == language_cplus - || cu->language == language_java) - ? &cu->objfile->global_psymbols - : &cu->objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, cu->objfile); + dwarf2_attach_fn_fields_to_type (&fi, type, cu); - info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); - continue; - } + /* Get the type which refers to the base class (possibly this + class itself) which contains the vtable pointer for the current + class from the DW_AT_containing_type attribute. This use of + DW_AT_containing_type is a GNU extension. */ - /* We'll save this DIE so link it in. */ - part_die->die_parent = parent_die; - part_die->die_sibling = NULL; - part_die->die_child = NULL; + if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) + { + struct type *t = die_containing_type (die, cu); - if (last_die && last_die == parent_die) - last_die->die_child = part_die; - else if (last_die) - last_die->die_sibling = part_die; + TYPE_VPTR_BASETYPE (type) = t; + if (type == t) + { + int i; - last_die = part_die; + /* Our own class provides vtbl ptr. */ + for (i = TYPE_NFIELDS (t) - 1; + i >= TYPE_N_BASECLASSES (t); + --i) + { + char *fieldname = TYPE_FIELD_NAME (t, i); - if (first_die == NULL) - first_die = part_die; + if (is_vtable_name (fieldname, cu)) + { + TYPE_VPTR_FIELDNO (type) = i; + break; + } + } - /* Maybe add the DIE to the hash table. Not all DIEs that we - find interesting need to be in the hash table, because we - also have the parent/sibling/child chains; only those that we - might refer to by offset later during partial symbol reading. + /* Complain if virtual function table field not found. */ + if (i < TYPE_N_BASECLASSES (t)) + complaint (&symfile_complaints, + _("virtual function table pointer " + "not found when defining class '%s'"), + TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : + ""); + } + else + { + TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t); + } + } + else if (cu->producer + && strncmp (cu->producer, + "IBM(R) XL C/C++ Advanced Edition", 32) == 0) + { + /* The IBM XLC compiler does not provide direct indication + of the containing type, but the vtable pointer is + always named __vfp. */ - For now this means things that might have be the target of a - DW_AT_specification, DW_AT_abstract_origin, or - DW_AT_extension. DW_AT_extension will refer only to - namespaces; DW_AT_abstract_origin refers to functions (and - many things under the function DIE, but we do not recurse - into function DIEs during partial symbol reading) and - possibly variables as well; DW_AT_specification refers to - declarations. Declarations ought to have the DW_AT_declaration - flag. It happens that GCC forgets to put it in sometimes, but - only for functions, not for types. + int i; - Adding more things than necessary to the hash table is harmless - except for the performance cost. Adding too few will result in - wasted time in find_partial_die, when we reread the compilation - unit with load_all_dies set. */ + for (i = TYPE_NFIELDS (type) - 1; + i >= TYPE_N_BASECLASSES (type); + --i) + { + if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0) + { + TYPE_VPTR_FIELDNO (type) = i; + TYPE_VPTR_BASETYPE (type) = type; + break; + } + } + } + } - if (load_all - || abbrev->tag == DW_TAG_subprogram - || abbrev->tag == DW_TAG_variable - || abbrev->tag == DW_TAG_namespace - || part_die->is_declaration) + /* Copy fi.typedef_field_list linked list elements content into the + allocated array TYPE_TYPEDEF_FIELD_ARRAY (type). */ + if (fi.typedef_field_list) { - void **slot; + int i = fi.typedef_field_list_count; - slot = htab_find_slot_with_hash (cu->partial_dies, part_die, - part_die->offset, INSERT); - *slot = part_die; + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_TYPEDEF_FIELD_ARRAY (type) + = TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i); + TYPE_TYPEDEF_FIELD_COUNT (type) = i; + + /* Reverse the list order to keep the debug info elements order. */ + while (--i >= 0) + { + struct typedef_field *dest, *src; + + dest = &TYPE_TYPEDEF_FIELD (type, i); + src = &fi.typedef_field_list->field; + fi.typedef_field_list = fi.typedef_field_list->next; + *dest = *src; + } } - part_die = obstack_alloc (&cu->comp_unit_obstack, - sizeof (struct partial_die_info)); + do_cleanups (back_to); + } - /* For some DIEs we want to follow their children (if any). For C - we have no reason to follow the children of structures; for other - languages we have to, both so that we can get at method physnames - to infer fully qualified class names, and for DW_AT_specification. + quirk_gcc_member_function_pointer (type, cu->objfile); - For Ada, we need to scan the children of subprograms and lexical - blocks as well because Ada allows the definition of nested - entities that could be interesting for the debugger, such as - nested subprograms for instance. */ - if (last_die->has_children - && (load_all - || last_die->tag == DW_TAG_namespace - || last_die->tag == DW_TAG_module - || last_die->tag == DW_TAG_enumeration_type - || (cu->language != language_c - && (last_die->tag == DW_TAG_class_type - || last_die->tag == DW_TAG_interface_type - || last_die->tag == DW_TAG_structure_type - || last_die->tag == DW_TAG_union_type)) - || (cu->language == language_ada - && (last_die->tag == DW_TAG_subprogram - || last_die->tag == DW_TAG_lexical_block)))) + /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its + snapshots) has been known to create a die giving a declaration + for a class that has, as a child, a die giving a definition for a + nested class. So we have to process our children even if the + current die is a declaration. Normally, of course, a declaration + won't have any children at all. */ + + while (child_die != NULL && child_die->tag) + { + if (child_die->tag == DW_TAG_member + || child_die->tag == DW_TAG_variable + || child_die->tag == DW_TAG_inheritance + || child_die->tag == DW_TAG_template_value_param + || child_die->tag == DW_TAG_template_type_param) { - nesting_level++; - parent_die = last_die; - continue; + /* Do nothing. */ } + else + process_die (child_die, cu); - /* Otherwise we skip to the next sibling, if any. */ - info_ptr = locate_pdi_sibling (last_die, buffer, info_ptr, abfd, cu); - - /* Back to the top, do it again. */ + child_die = sibling_die (child_die); } + + /* Do not consider external references. According to the DWARF standard, + these DIEs are identified by the fact that they have no byte_size + attribute, and a declaration attribute. */ + if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL + || !die_is_declaration (die, cu)) + new_symbol (die, type, cu); } -/* Read a minimal amount of information into the minimal die structure. */ +/* Given a DW_AT_enumeration_type die, set its type. We do not + complete the type's fields yet, or create any symbols. */ -static gdb_byte * -read_partial_die (struct partial_die_info *part_die, - struct abbrev_info *abbrev, - unsigned int abbrev_len, bfd *abfd, - gdb_byte *buffer, gdb_byte *info_ptr, - struct dwarf2_cu *cu) +static struct type * +read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) { - unsigned int i; - struct attribute attr; - int has_low_pc_attr = 0; - int has_high_pc_attr = 0; + struct objfile *objfile = cu->objfile; + struct type *type; + struct attribute *attr; + const char *name; - memset (part_die, 0, sizeof (struct partial_die_info)); + /* If the definition of this type lives in .debug_types, read that type. + Don't follow DW_AT_specification though, that will take us back up + the chain and we want to go down. */ + attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); + if (attr) + { + struct dwarf2_cu *type_cu = cu; + struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); - part_die->offset = info_ptr - buffer; + type = read_type_die (type_die, type_cu); - info_ptr += abbrev_len; + /* TYPE_CU may not be the same as CU. + Ensure TYPE is recorded in CU's type_hash table. */ + return set_die_type (die, type, cu); + } - if (abbrev == NULL) - return info_ptr; + type = alloc_type (objfile); - part_die->tag = abbrev->tag; - part_die->has_children = abbrev->has_children; + TYPE_CODE (type) = TYPE_CODE_ENUM; + name = dwarf2_full_name (NULL, die, cu); + if (name != NULL) + TYPE_TAG_NAME (type) = (char *) name; - for (i = 0; i < abbrev->num_attrs; ++i) + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) { - info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu); - - /* Store the data if it is of an attribute we want to keep in a - partial symbol table. */ - switch (attr.name) - { - case DW_AT_name: - switch (part_die->tag) - { - case DW_TAG_compile_unit: - case DW_TAG_type_unit: - /* Compilation units have a DW_AT_name that is a filename, not - a source language identifier. */ - case DW_TAG_enumeration_type: - case DW_TAG_enumerator: - /* These tags always have simple identifiers already; no need - to canonicalize them. */ - part_die->name = DW_STRING (&attr); - break; - default: - part_die->name - = dwarf2_canonicalize_name (DW_STRING (&attr), cu, - &cu->objfile->objfile_obstack); - break; - } - break; - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: - /* Note that both forms of linkage name might appear. We - assume they will be the same, and we only store the last - one we see. */ - if (cu->language == language_ada) - part_die->name = DW_STRING (&attr); - break; - case DW_AT_low_pc: - has_low_pc_attr = 1; - part_die->lowpc = DW_ADDR (&attr); - break; - case DW_AT_high_pc: - has_high_pc_attr = 1; - part_die->highpc = DW_ADDR (&attr); - break; - case DW_AT_location: - /* Support the .debug_loc offsets */ - if (attr_form_is_block (&attr)) - { - part_die->locdesc = DW_BLOCK (&attr); - } - else if (attr_form_is_section_offset (&attr)) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_location", - "partial symbol information"); - } - break; - case DW_AT_external: - part_die->is_external = DW_UNSND (&attr); - break; - case DW_AT_declaration: - part_die->is_declaration = DW_UNSND (&attr); - break; - case DW_AT_type: - part_die->has_type = 1; - break; - case DW_AT_abstract_origin: - case DW_AT_specification: - case DW_AT_extension: - part_die->has_specification = 1; - part_die->spec_offset = dwarf2_get_ref_die_offset (&attr); - break; - case DW_AT_sibling: - /* Ignore absolute siblings, they might point outside of - the current compile unit. */ - if (attr.form == DW_FORM_ref_addr) - complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); - else - part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr); - break; - case DW_AT_byte_size: - part_die->has_byte_size = 1; - break; - case DW_AT_calling_convention: - /* DWARF doesn't provide a way to identify a program's source-level - entry point. DW_AT_calling_convention attributes are only meant - to describe functions' calling conventions. - - However, because it's a necessary piece of information in - Fortran, and because DW_CC_program is the only piece of debugging - information whose definition refers to a 'main program' at all, - several compilers have begun marking Fortran main programs with - DW_CC_program --- even when those functions use the standard - calling conventions. - - So until DWARF specifies a way to provide this information and - compilers pick up the new representation, we'll support this - practice. */ - if (DW_UNSND (&attr) == DW_CC_program - && cu->language == language_fortran) - set_main_name (part_die->name); - break; - default: - break; - } + TYPE_LENGTH (type) = DW_UNSND (attr); + } + else + { + TYPE_LENGTH (type) = 0; } - /* When using the GNU linker, .gnu.linkonce. sections are used to - eliminate duplicate copies of functions and vtables and such. - The linker will arbitrarily choose one and discard the others. - The AT_*_pc values for such functions refer to local labels in - these sections. If the section from that file was discarded, the - labels are not in the output, so the relocs get a value of 0. - If this is a discarded function, mark the pc bounds as invalid, - so that GDB will ignore it. */ - if (has_low_pc_attr && has_high_pc_attr - && part_die->lowpc < part_die->highpc - && (part_die->lowpc != 0 - || dwarf2_per_objfile->has_section_at_zero)) - part_die->has_pc_info = 1; + /* The enumeration DIE can be incomplete. In Ada, any type can be + declared as private in the package spec, and then defined only + inside the package body. Such types are known as Taft Amendment + Types. When another package uses such a type, an incomplete DIE + may be generated by the compiler. */ + if (die_is_declaration (die, cu)) + TYPE_STUB (type) = 1; - return info_ptr; + return set_die_type (die, type, cu); } -/* Find a cached partial DIE at OFFSET in CU. */ - -static struct partial_die_info * -find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu) -{ - struct partial_die_info *lookup_die = NULL; - struct partial_die_info part_die; - - part_die.offset = offset; - lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset); - - return lookup_die; -} +/* Given a pointer to a die which begins an enumeration, process all + the dies that define the members of the enumeration, and create the + symbol for the enumeration type. -/* Find a partial DIE at OFFSET, which may or may not be in CU, - except in the case of .debug_types DIEs which do not reference - outside their CU (they do however referencing other types via - DW_FORM_sig8). */ + NOTE: We reverse the order of the element list. */ -static struct partial_die_info * -find_partial_die (unsigned int offset, struct dwarf2_cu *cu) +static void +process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) { - struct dwarf2_per_cu_data *per_cu = NULL; - struct partial_die_info *pd = NULL; + struct type *this_type; - if (cu->per_cu->from_debug_types) - { - pd = find_partial_die_in_comp_unit (offset, cu); - if (pd != NULL) - return pd; - goto not_found; - } + this_type = get_die_type (die, cu); + if (this_type == NULL) + this_type = read_enumeration_type (die, cu); - if (offset_in_cu_p (&cu->header, offset)) + if (die->child != NULL) { - pd = find_partial_die_in_comp_unit (offset, cu); - if (pd != NULL) - return pd; - } + struct die_info *child_die; + struct symbol *sym; + struct field *fields = NULL; + int num_fields = 0; + int unsigned_enum = 1; + char *name; - per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); + child_die = die->child; + while (child_die && child_die->tag) + { + if (child_die->tag != DW_TAG_enumerator) + { + process_die (child_die, cu); + } + else + { + name = dwarf2_name (child_die, cu); + if (name) + { + sym = new_symbol (child_die, this_type, cu); + if (SYMBOL_VALUE (sym) < 0) + unsigned_enum = 0; - if (per_cu->cu == NULL) - { - load_partial_comp_unit (per_cu, cu->objfile); - per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; - dwarf2_per_objfile->read_in_chain = per_cu; - } + if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fields = (struct field *) + xrealloc (fields, + (num_fields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct field)); + } - per_cu->cu->last_used = 0; - pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + FIELD_NAME (fields[num_fields]) = SYMBOL_LINKAGE_NAME (sym); + FIELD_TYPE (fields[num_fields]) = NULL; + SET_FIELD_BITPOS (fields[num_fields], SYMBOL_VALUE (sym)); + FIELD_BITSIZE (fields[num_fields]) = 0; - if (pd == NULL && per_cu->load_all_dies == 0) - { - struct cleanup *back_to; - struct partial_die_info comp_unit_die; - struct abbrev_info *abbrev; - unsigned int bytes_read; - char *info_ptr; + num_fields++; + } + } - per_cu->load_all_dies = 1; + child_die = sibling_die (child_die); + } - /* Re-read the DIEs. */ - back_to = make_cleanup (null_cleanup, 0); - if (per_cu->cu->dwarf2_abbrevs == NULL) + if (num_fields) { - dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu); - make_cleanup (dwarf2_free_abbrev_table, per_cu->cu); - } - info_ptr = (dwarf2_per_objfile->info.buffer - + per_cu->cu->header.offset - + per_cu->cu->header.first_die_offset); - abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu); - info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, - per_cu->cu->objfile->obfd, - dwarf2_per_objfile->info.buffer, info_ptr, - per_cu->cu); - if (comp_unit_die.has_children) - load_partial_dies (per_cu->cu->objfile->obfd, - dwarf2_per_objfile->info.buffer, info_ptr, - 0, per_cu->cu); - do_cleanups (back_to); - - pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + TYPE_NFIELDS (this_type) = num_fields; + TYPE_FIELDS (this_type) = (struct field *) + TYPE_ALLOC (this_type, sizeof (struct field) * num_fields); + memcpy (TYPE_FIELDS (this_type), fields, + sizeof (struct field) * num_fields); + xfree (fields); + } + if (unsigned_enum) + TYPE_UNSIGNED (this_type) = 1; } - not_found: - - if (pd == NULL) - internal_error (__FILE__, __LINE__, - _("could not find partial DIE 0x%x in cache [from module %s]\n"), - offset, bfd_get_filename (cu->objfile->obfd)); - return pd; + new_symbol (die, this_type, cu); } -/* Adjust PART_DIE before generating a symbol for it. This function - may set the is_external flag or change the DIE's name. */ +/* Extract all information from a DW_TAG_array_type DIE and put it in + the DIE's type field. For now, this only handles one dimensional + arrays. */ -static void -fixup_partial_die (struct partial_die_info *part_die, - struct dwarf2_cu *cu) +static struct type * +read_array_type (struct die_info *die, struct dwarf2_cu *cu) { - /* If we found a reference attribute and the DIE has no name, try - to find a name in the referred to DIE. */ + struct objfile *objfile = cu->objfile; + struct die_info *child_die; + struct type *type; + struct type *element_type, *range_type, *index_type; + struct type **range_types = NULL; + struct attribute *attr; + int ndim = 0; + struct cleanup *back_to; + char *name; - if (part_die->name == NULL && part_die->has_specification) - { - struct partial_die_info *spec_die; + element_type = die_type (die, cu); - spec_die = find_partial_die (part_die->spec_offset, cu); + /* The die_type call above may have already set the type for this DIE. */ + type = get_die_type (die, cu); + if (type) + return type; - fixup_partial_die (spec_die, cu); + /* Irix 6.2 native cc creates array types without children for + arrays with unspecified length. */ + if (die->child == NULL) + { + index_type = objfile_type (objfile)->builtin_int; + range_type = create_range_type (NULL, index_type, 0, -1); + type = create_array_type (NULL, element_type, range_type); + return set_die_type (die, type, cu); + } - if (spec_die->name) + back_to = make_cleanup (null_cleanup, NULL); + child_die = die->child; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_subrange_type) { - part_die->name = spec_die->name; + struct type *child_type = read_type_die (child_die, cu); - /* Copy DW_AT_external attribute if it is set. */ - if (spec_die->is_external) - part_die->is_external = spec_die->is_external; + if (child_type != NULL) + { + /* The range type was succesfully read. Save it for the + array type creation. */ + if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0) + { + range_types = (struct type **) + xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct type *)); + if (ndim == 0) + make_cleanup (free_current_contents, &range_types); + } + range_types[ndim++] = child_type; + } } + child_die = sibling_die (child_die); } - /* Set default names for some unnamed DIEs. */ - if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type - || part_die->tag == DW_TAG_class_type)) - part_die->name = "(anonymous class)"; + /* Dwarf2 dimensions are output from left to right, create the + necessary array types in backwards order. */ - if (part_die->name == NULL && part_die->tag == DW_TAG_namespace) - part_die->name = "(anonymous namespace)"; + type = element_type; - if (part_die->tag == DW_TAG_structure_type - || part_die->tag == DW_TAG_class_type - || part_die->tag == DW_TAG_union_type) - guess_structure_name (part_die, cu); -} + if (read_array_order (die, cu) == DW_ORD_col_major) + { + int i = 0; -/* Read an attribute value described by an attribute form. */ + while (i < ndim) + type = create_array_type (NULL, type, range_types[i++]); + } + else + { + while (ndim-- > 0) + type = create_array_type (NULL, type, range_types[ndim]); + } -static gdb_byte * -read_attribute_value (struct attribute *attr, unsigned form, - bfd *abfd, gdb_byte *info_ptr, - struct dwarf2_cu *cu) -{ - struct comp_unit_head *cu_header = &cu->header; - unsigned int bytes_read; - struct dwarf_block *blk; + /* Understand Dwarf2 support for vector types (like they occur on + the PowerPC w/ AltiVec). Gcc just adds another attribute to the + array type. This is not part of the Dwarf2/3 standard yet, but a + custom vendor extension. The main difference between a regular + array and the vector variant is that vectors are passed by value + to functions. */ + attr = dwarf2_attr (die, DW_AT_GNU_vector, cu); + if (attr) + make_vector_type (type); - attr->form = form; - switch (form) + /* The DIE may have DW_AT_byte_size set. For example an OpenCL + implementation may choose to implement triple vectors using this + attribute. */ + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) { - case DW_FORM_ref_addr: - if (cu->header.version == 2) - DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read); + if (DW_UNSND (attr) >= TYPE_LENGTH (type)) + TYPE_LENGTH (type) = DW_UNSND (attr); else - DW_ADDR (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_addr: - DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_block2: - blk = dwarf_alloc_block (cu); - blk->size = read_2_bytes (abfd, info_ptr); - info_ptr += 2; - blk->data = read_n_bytes (abfd, info_ptr, blk->size); - info_ptr += blk->size; - DW_BLOCK (attr) = blk; - break; - case DW_FORM_block4: - blk = dwarf_alloc_block (cu); - blk->size = read_4_bytes (abfd, info_ptr); - info_ptr += 4; - blk->data = read_n_bytes (abfd, info_ptr, blk->size); - info_ptr += blk->size; - DW_BLOCK (attr) = blk; - break; - case DW_FORM_data2: - DW_UNSND (attr) = read_2_bytes (abfd, info_ptr); - info_ptr += 2; - break; - case DW_FORM_data4: - DW_UNSND (attr) = read_4_bytes (abfd, info_ptr); - info_ptr += 4; - break; - case DW_FORM_data8: - DW_UNSND (attr) = read_8_bytes (abfd, info_ptr); - info_ptr += 8; - break; - case DW_FORM_sec_offset: - DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_string: - DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read); - DW_STRING_IS_CANONICAL (attr) = 0; - info_ptr += bytes_read; - break; - case DW_FORM_strp: - DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header, - &bytes_read); - DW_STRING_IS_CANONICAL (attr) = 0; - info_ptr += bytes_read; - break; - case DW_FORM_exprloc: - case DW_FORM_block: - blk = dwarf_alloc_block (cu); - blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - blk->data = read_n_bytes (abfd, info_ptr, blk->size); - info_ptr += blk->size; - DW_BLOCK (attr) = blk; - break; - case DW_FORM_block1: - blk = dwarf_alloc_block (cu); - blk->size = read_1_byte (abfd, info_ptr); - info_ptr += 1; - blk->data = read_n_bytes (abfd, info_ptr, blk->size); - info_ptr += blk->size; - DW_BLOCK (attr) = blk; - break; - case DW_FORM_data1: - DW_UNSND (attr) = read_1_byte (abfd, info_ptr); - info_ptr += 1; - break; - case DW_FORM_flag: - DW_UNSND (attr) = read_1_byte (abfd, info_ptr); - info_ptr += 1; - break; - case DW_FORM_flag_present: - DW_UNSND (attr) = 1; - break; - case DW_FORM_sdata: - DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_udata: - DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - break; - case DW_FORM_ref1: - DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr); - info_ptr += 1; - break; - case DW_FORM_ref2: - DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr); - info_ptr += 2; - break; - case DW_FORM_ref4: - DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr); - info_ptr += 4; - break; - case DW_FORM_ref8: - DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr); - info_ptr += 8; - break; - case DW_FORM_sig8: - /* Convert the signature to something we can record in DW_UNSND - for later lookup. - NOTE: This is NULL if the type wasn't found. */ - DW_SIGNATURED_TYPE (attr) = - lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr)); - info_ptr += 8; - break; - case DW_FORM_ref_udata: - DW_ADDR (attr) = (cu->header.offset - + read_unsigned_leb128 (abfd, info_ptr, &bytes_read)); - info_ptr += bytes_read; - break; - case DW_FORM_indirect: - form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu); - break; - default: - error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"), - dwarf_form_name (form), - bfd_get_filename (abfd)); + complaint (&symfile_complaints, + _("DW_AT_byte_size for array type smaller " + "than the total size of elements")); } - /* We have seen instances where the compiler tried to emit a byte - size attribute of -1 which ended up being encoded as an unsigned - 0xffffffff. Although 0xffffffff is technically a valid size value, - an object of this size seems pretty unlikely so we can relatively - safely treat these cases as if the size attribute was invalid and - treat them as zero by default. */ - if (attr->name == DW_AT_byte_size - && form == DW_FORM_data4 - && DW_UNSND (attr) >= 0xffffffff) - { - complaint - (&symfile_complaints, - _("Suspicious DW_AT_byte_size value treated as zero instead of %s"), - hex_string (DW_UNSND (attr))); - DW_UNSND (attr) = 0; - } - - return info_ptr; -} - -/* Read an attribute described by an abbreviated attribute. */ - -static gdb_byte * -read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, - bfd *abfd, gdb_byte *info_ptr, struct dwarf2_cu *cu) -{ - attr->name = abbrev->name; - return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu); -} + name = dwarf2_name (die, cu); + if (name) + TYPE_NAME (type) = name; -/* read dwarf information from a buffer */ + /* Install the type in the die. */ + set_die_type (die, type, cu); -static unsigned int -read_1_byte (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_8 (abfd, buf); -} + /* set_die_type should be already done. */ + set_descriptive_type (type, die, cu); -static int -read_1_signed_byte (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_signed_8 (abfd, buf); -} + do_cleanups (back_to); -static unsigned int -read_2_bytes (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_16 (abfd, buf); + return type; } -static int -read_2_signed_bytes (bfd *abfd, gdb_byte *buf) +static enum dwarf_array_dim_ordering +read_array_order (struct die_info *die, struct dwarf2_cu *cu) { - return bfd_get_signed_16 (abfd, buf); -} + struct attribute *attr; -static unsigned int -read_4_bytes (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_32 (abfd, buf); -} + attr = dwarf2_attr (die, DW_AT_ordering, cu); -static int -read_4_signed_bytes (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_signed_32 (abfd, buf); -} + if (attr) return DW_SND (attr); -static ULONGEST -read_8_bytes (bfd *abfd, gdb_byte *buf) -{ - return bfd_get_64 (abfd, buf); -} + /* GNU F77 is a special case, as at 08/2004 array type info is the + opposite order to the dwarf2 specification, but data is still + laid out as per normal fortran. -static CORE_ADDR -read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu, - unsigned int *bytes_read) -{ - struct comp_unit_head *cu_header = &cu->header; - CORE_ADDR retval = 0; + FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need + version checking. */ - if (cu_header->signed_addr_p) - { - switch (cu_header->addr_size) - { - case 2: - retval = bfd_get_signed_16 (abfd, buf); - break; - case 4: - retval = bfd_get_signed_32 (abfd, buf); - break; - case 8: - retval = bfd_get_signed_64 (abfd, buf); - break; - default: - internal_error (__FILE__, __LINE__, - _("read_address: bad switch, signed [in module %s]"), - bfd_get_filename (abfd)); - } - } - else + if (cu->language == language_fortran + && cu->producer && strstr (cu->producer, "GNU F77")) { - switch (cu_header->addr_size) - { - case 2: - retval = bfd_get_16 (abfd, buf); - break; - case 4: - retval = bfd_get_32 (abfd, buf); - break; - case 8: - retval = bfd_get_64 (abfd, buf); - break; - default: - internal_error (__FILE__, __LINE__, - _("read_address: bad switch, unsigned [in module %s]"), - bfd_get_filename (abfd)); - } + return DW_ORD_row_major; } - *bytes_read = cu_header->addr_size; - return retval; + switch (cu->language_defn->la_array_ordering) + { + case array_column_major: + return DW_ORD_col_major; + case array_row_major: + default: + return DW_ORD_row_major; + }; } -/* Read the initial length from a section. The (draft) DWARF 3 - specification allows the initial length to take up either 4 bytes - or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8 - bytes describe the length and all offsets will be 8 bytes in length - instead of 4. +/* Extract all information from a DW_TAG_set_type DIE and put it in + the DIE's type field. */ - An older, non-standard 64-bit format is also handled by this - function. The older format in question stores the initial length - as an 8-byte quantity without an escape value. Lengths greater - than 2^32 aren't very common which means that the initial 4 bytes - is almost always zero. Since a length value of zero doesn't make - sense for the 32-bit format, this initial zero can be considered to - be an escape value which indicates the presence of the older 64-bit - format. As written, the code can't detect (old format) lengths - greater than 4GB. If it becomes necessary to handle lengths - somewhat larger than 4GB, we could allow other small values (such - as the non-sensical values of 1, 2, and 3) to also be used as - escape values indicating the presence of the old format. +static struct type * +read_set_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *domain_type, *set_type; + struct attribute *attr; - The value returned via bytes_read should be used to increment the - relevant pointer after calling read_initial_length(). + domain_type = die_type (die, cu); - [ Note: read_initial_length() and read_offset() are based on the - document entitled "DWARF Debugging Information Format", revision - 3, draft 8, dated November 19, 2001. This document was obtained - from: + /* The die_type call above may have already set the type for this DIE. */ + set_type = get_die_type (die, cu); + if (set_type) + return set_type; - http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf + set_type = create_set_type (NULL, domain_type); - This document is only a draft and is subject to change. (So beware.) + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) + TYPE_LENGTH (set_type) = DW_UNSND (attr); - Details regarding the older, non-standard 64-bit format were - determined empirically by examining 64-bit ELF files produced by - the SGI toolchain on an IRIX 6.5 machine. + return set_die_type (die, set_type, cu); +} - - Kevin, July 16, 2002 - ] */ +/* First cut: install each common block member as a global variable. */ -static LONGEST -read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read) +static void +read_common_block (struct die_info *die, struct dwarf2_cu *cu) { - LONGEST length = bfd_get_32 (abfd, buf); + struct die_info *child_die; + struct attribute *attr; + struct symbol *sym; + CORE_ADDR base = (CORE_ADDR) 0; - if (length == 0xffffffff) - { - length = bfd_get_64 (abfd, buf + 4); - *bytes_read = 12; - } - else if (length == 0) + attr = dwarf2_attr (die, DW_AT_location, cu); + if (attr) { - /* Handle the (non-standard) 64-bit DWARF2 format used by IRIX. */ - length = bfd_get_64 (abfd, buf); - *bytes_read = 8; + /* Support the .debug_loc offsets. */ + if (attr_form_is_block (attr)) + { + base = decode_locdesc (DW_BLOCK (attr), cu); + } + else if (attr_form_is_section_offset (attr)) + { + dwarf2_complex_location_expr_complaint (); + } + else + { + dwarf2_invalid_attrib_class_complaint ("DW_AT_location", + "common block member"); + } } - else + if (die->child != NULL) { - *bytes_read = 4; - } + child_die = die->child; + while (child_die && child_die->tag) + { + LONGEST offset; - return length; + sym = new_symbol (child_die, NULL, cu); + if (sym != NULL + && handle_data_member_location (child_die, cu, &offset)) + { + SYMBOL_VALUE_ADDRESS (sym) = base + offset; + add_symbol_to_list (sym, &global_symbols); + } + child_die = sibling_die (child_die); + } + } } -/* Cover function for read_initial_length. - Returns the length of the object at BUF, and stores the size of the - initial length in *BYTES_READ and stores the size that offsets will be in - *OFFSET_SIZE. - If the initial length size is not equivalent to that specified in - CU_HEADER then issue a complaint. - This is useful when reading non-comp-unit headers. */ +/* Create a type for a C++ namespace. */ -static LONGEST -read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf, - const struct comp_unit_head *cu_header, - unsigned int *bytes_read, - unsigned int *offset_size) +static struct type * +read_namespace_type (struct die_info *die, struct dwarf2_cu *cu) { - LONGEST length = read_initial_length (abfd, buf, bytes_read); + struct objfile *objfile = cu->objfile; + const char *previous_prefix, *name; + int is_anonymous; + struct type *type; - gdb_assert (cu_header->initial_length_size == 4 - || cu_header->initial_length_size == 8 - || cu_header->initial_length_size == 12); + /* For extensions, reuse the type of the original namespace. */ + if (dwarf2_attr (die, DW_AT_extension, cu) != NULL) + { + struct die_info *ext_die; + struct dwarf2_cu *ext_cu = cu; - if (cu_header->initial_length_size != *bytes_read) - complaint (&symfile_complaints, - _("intermixed 32-bit and 64-bit DWARF sections")); - - *offset_size = (*bytes_read == 4) ? 4 : 8; - return length; -} - -/* Read an offset from the data stream. The size of the offset is - given by cu_header->offset_size. */ + ext_die = dwarf2_extension (die, &ext_cu); + type = read_type_die (ext_die, ext_cu); -static LONGEST -read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header, - unsigned int *bytes_read) -{ - LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size); + /* EXT_CU may not be the same as CU. + Ensure TYPE is recorded in CU's type_hash table. */ + return set_die_type (die, type, cu); + } - *bytes_read = cu_header->offset_size; - return offset; -} + name = namespace_name (die, &is_anonymous, cu); -/* Read an offset from the data stream. */ + /* Now build the name of the current namespace. */ -static LONGEST -read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size) -{ - LONGEST retval = 0; + previous_prefix = determine_prefix (die, cu); + if (previous_prefix[0] != '\0') + name = typename_concat (&objfile->objfile_obstack, + previous_prefix, name, 0, cu); - switch (offset_size) - { - case 4: - retval = bfd_get_32 (abfd, buf); - break; - case 8: - retval = bfd_get_64 (abfd, buf); - break; - default: - internal_error (__FILE__, __LINE__, - _("read_offset_1: bad switch [in module %s]"), - bfd_get_filename (abfd)); - } + /* Create the type. */ + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL, + objfile); + TYPE_NAME (type) = (char *) name; + TYPE_TAG_NAME (type) = TYPE_NAME (type); - return retval; + return set_die_type (die, type, cu); } -static gdb_byte * -read_n_bytes (bfd *abfd, gdb_byte *buf, unsigned int size) -{ - /* If the size of a host char is 8 bits, we can return a pointer - to the buffer, otherwise we have to copy the data to a buffer - allocated on the temporary obstack. */ - gdb_assert (HOST_CHAR_BIT == 8); - return buf; -} +/* Read a C++ namespace. */ -static char * -read_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) +static void +read_namespace (struct die_info *die, struct dwarf2_cu *cu) { - /* If the size of a host char is 8 bits, we can return a pointer - to the string, otherwise we have to copy the string to a buffer - allocated on the temporary obstack. */ - gdb_assert (HOST_CHAR_BIT == 8); - if (*buf == '\0') - { - *bytes_read_ptr = 1; - return NULL; - } - *bytes_read_ptr = strlen ((char *) buf) + 1; - return (char *) buf; -} + struct objfile *objfile = cu->objfile; + int is_anonymous; -static char * -read_indirect_string (bfd *abfd, gdb_byte *buf, - const struct comp_unit_head *cu_header, - unsigned int *bytes_read_ptr) -{ - LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); + /* Add a symbol associated to this if we haven't seen the namespace + before. Also, add a using directive if it's an anonymous + namespace. */ - dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str); - if (dwarf2_per_objfile->str.buffer == NULL) - { - error (_("DW_FORM_strp used without .debug_str section [in module %s]"), - bfd_get_filename (abfd)); - return NULL; - } - if (str_offset >= dwarf2_per_objfile->str.size) + if (dwarf2_attr (die, DW_AT_extension, cu) == NULL) { - error (_("DW_FORM_strp pointing outside of .debug_str section [in module %s]"), - bfd_get_filename (abfd)); - return NULL; - } - gdb_assert (HOST_CHAR_BIT == 8); - if (dwarf2_per_objfile->str.buffer[str_offset] == '\0') - return NULL; - return (char *) (dwarf2_per_objfile->str.buffer + str_offset); -} + struct type *type; -static unsigned long -read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) -{ - unsigned long result; - unsigned int num_read; - int i, shift; - unsigned char byte; + type = read_type_die (die, cu); + new_symbol (die, type, cu); - result = 0; - shift = 0; - num_read = 0; - i = 0; - while (1) - { - byte = bfd_get_8 (abfd, buf); - buf++; - num_read++; - result |= ((unsigned long)(byte & 127) << shift); - if ((byte & 128) == 0) + namespace_name (die, &is_anonymous, cu); + if (is_anonymous) { - break; + const char *previous_prefix = determine_prefix (die, cu); + + cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL, + NULL, &objfile->objfile_obstack); } - shift += 7; } - *bytes_read_ptr = num_read; - return result; -} - -static long -read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) -{ - long result; - int i, shift, num_read; - unsigned char byte; - result = 0; - shift = 0; - num_read = 0; - i = 0; - while (1) + if (die->child != NULL) { - byte = bfd_get_8 (abfd, buf); - buf++; - num_read++; - result |= ((long)(byte & 127) << shift); - shift += 7; - if ((byte & 128) == 0) + struct die_info *child_die = die->child; + + while (child_die && child_die->tag) { - break; + process_die (child_die, cu); + child_die = sibling_die (child_die); } } - if ((shift < 8 * sizeof (result)) && (byte & 0x40)) - result |= -(((long)1) << shift); - *bytes_read_ptr = num_read; - return result; } -/* Return a pointer to just past the end of an LEB128 number in BUF. */ +/* Read a Fortran module as type. This DIE can be only a declaration used for + imported module. Still we need that type as local Fortran "use ... only" + declaration imports depend on the created type in determine_prefix. */ -static gdb_byte * -skip_leb128 (bfd *abfd, gdb_byte *buf) +static struct type * +read_module_type (struct die_info *die, struct dwarf2_cu *cu) { - int byte; + struct objfile *objfile = cu->objfile; + char *module_name; + struct type *type; - while (1) - { - byte = bfd_get_8 (abfd, buf); - buf++; - if ((byte & 128) == 0) - return buf; - } + module_name = dwarf2_name (die, cu); + if (!module_name) + complaint (&symfile_complaints, + _("DW_TAG_module has no name, offset 0x%x"), + die->offset); + type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile); + + /* determine_prefix uses TYPE_TAG_NAME. */ + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + return set_die_type (die, type, cu); } +/* Read a Fortran module. */ + static void -set_cu_language (unsigned int lang, struct dwarf2_cu *cu) +read_module (struct die_info *die, struct dwarf2_cu *cu) { - switch (lang) + struct die_info *child_die = die->child; + + while (child_die && child_die->tag) { - case DW_LANG_C89: - case DW_LANG_C99: - case DW_LANG_C: - cu->language = language_c; - break; - case DW_LANG_C_plus_plus: - cu->language = language_cplus; - break; - case DW_LANG_D: - cu->language = language_d; - break; - case DW_LANG_Fortran77: - case DW_LANG_Fortran90: - case DW_LANG_Fortran95: - cu->language = language_fortran; - break; - case DW_LANG_Mips_Assembler: - cu->language = language_asm; - break; - case DW_LANG_Java: - cu->language = language_java; - break; - case DW_LANG_Ada83: - case DW_LANG_Ada95: - cu->language = language_ada; - break; - case DW_LANG_Modula2: - cu->language = language_m2; - break; - case DW_LANG_Pascal83: - cu->language = language_pascal; - break; - case DW_LANG_ObjC: - cu->language = language_objc; - break; - case DW_LANG_Cobol74: - case DW_LANG_Cobol85: - default: - cu->language = language_minimal; - break; + process_die (child_die, cu); + child_die = sibling_die (child_die); } - cu->language_defn = language_def (cu->language); } -/* Return the named attribute or NULL if not there. */ +/* Return the name of the namespace represented by DIE. Set + *IS_ANONYMOUS to tell whether or not the namespace is an anonymous + namespace. */ -static struct attribute * -dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) +static const char * +namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) { - unsigned int i; - struct attribute *spec = NULL; + struct die_info *current_die; + const char *name = NULL; - for (i = 0; i < die->num_attrs; ++i) - { - if (die->attrs[i].name == name) - return &die->attrs[i]; - if (die->attrs[i].name == DW_AT_specification - || die->attrs[i].name == DW_AT_abstract_origin) - spec = &die->attrs[i]; - } + /* Loop through the extensions until we find a name. */ - if (spec) + for (current_die = die; + current_die != NULL; + current_die = dwarf2_extension (die, &cu)) { - die = follow_die_ref (die, spec, &cu); - return dwarf2_attr (die, name, cu); + name = dwarf2_name (current_die, cu); + if (name != NULL) + break; } - return NULL; + /* Is it an anonymous namespace? */ + + *is_anonymous = (name == NULL); + if (*is_anonymous) + name = CP_ANONYMOUS_NAMESPACE_STR; + + return name; } -/* Return the named attribute or NULL if not there, - but do not follow DW_AT_specification, etc. - This is for use in contexts where we're reading .debug_types dies. - Following DW_AT_specification, DW_AT_abstract_origin will take us - back up the chain, and we want to go down. */ +/* Extract all information from a DW_TAG_pointer_type DIE and add to + the user defined type vector. */ -static struct attribute * -dwarf2_attr_no_follow (struct die_info *die, unsigned int name, - struct dwarf2_cu *cu) +static struct type * +read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) { - unsigned int i; + struct gdbarch *gdbarch = get_objfile_arch (cu->objfile); + struct comp_unit_head *cu_header = &cu->header; + struct type *type; + struct attribute *attr_byte_size; + struct attribute *attr_address_class; + int byte_size, addr_class; + struct type *target_type; - for (i = 0; i < die->num_attrs; ++i) - if (die->attrs[i].name == name) - return &die->attrs[i]; + target_type = die_type (die, cu); - return NULL; -} + /* The die_type call above may have already set the type for this DIE. */ + type = get_die_type (die, cu); + if (type) + return type; -/* Return non-zero iff the attribute NAME is defined for the given DIE, - and holds a non-zero value. This function should only be used for - DW_FORM_flag or DW_FORM_flag_present attributes. */ + type = lookup_pointer_type (target_type); -static int -dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu) -{ - struct attribute *attr = dwarf2_attr (die, name, cu); + attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr_byte_size) + byte_size = DW_UNSND (attr_byte_size); + else + byte_size = cu_header->addr_size; - return (attr && DW_UNSND (attr)); -} + attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu); + if (attr_address_class) + addr_class = DW_UNSND (attr_address_class); + else + addr_class = DW_ADDR_none; -static int -die_is_declaration (struct die_info *die, struct dwarf2_cu *cu) -{ - /* A DIE is a declaration if it has a DW_AT_declaration attribute - which value is non-zero. However, we have to be careful with - DIEs having a DW_AT_specification attribute, because dwarf2_attr() - (via dwarf2_flag_true_p) follows this attribute. So we may - end up accidently finding a declaration attribute that belongs - to a different DIE referenced by the specification attribute, - even though the given DIE does not have a declaration attribute. */ - return (dwarf2_flag_true_p (die, DW_AT_declaration, cu) - && dwarf2_attr (die, DW_AT_specification, cu) == NULL); + /* If the pointer size or address class is different than the + default, create a type variant marked as such and set the + length accordingly. */ + if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none) + { + if (gdbarch_address_class_type_flags_p (gdbarch)) + { + int type_flags; + + type_flags = gdbarch_address_class_type_flags + (gdbarch, byte_size, addr_class); + gdb_assert ((type_flags & ~TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL) + == 0); + type = make_type_with_address_space (type, type_flags); + } + else if (TYPE_LENGTH (type) != byte_size) + { + complaint (&symfile_complaints, + _("invalid pointer size %d"), byte_size); + } + else + { + /* Should we also complain about unhandled address classes? */ + } + } + + TYPE_LENGTH (type) = byte_size; + return set_die_type (die, type, cu); } -/* Return the die giving the specification for DIE, if there is - one. *SPEC_CU is the CU containing DIE on input, and the CU - containing the return value on output. If there is no - specification, but there is an abstract origin, that is - returned. */ +/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to + the user defined type vector. */ -static struct die_info * -die_specification (struct die_info *die, struct dwarf2_cu **spec_cu) +static struct type * +read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu) { - struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, - *spec_cu); + struct type *type; + struct type *to_type; + struct type *domain; - if (spec_attr == NULL) - spec_attr = dwarf2_attr (die, DW_AT_abstract_origin, *spec_cu); + to_type = die_type (die, cu); + domain = die_containing_type (die, cu); - if (spec_attr == NULL) - return NULL; + /* The calls above may have already set the type for this DIE. */ + type = get_die_type (die, cu); + if (type) + return type; + + if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD) + type = lookup_methodptr_type (to_type); else - return follow_die_ref (die, spec_attr, spec_cu); -} + type = lookup_memberptr_type (to_type, domain); -/* Free the line_header structure *LH, and any arrays and strings it - refers to. */ -static void -free_line_header (struct line_header *lh) -{ - if (lh->standard_opcode_lengths) - xfree (lh->standard_opcode_lengths); + return set_die_type (die, type, cu); +} - /* Remember that all the lh->file_names[i].name pointers are - pointers into debug_line_buffer, and don't need to be freed. */ - if (lh->file_names) - xfree (lh->file_names); +/* Extract all information from a DW_TAG_reference_type DIE and add to + the user defined type vector. */ - /* Similarly for the include directory names. */ - if (lh->include_dirs) - xfree (lh->include_dirs); +static struct type * +read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct comp_unit_head *cu_header = &cu->header; + struct type *type, *target_type; + struct attribute *attr; - xfree (lh); -} + target_type = die_type (die, cu); + /* The die_type call above may have already set the type for this DIE. */ + type = get_die_type (die, cu); + if (type) + return type; -/* Add an entry to LH's include directory table. */ -static void -add_include_dir (struct line_header *lh, char *include_dir) -{ - /* Grow the array if necessary. */ - if (lh->include_dirs_size == 0) + type = lookup_reference_type (target_type); + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) { - lh->include_dirs_size = 1; /* for testing */ - lh->include_dirs = xmalloc (lh->include_dirs_size - * sizeof (*lh->include_dirs)); + TYPE_LENGTH (type) = DW_UNSND (attr); } - else if (lh->num_include_dirs >= lh->include_dirs_size) + else { - lh->include_dirs_size *= 2; - lh->include_dirs = xrealloc (lh->include_dirs, - (lh->include_dirs_size - * sizeof (*lh->include_dirs))); + TYPE_LENGTH (type) = cu_header->addr_size; } - - lh->include_dirs[lh->num_include_dirs++] = include_dir; + return set_die_type (die, type, cu); } - -/* Add an entry to LH's file name table. */ -static void -add_file_name (struct line_header *lh, - char *name, - unsigned int dir_index, - unsigned int mod_time, - unsigned int length) +static struct type * +read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu) { - struct file_entry *fe; + struct type *base_type, *cv_type; - /* Grow the array if necessary. */ - if (lh->file_names_size == 0) - { - lh->file_names_size = 1; /* for testing */ - lh->file_names = xmalloc (lh->file_names_size - * sizeof (*lh->file_names)); - } - else if (lh->num_file_names >= lh->file_names_size) + base_type = die_type (die, cu); + + /* The die_type call above may have already set the type for this DIE. */ + cv_type = get_die_type (die, cu); + if (cv_type) + return cv_type; + + /* In case the const qualifier is applied to an array type, the element type + is so qualified, not the array type (section 6.7.3 of C99). */ + if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY) { - lh->file_names_size *= 2; - lh->file_names = xrealloc (lh->file_names, - (lh->file_names_size - * sizeof (*lh->file_names))); + struct type *el_type, *inner_array; + + base_type = copy_type (base_type); + inner_array = base_type; + + while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY) + { + TYPE_TARGET_TYPE (inner_array) = + copy_type (TYPE_TARGET_TYPE (inner_array)); + inner_array = TYPE_TARGET_TYPE (inner_array); + } + + el_type = TYPE_TARGET_TYPE (inner_array); + TYPE_TARGET_TYPE (inner_array) = + make_cv_type (1, TYPE_VOLATILE (el_type), el_type, NULL); + + return set_die_type (die, base_type, cu); } - fe = &lh->file_names[lh->num_file_names++]; - fe->name = name; - fe->dir_index = dir_index; - fe->mod_time = mod_time; - fe->length = length; - fe->included_p = 0; - fe->symtab = NULL; + cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0); + return set_die_type (die, cv_type, cu); } +static struct type * +read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *base_type, *cv_type; -/* Read the statement program header starting at OFFSET in - .debug_line, according to the endianness of ABFD. Return a pointer - to a struct line_header, allocated using xmalloc. + base_type = die_type (die, cu); - NOTE: the strings in the include directory and file name tables of - the returned object point into debug_line_buffer, and must not be - freed. */ -static struct line_header * -dwarf_decode_line_header (unsigned int offset, bfd *abfd, - struct dwarf2_cu *cu) -{ - struct cleanup *back_to; - struct line_header *lh; - gdb_byte *line_ptr; - unsigned int bytes_read, offset_size; - int i; - char *cur_dir, *cur_file; - - dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line); - if (dwarf2_per_objfile->line.buffer == NULL) - { - complaint (&symfile_complaints, _("missing .debug_line section")); - return 0; - } + /* The die_type call above may have already set the type for this DIE. */ + cv_type = get_die_type (die, cu); + if (cv_type) + return cv_type; - /* Make sure that at least there's room for the total_length field. - That could be 12 bytes long, but we're just going to fudge that. */ - if (offset + 4 >= dwarf2_per_objfile->line.size) - { - dwarf2_statement_list_fits_in_line_number_section_complaint (); - return 0; - } + cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0); + return set_die_type (die, cv_type, cu); +} - lh = xmalloc (sizeof (*lh)); - memset (lh, 0, sizeof (*lh)); - back_to = make_cleanup ((make_cleanup_ftype *) free_line_header, - (void *) lh); +/* Extract all information from a DW_TAG_string_type DIE and add to + the user defined type vector. It isn't really a user defined type, + but it behaves like one, with other DIE's using an AT_user_def_type + attribute to reference it. */ - line_ptr = dwarf2_per_objfile->line.buffer + offset; +static struct type * +read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct type *type, *range_type, *index_type, *char_type; + struct attribute *attr; + unsigned int length; - /* Read in the header. */ - lh->total_length = - read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header, - &bytes_read, &offset_size); - line_ptr += bytes_read; - if (line_ptr + lh->total_length > (dwarf2_per_objfile->line.buffer - + dwarf2_per_objfile->line.size)) - { - dwarf2_statement_list_fits_in_line_number_section_complaint (); - return 0; - } - lh->statement_program_end = line_ptr + lh->total_length; - lh->version = read_2_bytes (abfd, line_ptr); - line_ptr += 2; - lh->header_length = read_offset_1 (abfd, line_ptr, offset_size); - line_ptr += offset_size; - lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); - line_ptr += 1; - if (lh->version >= 4) + attr = dwarf2_attr (die, DW_AT_string_length, cu); + if (attr) { - lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr); - line_ptr += 1; + length = DW_UNSND (attr); } else - lh->maximum_ops_per_instruction = 1; - - if (lh->maximum_ops_per_instruction == 0) { - lh->maximum_ops_per_instruction = 1; - complaint (&symfile_complaints, - _("invalid maximum_ops_per_instruction in `.debug_line' section")); + /* Check for the DW_AT_byte_size attribute. */ + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) + { + length = DW_UNSND (attr); + } + else + { + length = 1; + } } - lh->default_is_stmt = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->line_base = read_1_signed_byte (abfd, line_ptr); - line_ptr += 1; - lh->line_range = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->opcode_base = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->standard_opcode_lengths - = xmalloc (lh->opcode_base * sizeof (lh->standard_opcode_lengths[0])); + index_type = objfile_type (objfile)->builtin_int; + range_type = create_range_type (NULL, index_type, 1, length); + char_type = language_string_char_type (cu->language_defn, gdbarch); + type = create_string_type (NULL, char_type, range_type); - lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ - for (i = 1; i < lh->opcode_base; ++i) - { - lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); - line_ptr += 1; - } + return set_die_type (die, type, cu); +} - /* Read directory table. */ - while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL) - { - line_ptr += bytes_read; - add_include_dir (lh, cur_dir); - } - line_ptr += bytes_read; +/* Handle DIES due to C code like: - /* Read file name table. */ - while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL) - { - unsigned int dir_index, mod_time, length; + struct foo + { + int (*funcp)(int a, long l); + int b; + }; - line_ptr += bytes_read; - dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; + ('funcp' generates a DW_TAG_subroutine_type DIE). */ - add_file_name (lh, cur_file, dir_index, mod_time, length); - } - line_ptr += bytes_read; - lh->statement_program_start = line_ptr; +static struct type * +read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *type; /* Type that this function returns. */ + struct type *ftype; /* Function that returns above type. */ + struct attribute *attr; - if (line_ptr > (dwarf2_per_objfile->line.buffer - + dwarf2_per_objfile->line.size)) - complaint (&symfile_complaints, - _("line number info header doesn't fit in `.debug_line' section")); + type = die_type (die, cu); - discard_cleanups (back_to); - return lh; -} + /* The die_type call above may have already set the type for this DIE. */ + ftype = get_die_type (die, cu); + if (ftype) + return ftype; -/* This function exists to work around a bug in certain compilers - (particularly GCC 2.95), in which the first line number marker of a - function does not show up until after the prologue, right before - the second line number marker. This function shifts ADDRESS down - to the beginning of the function if necessary, and is called on - addresses passed to record_line. */ + ftype = lookup_function_type (type); -static CORE_ADDR -check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu) -{ - struct function_range *fn; + /* All functions in C++, Pascal and Java have prototypes. */ + attr = dwarf2_attr (die, DW_AT_prototyped, cu); + if ((attr && (DW_UNSND (attr) != 0)) + || cu->language == language_cplus + || cu->language == language_java + || cu->language == language_pascal) + TYPE_PROTOTYPED (ftype) = 1; + else if (producer_is_realview (cu->producer)) + /* RealView does not emit DW_AT_prototyped. We can not + distinguish prototyped and unprototyped functions; default to + prototyped, since that is more common in modern code (and + RealView warns about unprototyped functions). */ + TYPE_PROTOTYPED (ftype) = 1; - /* Find the function_range containing address. */ - if (!cu->first_fn) - return address; + /* Store the calling convention in the type if it's available in + the subroutine die. Otherwise set the calling convention to + the default value DW_CC_normal. */ + attr = dwarf2_attr (die, DW_AT_calling_convention, cu); + if (attr) + TYPE_CALLING_CONVENTION (ftype) = DW_UNSND (attr); + else if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL")) + TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL; + else + TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal; - if (!cu->cached_fn) - cu->cached_fn = cu->first_fn; + /* We need to add the subroutine type to the die immediately so + we don't infinitely recurse when dealing with parameters + declared as the same subroutine type. */ + set_die_type (die, ftype, cu); - fn = cu->cached_fn; - while (fn) - if (fn->lowpc <= address && fn->highpc > address) - goto found; - else - fn = fn->next; + if (die->child != NULL) + { + struct type *void_type = objfile_type (cu->objfile)->builtin_void; + struct die_info *child_die; + int nparams, iparams; - fn = cu->first_fn; - while (fn && fn != cu->cached_fn) - if (fn->lowpc <= address && fn->highpc > address) - goto found; - else - fn = fn->next; + /* Count the number of parameters. + FIXME: GDB currently ignores vararg functions, but knows about + vararg member functions. */ + nparams = 0; + child_die = die->child; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + nparams++; + else if (child_die->tag == DW_TAG_unspecified_parameters) + TYPE_VARARGS (ftype) = 1; + child_die = sibling_die (child_die); + } - return address; + /* Allocate storage for parameters and fill them in. */ + TYPE_NFIELDS (ftype) = nparams; + TYPE_FIELDS (ftype) = (struct field *) + TYPE_ZALLOC (ftype, nparams * sizeof (struct field)); - found: - if (fn->seen_line) - return address; - if (address != fn->lowpc) - complaint (&symfile_complaints, - _("misplaced first line number at 0x%lx for '%s'"), - (unsigned long) address, fn->name); - fn->seen_line = 1; - return fn->lowpc; -} + /* TYPE_FIELD_TYPE must never be NULL. Pre-fill the array to ensure it + even if we error out during the parameters reading below. */ + for (iparams = 0; iparams < nparams; iparams++) + TYPE_FIELD_TYPE (ftype, iparams) = void_type; -/* Decode the Line Number Program (LNP) for the given line_header - structure and CU. The actual information extracted and the type - of structures created from the LNP depends on the value of PST. + iparams = 0; + child_die = die->child; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + { + struct type *arg_type; - 1. If PST is NULL, then this procedure uses the data from the program - to create all necessary symbol tables, and their linetables. - The compilation directory of the file is passed in COMP_DIR, - and must not be NULL. + /* DWARF version 2 has no clean way to discern C++ + static and non-static member functions. G++ helps + GDB by marking the first parameter for non-static + member functions (which is the this pointer) as + artificial. We pass this information to + dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. - 2. If PST is not NULL, this procedure reads the program to determine - the list of files included by the unit represented by PST, and - builds all the associated partial symbol tables. In this case, - the value of COMP_DIR is ignored, and can thus be NULL (the COMP_DIR - is not used to compute the full name of the symtab, and therefore - omitting it when building the partial symtab does not introduce - the potential for inconsistency - a partial symtab and its associated - symbtab having a different fullname -). */ + DWARF version 3 added DW_AT_object_pointer, which GCC + 4.5 does not yet generate. */ + attr = dwarf2_attr (child_die, DW_AT_artificial, cu); + if (attr) + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); + else + { + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; -static void -dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, - struct dwarf2_cu *cu, struct partial_symtab *pst) -{ - gdb_byte *line_ptr, *extended_end; - gdb_byte *line_end; - unsigned int bytes_read, extended_len; - unsigned char op_code, extended_op, adj_opcode; - CORE_ADDR baseaddr; - struct objfile *objfile = cu->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - const int decode_for_pst_p = (pst != NULL); - struct subfile *last_subfile = NULL, *first_subfile = current_subfile; - - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - - line_ptr = lh->statement_program_start; - line_end = lh->statement_program_end; - - /* Read the statement sequences until there's nothing left. */ - while (line_ptr < line_end) - { - /* state machine registers */ - CORE_ADDR address = 0; - unsigned int file = 1; - unsigned int line = 1; - unsigned int column = 0; - int is_stmt = lh->default_is_stmt; - int basic_block = 0; - int end_sequence = 0; - CORE_ADDR addr; - unsigned char op_index = 0; - - if (!decode_for_pst_p && lh->num_file_names >= file) - { - /* Start a subfile for the current file of the state machine. */ - /* lh->include_dirs and lh->file_names are 0-based, but the - directory and file name numbers in the statement program - are 1-based. */ - struct file_entry *fe = &lh->file_names[file - 1]; - char *dir = NULL; - - if (fe->dir_index) - dir = lh->include_dirs[fe->dir_index - 1]; - - dwarf2_start_subfile (fe->name, dir, comp_dir); - } - - /* Decode the table. */ - while (!end_sequence) - { - op_code = read_1_byte (abfd, line_ptr); - line_ptr += 1; - if (line_ptr > line_end) - { - dwarf2_debug_line_missing_end_sequence_complaint (); - break; - } - - if (op_code >= lh->opcode_base) - { - /* Special operand. */ - adj_opcode = op_code - lh->opcode_base; - address += (((op_index + (adj_opcode / lh->line_range)) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - op_index = ((op_index + (adj_opcode / lh->line_range)) - % lh->maximum_ops_per_instruction); - line += lh->line_base + (adj_opcode % lh->line_range); - if (lh->num_file_names < file || file == 0) - dwarf2_debug_line_missing_file_complaint (); - /* For now we ignore lines not starting on an - instruction boundary. */ - else if (op_index == 0) - { - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p && is_stmt) + /* GCC/43521: In java, the formal parameter + "this" is sometimes not marked with DW_AT_artificial. */ + if (cu->language == language_java) { - if (last_subfile != current_subfile) - { - addr = gdbarch_addr_bits_remove (gdbarch, address); - if (last_subfile) - record_line (last_subfile, 0, addr); - last_subfile = current_subfile; - } - /* Append row to matrix using current values. */ - addr = check_cu_functions (address, cu); - addr = gdbarch_addr_bits_remove (gdbarch, addr); - record_line (current_subfile, line, addr); + const char *name = dwarf2_name (child_die, cu); + + if (name && !strcmp (name, "this")) + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 1; } } - basic_block = 0; - } - else switch (op_code) - { - case DW_LNS_extended_op: - extended_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - extended_end = line_ptr + extended_len; - extended_op = read_1_byte (abfd, line_ptr); - line_ptr += 1; - switch (extended_op) - { - case DW_LNE_end_sequence: - end_sequence = 1; - break; - case DW_LNE_set_address: - address = read_address (abfd, line_ptr, cu, &bytes_read); - op_index = 0; - line_ptr += bytes_read; - address += baseaddr; - break; - case DW_LNE_define_file: - { - char *cur_file; - unsigned int dir_index, mod_time, length; + arg_type = die_type (child_die, cu); - cur_file = read_string (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - dir_index = - read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - mod_time = - read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - length = - read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - add_file_name (lh, cur_file, dir_index, mod_time, length); - } - break; - case DW_LNE_set_discriminator: - /* The discriminator is not interesting to the debugger; - just ignore it. */ - line_ptr = extended_end; - break; - default: - complaint (&symfile_complaints, - _("mangled .debug_line section")); - return; - } - /* Make sure that we parsed the extended op correctly. If e.g. - we expected a different address size than the producer used, - we may have read the wrong number of bytes. */ - if (line_ptr != extended_end) - { - complaint (&symfile_complaints, - _("mangled .debug_line section")); - return; - } - break; - case DW_LNS_copy: - if (lh->num_file_names < file || file == 0) - dwarf2_debug_line_missing_file_complaint (); - else + /* RealView does not mark THIS as const, which the testsuite + expects. GCC marks THIS as const in method definitions, + but not in the class specifications (GCC PR 43053). */ + if (cu->language == language_cplus && !TYPE_CONST (arg_type) + && TYPE_FIELD_ARTIFICIAL (ftype, iparams)) { - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p && is_stmt) + int is_this = 0; + struct dwarf2_cu *arg_cu = cu; + const char *name = dwarf2_name (child_die, cu); + + attr = dwarf2_attr (die, DW_AT_object_pointer, cu); + if (attr) { - if (last_subfile != current_subfile) - { - addr = gdbarch_addr_bits_remove (gdbarch, address); - if (last_subfile) - record_line (last_subfile, 0, addr); - last_subfile = current_subfile; - } - addr = check_cu_functions (address, cu); - addr = gdbarch_addr_bits_remove (gdbarch, addr); - record_line (current_subfile, line, addr); + /* If the compiler emits this, use it. */ + if (follow_die_ref (die, attr, &arg_cu) == child_die) + is_this = 1; } + else if (name && strcmp (name, "this") == 0) + /* Function definitions will have the argument names. */ + is_this = 1; + else if (name == NULL && iparams == 0) + /* Declarations may not have the names, so like + elsewhere in GDB, assume an artificial first + argument is "this". */ + is_this = 1; + + if (is_this) + arg_type = make_cv_type (1, TYPE_VOLATILE (arg_type), + arg_type, 0); } - basic_block = 0; - break; - case DW_LNS_advance_pc: - { - CORE_ADDR adjust - = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - address += (((op_index + adjust) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - op_index = ((op_index + adjust) - % lh->maximum_ops_per_instruction); - line_ptr += bytes_read; - } - break; - case DW_LNS_advance_line: - line += read_signed_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - case DW_LNS_set_file: - { - /* The arrays lh->include_dirs and lh->file_names are - 0-based, but the directory and file name numbers in - the statement program are 1-based. */ - struct file_entry *fe; - char *dir = NULL; + TYPE_FIELD_TYPE (ftype, iparams) = arg_type; + iparams++; + } + child_die = sibling_die (child_die); + } + } - file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - if (lh->num_file_names < file || file == 0) - dwarf2_debug_line_missing_file_complaint (); - else - { - fe = &lh->file_names[file - 1]; - if (fe->dir_index) - dir = lh->include_dirs[fe->dir_index - 1]; - if (!decode_for_pst_p) - { - last_subfile = current_subfile; - dwarf2_start_subfile (fe->name, dir, comp_dir); - } - } - } - break; - case DW_LNS_set_column: - column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - case DW_LNS_negate_stmt: - is_stmt = (!is_stmt); - break; - case DW_LNS_set_basic_block: - basic_block = 1; - break; - /* Add to the address register of the state machine the - address increment value corresponding to special opcode - 255. I.e., this value is scaled by the minimum - instruction length since special opcode 255 would have - scaled the the increment. */ - case DW_LNS_const_add_pc: - { - CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range; + return ftype; +} - address += (((op_index + adjust) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - op_index = ((op_index + adjust) - % lh->maximum_ops_per_instruction); - } - break; - case DW_LNS_fixed_advance_pc: - address += read_2_bytes (abfd, line_ptr); - op_index = 0; - line_ptr += 2; - break; - default: - { - /* Unknown standard opcode, ignore it. */ - int i; +static struct type * +read_typedef (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + const char *name = NULL; + struct type *this_type; - for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++) - { - (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - } - } - } - } - if (lh->num_file_names < file || file == 0) - dwarf2_debug_line_missing_file_complaint (); - else - { - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p) - { - addr = gdbarch_addr_bits_remove (gdbarch, address); - record_line (current_subfile, 0, addr); - } - } - } - - if (decode_for_pst_p) - { - int file_index; - - /* Now that we're done scanning the Line Header Program, we can - create the psymtab of each included file. */ - for (file_index = 0; file_index < lh->num_file_names; file_index++) - if (lh->file_names[file_index].included_p == 1) - { - const struct file_entry fe = lh->file_names [file_index]; - char *include_name = fe.name; - char *dir_name = NULL; - char *pst_filename = pst->filename; - - if (fe.dir_index) - dir_name = lh->include_dirs[fe.dir_index - 1]; + name = dwarf2_full_name (NULL, die, cu); + this_type = init_type (TYPE_CODE_TYPEDEF, 0, + TYPE_FLAG_TARGET_STUB, NULL, objfile); + TYPE_NAME (this_type) = (char *) name; + set_die_type (die, this_type, cu); + TYPE_TARGET_TYPE (this_type) = die_type (die, cu); + return this_type; +} - if (!IS_ABSOLUTE_PATH (include_name) && dir_name != NULL) - { - include_name = concat (dir_name, SLASH_STRING, - include_name, (char *)NULL); - make_cleanup (xfree, include_name); - } +/* Find a representation of a given base type and install + it in the TYPE field of the die. */ - if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL) - { - pst_filename = concat (pst->dirname, SLASH_STRING, - pst_filename, (char *)NULL); - make_cleanup (xfree, pst_filename); - } +static struct type * +read_base_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct type *type; + struct attribute *attr; + int encoding = 0, size = 0; + char *name; + enum type_code code = TYPE_CODE_INT; + int type_flags = 0; + struct type *target_type = NULL; - if (strcmp (include_name, pst_filename) != 0) - dwarf2_create_include_psymtab (include_name, pst, objfile); - } + attr = dwarf2_attr (die, DW_AT_encoding, cu); + if (attr) + { + encoding = DW_UNSND (attr); } - else + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) { - /* Make sure a symtab is created for every file, even files - which contain only variables (i.e. no code with associated - line numbers). */ - - int i; - struct file_entry *fe; - - for (i = 0; i < lh->num_file_names; i++) - { - char *dir = NULL; - - fe = &lh->file_names[i]; - if (fe->dir_index) - dir = lh->include_dirs[fe->dir_index - 1]; - dwarf2_start_subfile (fe->name, dir, comp_dir); + size = DW_UNSND (attr); + } + name = dwarf2_name (die, cu); + if (!name) + { + complaint (&symfile_complaints, + _("DW_AT_name missing from DW_TAG_base_type")); + } - /* Skip the main file; we don't need it, and it must be - allocated last, so that it will show up before the - non-primary symtabs in the objfile's symtab list. */ - if (current_subfile == first_subfile) - continue; + switch (encoding) + { + case DW_ATE_address: + /* Turn DW_ATE_address into a void * pointer. */ + code = TYPE_CODE_PTR; + type_flags |= TYPE_FLAG_UNSIGNED; + target_type = init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile); + break; + case DW_ATE_boolean: + code = TYPE_CODE_BOOL; + type_flags |= TYPE_FLAG_UNSIGNED; + break; + case DW_ATE_complex_float: + code = TYPE_CODE_COMPLEX; + target_type = init_type (TYPE_CODE_FLT, size / 2, 0, NULL, objfile); + break; + case DW_ATE_decimal_float: + code = TYPE_CODE_DECFLOAT; + break; + case DW_ATE_float: + code = TYPE_CODE_FLT; + break; + case DW_ATE_signed: + break; + case DW_ATE_unsigned: + type_flags |= TYPE_FLAG_UNSIGNED; + break; + case DW_ATE_signed_char: + if (cu->language == language_ada || cu->language == language_m2 + || cu->language == language_pascal) + code = TYPE_CODE_CHAR; + break; + case DW_ATE_unsigned_char: + if (cu->language == language_ada || cu->language == language_m2 + || cu->language == language_pascal) + code = TYPE_CODE_CHAR; + type_flags |= TYPE_FLAG_UNSIGNED; + break; + case DW_ATE_UTF: + /* We just treat this as an integer and then recognize the + type by name elsewhere. */ + break; - if (current_subfile->symtab == NULL) - current_subfile->symtab = allocate_symtab (current_subfile->name, - cu->objfile); - fe->symtab = current_subfile->symtab; - } + default: + complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"), + dwarf_type_encoding_name (encoding)); + break; } -} -/* Start a subfile for DWARF. FILENAME is the name of the file and - DIRNAME the name of the source directory which contains FILENAME - or NULL if not known. COMP_DIR is the compilation directory for the - linetable's compilation unit or NULL if not known. - This routine tries to keep line numbers from identical absolute and - relative file names in a common subfile. + type = init_type (code, size, type_flags, NULL, objfile); + TYPE_NAME (type) = name; + TYPE_TARGET_TYPE (type) = target_type; - Using the `list' example from the GDB testsuite, which resides in - /srcdir and compiling it with Irix6.2 cc in /compdir using a filename - of /srcdir/list0.c yields the following debugging information for list0.c: + if (name && strcmp (name, "char") == 0) + TYPE_NOSIGN (type) = 1; - DW_AT_name: /srcdir/list0.c - DW_AT_comp_dir: /compdir - files.files[0].name: list0.h - files.files[0].dir: /srcdir - files.files[1].name: list0.c - files.files[1].dir: /srcdir + return set_die_type (die, type, cu); +} - The line number information for list0.c has to end up in a single - subfile, so that `break /srcdir/list0.c:1' works as expected. - start_subfile will ensure that this happens provided that we pass the - concatenation of files.files[1].dir and files.files[1].name as the - subfile's name. */ +/* Read the given DW_AT_subrange DIE. */ -static void -dwarf2_start_subfile (char *filename, char *dirname, char *comp_dir) +static struct type * +read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) { - char *fullname; - - /* While reading the DIEs, we call start_symtab(DW_AT_name, DW_AT_comp_dir). - `start_symtab' will always pass the contents of DW_AT_comp_dir as - second argument to start_subfile. To be consistent, we do the - same here. In order not to lose the line information directory, - we concatenate it to the filename when it makes sense. - Note that the Dwarf3 standard says (speaking of filenames in line - information): ``The directory index is ignored for file names - that represent full path names''. Thus ignoring dirname in the - `else' branch below isn't an issue. */ - - if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL) - fullname = concat (dirname, SLASH_STRING, filename, (char *)NULL); - else - fullname = filename; - - start_subfile (fullname, comp_dir); - - if (fullname != filename) - xfree (fullname); -} + struct type *base_type; + struct type *range_type; + struct attribute *attr; + LONGEST low = 0; + LONGEST high = -1; + char *name; + LONGEST negative_mask; -static void -var_decode_location (struct attribute *attr, struct symbol *sym, - struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct comp_unit_head *cu_header = &cu->header; + base_type = die_type (die, cu); + /* Preserve BASE_TYPE's original type, just set its LENGTH. */ + check_typedef (base_type); - /* NOTE drow/2003-01-30: There used to be a comment and some special - code here to turn a symbol with DW_AT_external and a - SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was - necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux - with some versions of binutils) where shared libraries could have - relocations against symbols in their debug information - the - minimal symbol would have the right address, but the debug info - would not. It's no longer necessary, because we will explicitly - apply relocations when we read in the debug information now. */ + /* The die_type call above may have already set the type for this DIE. */ + range_type = get_die_type (die, cu); + if (range_type) + return range_type; - /* A DW_AT_location attribute with no contents indicates that a - variable has been optimized away. */ - if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0) + if (cu->language == language_fortran) { - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; - return; + /* FORTRAN implies a lower bound of 1, if not given. */ + low = 1; } - /* Handle one degenerate form of location expression specially, to - preserve GDB's previous behavior when section offsets are - specified. If this is just a DW_OP_addr then mark this symbol - as LOC_STATIC. */ + /* FIXME: For variable sized arrays either of these could be + a variable rather than a constant value. We'll allow it, + but we don't know how to handle it. */ + attr = dwarf2_attr (die, DW_AT_lower_bound, cu); + if (attr) + low = dwarf2_get_attr_constant_value (attr, 0); - if (attr_form_is_block (attr) - && DW_BLOCK (attr)->size == 1 + cu_header->addr_size - && DW_BLOCK (attr)->data[0] == DW_OP_addr) + attr = dwarf2_attr (die, DW_AT_upper_bound, cu); + if (attr) { - unsigned int dummy; + if (attr->form == DW_FORM_block1 || is_ref_attr (attr)) + { + /* GCC encodes arrays with unspecified or dynamic length + with a DW_FORM_block1 attribute or a reference attribute. + FIXME: GDB does not yet know how to handle dynamic + arrays properly, treat them as arrays with unspecified + length for now. - SYMBOL_VALUE_ADDRESS (sym) = - read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy); - SYMBOL_CLASS (sym) = LOC_STATIC; - fixup_symbol_section (sym, objfile); - SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, - SYMBOL_SECTION (sym)); - return; + FIXME: jimb/2003-09-22: GDB does not really know + how to handle arrays of unspecified length + either; we just represent them as zero-length + arrays. Choose an appropriate upper bound given + the lower bound we've computed above. */ + high = low - 1; + } + else + high = dwarf2_get_attr_constant_value (attr, 1); + } + else + { + attr = dwarf2_attr (die, DW_AT_count, cu); + if (attr) + { + int count = dwarf2_get_attr_constant_value (attr, 1); + high = low + count - 1; + } + else + { + /* Unspecified array length. */ + high = low - 1; + } } - /* NOTE drow/2002-01-30: It might be worthwhile to have a static - expression evaluator, and use LOC_COMPUTED only when necessary - (i.e. when the value of a register or memory location is - referenced, or a thread-local block, etc.). Then again, it might - not be worthwhile. I'm assuming that it isn't unless performance - or memory numbers show me otherwise. */ + /* Dwarf-2 specifications explicitly allows to create subrange types + without specifying a base type. + In that case, the base type must be set to the type of + the lower bound, upper bound or count, in that order, if any of these + three attributes references an object that has a type. + If no base type is found, the Dwarf-2 specifications say that + a signed integer type of size equal to the size of an address should + be used. + For the following C code: `extern char gdb_int [];' + GCC produces an empty range DIE. + FIXME: muller/2010-05-28: Possible references to object for low bound, + high bound or count are not yet handled by this code. */ + if (TYPE_CODE (base_type) == TYPE_CODE_VOID) + { + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + int addr_size = gdbarch_addr_bit (gdbarch) /8; + struct type *int_type = objfile_type (objfile)->builtin_int; - dwarf2_symbol_mark_computed (attr, sym, cu); - SYMBOL_CLASS (sym) = LOC_COMPUTED; -} + /* Test "int", "long int", and "long long int" objfile types, + and select the first one having a size above or equal to the + architecture address size. */ + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + base_type = int_type; + else + { + int_type = objfile_type (objfile)->builtin_long; + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + base_type = int_type; + else + { + int_type = objfile_type (objfile)->builtin_long_long; + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + base_type = int_type; + } + } + } -/* Given a pointer to a DWARF information entry, figure out if we need - to make a symbol table entry for it, and if so, create a new entry - and return a pointer to it. - If TYPE is NULL, determine symbol type from the die, otherwise - used the passed type. */ + negative_mask = + (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1); + if (!TYPE_UNSIGNED (base_type) && (low & negative_mask)) + low |= negative_mask; + if (!TYPE_UNSIGNED (base_type) && (high & negative_mask)) + high |= negative_mask; -static struct symbol * -new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) -{ - struct objfile *objfile = cu->objfile; - struct symbol *sym = NULL; - char *name; - struct attribute *attr = NULL; - struct attribute *attr2 = NULL; - CORE_ADDR baseaddr; - int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + range_type = create_range_type (NULL, base_type, low, high); - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* Mark arrays with dynamic length at least as an array of unspecified + length. GDB could check the boundary but before it gets implemented at + least allow accessing the array elements. */ + if (attr && attr->form == DW_FORM_block1) + TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; + + /* Ada expects an empty array on no boundary attributes. */ + if (attr == NULL && cu->language != language_ada) + TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; name = dwarf2_name (die, cu); if (name) - { - const char *linkagename; + TYPE_NAME (range_type) = name; - sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack, - sizeof (struct symbol)); - OBJSTAT (objfile, n_syms++); - memset (sym, 0, sizeof (struct symbol)); + attr = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr) + TYPE_LENGTH (range_type) = DW_UNSND (attr); - /* Cache this symbol's name and the name's demangled form (if any). */ - SYMBOL_LANGUAGE (sym) = cu->language; - linkagename = dwarf2_physname (name, die, cu); - SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), 0, objfile); + set_die_type (die, range_type, cu); - /* Fortran does not have mangling standard and the mangling does differ - between gfortran, iFort etc. */ - if (cu->language == language_fortran - && sym->ginfo.language_specific.cplus_specific.demangled_name == NULL) - sym->ginfo.language_specific.cplus_specific.demangled_name - = (char *) dwarf2_full_name (name, die, cu); + /* set_die_type should be already done. */ + set_descriptive_type (range_type, die, cu); - /* Default assumptions. - Use the passed type or decode it from the die. */ - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; - if (type != NULL) - SYMBOL_TYPE (sym) = type; - else - SYMBOL_TYPE (sym) = die_type (die, cu); - attr = dwarf2_attr (die, - inlined_func ? DW_AT_call_line : DW_AT_decl_line, - cu); - if (attr) - { - SYMBOL_LINE (sym) = DW_UNSND (attr); - } + return range_type; +} - attr = dwarf2_attr (die, - inlined_func ? DW_AT_call_file : DW_AT_decl_file, - cu); - if (attr) - { - int file_index = DW_UNSND (attr); +static struct type * +read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *type; - if (cu->line_header == NULL - || file_index > cu->line_header->num_file_names) - complaint (&symfile_complaints, - _("file index out of range")); - else if (file_index > 0) - { - struct file_entry *fe; + /* For now, we only support the C meaning of an unspecified type: void. */ - fe = &cu->line_header->file_names[file_index - 1]; - SYMBOL_SYMTAB (sym) = fe->symtab; - } - } + type = init_type (TYPE_CODE_VOID, 0, 0, NULL, cu->objfile); + TYPE_NAME (type) = dwarf2_name (die, cu); - switch (die->tag) - { - case DW_TAG_label: - attr = dwarf2_attr (die, DW_AT_low_pc, cu); - if (attr) - { - SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr; - } - SYMBOL_CLASS (sym) = LOC_LABEL; - break; - case DW_TAG_subprogram: - /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by - finish_block. */ - SYMBOL_CLASS (sym) = LOC_BLOCK; - attr2 = dwarf2_attr (die, DW_AT_external, cu); - if ((attr2 && (DW_UNSND (attr2) != 0)) - || cu->language == language_ada) - { - /* Subprograms marked external are stored as a global symbol. - Ada subprograms, whether marked external or not, are always - stored as a global symbol, because we want to be able to - access them globally. For instance, we want to be able - to break on a nested subprogram without having to - specify the context. */ - add_symbol_to_list (sym, &global_symbols); - } - else - { - add_symbol_to_list (sym, cu->list_in_scope); - } - break; - case DW_TAG_inlined_subroutine: - /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by - finish_block. */ - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_INLINED (sym) = 1; - /* Do not add the symbol to any lists. It will be found via - BLOCK_FUNCTION from the blockvector. */ - break; - case DW_TAG_variable: - case DW_TAG_member: - /* Compilation with minimal debug info may result in variables - with missing type entries. Change the misleading `void' type - to something sensible. */ - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID) - SYMBOL_TYPE (sym) - = objfile_type (objfile)->nodebug_data_symbol; + return set_die_type (die, type, cu); +} - attr = dwarf2_attr (die, DW_AT_const_value, cu); - /* In the case of DW_TAG_member, we should only be called for - static const members. */ - if (die->tag == DW_TAG_member) - { - /* dwarf2_add_field uses die_is_declaration, - so we do the same. */ - gdb_assert (die_is_declaration (die, cu)); - gdb_assert (attr); - } - if (attr) - { - dwarf2_const_value (attr, sym, cu); - attr2 = dwarf2_attr (die, DW_AT_external, cu); - if (attr2 && (DW_UNSND (attr2) != 0)) - add_symbol_to_list (sym, &global_symbols); - else - add_symbol_to_list (sym, cu->list_in_scope); - break; - } - attr = dwarf2_attr (die, DW_AT_location, cu); - if (attr) - { - var_decode_location (attr, sym, cu); - attr2 = dwarf2_attr (die, DW_AT_external, cu); - if (attr2 && (DW_UNSND (attr2) != 0)) - { - struct pending **list_to_add; +/* Trivial hash function for die_info: the hash value of a DIE + is its offset in .debug_info for this objfile. */ - /* Workaround gfortran PR debug/40040 - it uses - DW_AT_location for variables in -fPIC libraries which may - get overriden by other libraries/executable and get - a different address. Resolve it by the minimal symbol - which may come from inferior's executable using copy - relocation. Make this workaround only for gfortran as for - other compilers GDB cannot guess the minimal symbol - Fortran mangling kind. */ - if (cu->language == language_fortran && die->parent - && die->parent->tag == DW_TAG_module - && cu->producer - && strncmp (cu->producer, "GNU Fortran ", 12) == 0) - SYMBOL_CLASS (sym) = LOC_UNRESOLVED; +static hashval_t +die_hash (const void *item) +{ + const struct die_info *die = item; - /* A variable with DW_AT_external is never static, - but it may be block-scoped. */ - list_to_add = (cu->list_in_scope == &file_symbols - ? &global_symbols : cu->list_in_scope); - add_symbol_to_list (sym, list_to_add); - } - else - add_symbol_to_list (sym, cu->list_in_scope); - } - else - { - /* We do not know the address of this symbol. - If it is an external symbol and we have type information - for it, enter the symbol as a LOC_UNRESOLVED symbol. - The address of the variable will then be determined from - the minimal symbol table whenever the variable is - referenced. */ - attr2 = dwarf2_attr (die, DW_AT_external, cu); - if (attr2 && (DW_UNSND (attr2) != 0) - && dwarf2_attr (die, DW_AT_type, cu) != NULL) - { - struct pending **list_to_add; - - /* A variable with DW_AT_external is never static, but it - may be block-scoped. */ - list_to_add = (cu->list_in_scope == &file_symbols - ? &global_symbols : cu->list_in_scope); - - SYMBOL_CLASS (sym) = LOC_UNRESOLVED; - add_symbol_to_list (sym, list_to_add); - } - else if (!die_is_declaration (die, cu)) - { - /* Use the default LOC_OPTIMIZED_OUT class. */ - gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT); - add_symbol_to_list (sym, cu->list_in_scope); - } - } - break; - case DW_TAG_formal_parameter: - /* If we are inside a function, mark this as an argument. If - not, we might be looking at an argument to an inlined function - when we do not have enough information to show inlined frames; - pretend it's a local variable in that case so that the user can - still see it. */ - if (context_stack_depth > 0 - && context_stack[context_stack_depth - 1].name != NULL) - SYMBOL_IS_ARGUMENT (sym) = 1; - attr = dwarf2_attr (die, DW_AT_location, cu); - if (attr) - { - var_decode_location (attr, sym, cu); - } - attr = dwarf2_attr (die, DW_AT_const_value, cu); - if (attr) - { - dwarf2_const_value (attr, sym, cu); - } - attr = dwarf2_attr (die, DW_AT_variable_parameter, cu); - if (attr && DW_UNSND (attr)) - { - struct type *ref_type; - - ref_type = lookup_reference_type (SYMBOL_TYPE (sym)); - SYMBOL_TYPE (sym) = ref_type; - } - - add_symbol_to_list (sym, cu->list_in_scope); - break; - case DW_TAG_unspecified_parameters: - /* From varargs functions; gdb doesn't seem to have any - interest in this information, so just ignore it for now. - (FIXME?) */ - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_set_type: - case DW_TAG_enumeration_type: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; - - { - /* NOTE: carlton/2003-11-10: C++ and Java class symbols shouldn't - really ever be static objects: otherwise, if you try - to, say, break of a class's method and you're in a file - which doesn't mention that class, it won't work unless - the check for all static symbols in lookup_symbol_aux - saves you. See the OtherFileClass tests in - gdb.c++/namespace.exp. */ - - struct pending **list_to_add; - - list_to_add = (cu->list_in_scope == &file_symbols - && (cu->language == language_cplus - || cu->language == language_java) - ? &global_symbols : cu->list_in_scope); - - add_symbol_to_list (sym, list_to_add); - - /* The semantics of C++ state that "struct foo { ... }" also - defines a typedef for "foo". A Java class declaration also - defines a typedef for the class. */ - if (cu->language == language_cplus - || cu->language == language_java - || cu->language == language_ada) - { - /* The symbol's name is already allocated along with - this objfile, so we don't need to duplicate it for - the type. */ - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym); - } - } - break; - case DW_TAG_typedef: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - add_symbol_to_list (sym, cu->list_in_scope); - break; - case DW_TAG_base_type: - case DW_TAG_subrange_type: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - add_symbol_to_list (sym, cu->list_in_scope); - break; - case DW_TAG_enumerator: - attr = dwarf2_attr (die, DW_AT_const_value, cu); - if (attr) - { - dwarf2_const_value (attr, sym, cu); - } - { - /* NOTE: carlton/2003-11-10: See comment above in the - DW_TAG_class_type, etc. block. */ - - struct pending **list_to_add; + return die->offset; +} - list_to_add = (cu->list_in_scope == &file_symbols - && (cu->language == language_cplus - || cu->language == language_java) - ? &global_symbols : cu->list_in_scope); +/* Trivial comparison function for die_info structures: two DIEs + are equal if they have the same offset. */ - add_symbol_to_list (sym, list_to_add); - } - break; - case DW_TAG_namespace: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - add_symbol_to_list (sym, &global_symbols); - break; - default: - /* Not a tag we recognize. Hopefully we aren't processing - trash data, but since we must specifically ignore things - we don't recognize, there is nothing else we should do at - this point. */ - complaint (&symfile_complaints, _("unsupported tag: '%s'"), - dwarf_tag_name (die->tag)); - break; - } +static int +die_eq (const void *item_lhs, const void *item_rhs) +{ + const struct die_info *die_lhs = item_lhs; + const struct die_info *die_rhs = item_rhs; - /* For the benefit of old versions of GCC, check for anonymous - namespaces based on the demangled name. */ - if (!processing_has_namespace_info - && cu->language == language_cplus) - cp_scan_for_anonymous_namespaces (sym); - } - return (sym); + return die_lhs->offset == die_rhs->offset; } -/* Copy constant value from an attribute to a symbol. */ +/* Read a whole compilation unit into a linked list of dies. */ -static void -dwarf2_const_value (struct attribute *attr, struct symbol *sym, - struct dwarf2_cu *cu) +static struct die_info * +read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - struct comp_unit_head *cu_header = &cu->header; - enum bfd_endian byte_order = bfd_big_endian (objfile->obfd) ? - BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; - struct dwarf_block *blk; + struct die_reader_specs reader_specs; + int read_abbrevs = 0; + struct cleanup *back_to = NULL; + struct die_info *die; - switch (attr->form) + if (cu->dwarf2_abbrevs == NULL) { - case DW_FORM_addr: - { - struct dwarf2_locexpr_baton *baton; - gdb_byte *data; - - if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size) - dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym), - cu_header->addr_size, - TYPE_LENGTH (SYMBOL_TYPE - (sym))); - /* Symbols of this form are reasonably rare, so we just - piggyback on the existing location code rather than writing - a new implementation of symbol_computed_ops. */ - baton = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_locexpr_baton)); - baton->per_cu = cu->per_cu; - gdb_assert (baton->per_cu); - - baton->size = 2 + cu_header->addr_size; - data = obstack_alloc (&objfile->objfile_obstack, baton->size); - baton->data = data; - - data[0] = DW_OP_addr; - store_unsigned_integer (&data[1], cu_header->addr_size, - byte_order, DW_ADDR (attr)); - data[cu_header->addr_size + 1] = DW_OP_stack_value; + dwarf2_read_abbrevs (cu->objfile->obfd, cu); + back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + read_abbrevs = 1; + } - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; - SYMBOL_CLASS (sym) = LOC_COMPUTED; - } - break; - case DW_FORM_string: - case DW_FORM_strp: - /* DW_STRING is already allocated on the obstack, point directly - to it. */ - SYMBOL_VALUE_BYTES (sym) = (gdb_byte *) DW_STRING (attr); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; - break; - case DW_FORM_block1: - case DW_FORM_block2: - case DW_FORM_block4: - case DW_FORM_block: - case DW_FORM_exprloc: - blk = DW_BLOCK (attr); - if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size) - dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym), - blk->size, - TYPE_LENGTH (SYMBOL_TYPE - (sym))); - SYMBOL_VALUE_BYTES (sym) = - obstack_alloc (&objfile->objfile_obstack, blk->size); - memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; - break; + gdb_assert (cu->die_hash == NULL); + cu->die_hash + = htab_create_alloc_ex (cu->header.length / 12, + die_hash, + die_eq, + NULL, + &cu->comp_unit_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); - /* The DW_AT_const_value attributes are supposed to carry the - symbol's value "represented as it would be on the target - architecture." By the time we get here, it's already been - converted to host endianness, so we just need to sign- or - zero-extend it as appropriate. */ - case DW_FORM_data1: - dwarf2_const_value_data (attr, sym, 8); - break; - case DW_FORM_data2: - dwarf2_const_value_data (attr, sym, 16); - break; - case DW_FORM_data4: - dwarf2_const_value_data (attr, sym, 32); - break; - case DW_FORM_data8: - dwarf2_const_value_data (attr, sym, 64); - break; + init_cu_die_reader (&reader_specs, cu); - case DW_FORM_sdata: - SYMBOL_VALUE (sym) = DW_SND (attr); - SYMBOL_CLASS (sym) = LOC_CONST; - break; + die = read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL); - case DW_FORM_udata: - SYMBOL_VALUE (sym) = DW_UNSND (attr); - SYMBOL_CLASS (sym) = LOC_CONST; - break; + if (read_abbrevs) + do_cleanups (back_to); - default: - complaint (&symfile_complaints, - _("unsupported const value attribute form: '%s'"), - dwarf_form_name (attr->form)); - SYMBOL_VALUE (sym) = 0; - SYMBOL_CLASS (sym) = LOC_CONST; - break; - } + return die; } +/* Main entry point for reading a DIE and all children. + Read the DIE and dump it if requested. */ -/* Given an attr with a DW_FORM_dataN value in host byte order, sign- - or zero-extend it as appropriate for the symbol's type. */ -static void -dwarf2_const_value_data (struct attribute *attr, - struct symbol *sym, - int bits) +static struct die_info * +read_die_and_children (const struct die_reader_specs *reader, + gdb_byte *info_ptr, + gdb_byte **new_info_ptr, + struct die_info *parent) { - LONGEST l = DW_UNSND (attr); + struct die_info *result = read_die_and_children_1 (reader, info_ptr, + new_info_ptr, parent); - if (bits < sizeof (l) * 8) + if (dwarf2_die_debug) { - if (TYPE_UNSIGNED (SYMBOL_TYPE (sym))) - l &= ((LONGEST) 1 << bits) - 1; - else - l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits); + fprintf_unfiltered (gdb_stdlog, + "\nRead die from %s of %s:\n", + reader->buffer == dwarf2_per_objfile->info.buffer + ? ".debug_info" + : reader->buffer == dwarf2_per_objfile->types.buffer + ? ".debug_types" + : "unknown section", + reader->abfd->filename); + dump_die (result, dwarf2_die_debug); } - SYMBOL_VALUE (sym) = l; - SYMBOL_CLASS (sym) = LOC_CONST; + return result; } +/* Read a single die and all its descendents. Set the die's sibling + field to NULL; set other fields in the die correctly, and set all + of the descendents' fields correctly. Set *NEW_INFO_PTR to the + location of the info_ptr after reading all of those dies. PARENT + is the parent of the die in question. */ -/* Return the type of the die in question using its DW_AT_type attribute. */ - -static struct type * -die_type (struct die_info *die, struct dwarf2_cu *cu) +static struct die_info * +read_die_and_children_1 (const struct die_reader_specs *reader, + gdb_byte *info_ptr, + gdb_byte **new_info_ptr, + struct die_info *parent) { - struct attribute *type_attr; - struct die_info *type_die; - - type_attr = dwarf2_attr (die, DW_AT_type, cu); - if (!type_attr) + struct die_info *die; + gdb_byte *cur_ptr; + int has_children; + + cur_ptr = read_full_die (reader, &die, info_ptr, &has_children); + if (die == NULL) { - /* A missing DW_AT_type represents a void type. */ - return objfile_type (cu->objfile)->builtin_void; + *new_info_ptr = cur_ptr; + return NULL; } + store_in_ref_table (die, reader->cu); - type_die = follow_die_ref_or_sig (die, type_attr, &cu); + if (has_children) + die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die); + else + { + die->child = NULL; + *new_info_ptr = cur_ptr; + } - return tag_type_to_type (type_die, cu); + die->sibling = NULL; + die->parent = parent; + return die; } -/* True iff CU's producer generates GNAT Ada auxiliary information - that allows to find parallel types through that information instead - of having to do expensive parallel lookups by type name. */ +/* Read a die, all of its descendents, and all of its siblings; set + all of the fields of all of the dies correctly. Arguments are as + in read_die_and_children. */ -static int -need_gnat_info (struct dwarf2_cu *cu) +static struct die_info * +read_die_and_siblings (const struct die_reader_specs *reader, + gdb_byte *info_ptr, + gdb_byte **new_info_ptr, + struct die_info *parent) { - /* FIXME: brobecker/2010-10-12: As of now, only the AdaCore version - of GNAT produces this auxiliary information, without any indication - that it is produced. Part of enhancing the FSF version of GNAT - to produce that information will be to put in place an indicator - that we can use in order to determine whether the descriptive type - info is available or not. One suggestion that has been made is - to use a new attribute, attached to the CU die. For now, assume - that the descriptive type info is not available. */ - return 0; -} + struct die_info *first_die, *last_sibling; + gdb_byte *cur_ptr; + cur_ptr = info_ptr; + first_die = last_sibling = NULL; -/* Return the auxiliary type of the die in question using its - DW_AT_GNAT_descriptive_type attribute. Returns NULL if the - attribute is not present. */ + while (1) + { + struct die_info *die + = read_die_and_children_1 (reader, cur_ptr, &cur_ptr, parent); -static struct type * -die_descriptive_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct attribute *type_attr; - struct die_info *type_die; + if (die == NULL) + { + *new_info_ptr = cur_ptr; + return first_die; + } - type_attr = dwarf2_attr (die, DW_AT_GNAT_descriptive_type, cu); - if (!type_attr) - return NULL; + if (!first_die) + first_die = die; + else + last_sibling->sibling = die; - type_die = follow_die_ref (die, type_attr, &cu); - return tag_type_to_type (type_die, cu); + last_sibling = die; + } } -/* If DIE has a descriptive_type attribute, then set the TYPE's - descriptive type accordingly. */ +/* Read the die from the .debug_info section buffer. Set DIEP to + point to a newly allocated die with its information, except for its + child, sibling, and parent fields. Set HAS_CHILDREN to tell + whether the die has children or not. */ -static void -set_descriptive_type (struct type *type, struct die_info *die, - struct dwarf2_cu *cu) +static gdb_byte * +read_full_die (const struct die_reader_specs *reader, + struct die_info **diep, gdb_byte *info_ptr, + int *has_children) { - struct type *descriptive_type = die_descriptive_type (die, cu); + unsigned int abbrev_number, bytes_read, i, offset; + struct abbrev_info *abbrev; + struct die_info *die; + struct dwarf2_cu *cu = reader->cu; + bfd *abfd = reader->abfd; - if (descriptive_type) + offset = info_ptr - reader->buffer; + abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + if (!abbrev_number) { - ALLOCATE_GNAT_AUX_TYPE (type); - TYPE_DESCRIPTIVE_TYPE (type) = descriptive_type; + *diep = NULL; + *has_children = 0; + return info_ptr; } -} -/* Return the containing type of the die in question using its - DW_AT_containing_type attribute. */ + abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); + if (!abbrev) + error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), + abbrev_number, + bfd_get_filename (abfd)); -static struct type * -die_containing_type (struct die_info *die, struct dwarf2_cu *cu) -{ - struct attribute *type_attr; - struct die_info *type_die; + die = dwarf_alloc_die (cu, abbrev->num_attrs); + die->offset = offset; + die->tag = abbrev->tag; + die->abbrev = abbrev_number; - type_attr = dwarf2_attr (die, DW_AT_containing_type, cu); - if (!type_attr) - error (_("Dwarf Error: Problem turning containing type into gdb type " - "[in module %s]"), cu->objfile->name); + die->num_attrs = abbrev->num_attrs; + + for (i = 0; i < abbrev->num_attrs; ++i) + info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i], + abfd, info_ptr, cu); - type_die = follow_die_ref_or_sig (die, type_attr, &cu); - return tag_type_to_type (type_die, cu); + *diep = die; + *has_children = abbrev->has_children; + return info_ptr; } -static struct type * -tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu) +/* In DWARF version 2, the description of the debugging information is + stored in a separate .debug_abbrev section. Before we read any + dies from a section we read in all abbreviations and install them + in a hash table. This function also sets flags in CU describing + the data found in the abbrev table. */ + +static void +dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu) { - struct type *this_type; + struct comp_unit_head *cu_header = &cu->header; + gdb_byte *abbrev_ptr; + struct abbrev_info *cur_abbrev; + unsigned int abbrev_number, bytes_read, abbrev_name; + unsigned int abbrev_form, hash_number; + struct attr_abbrev *cur_attrs; + unsigned int allocated_attrs; - this_type = read_type_die (die, cu); - if (!this_type) + /* Initialize dwarf2 abbrevs. */ + obstack_init (&cu->abbrev_obstack); + cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack, + (ABBREV_HASH_SIZE + * sizeof (struct abbrev_info *))); + memset (cu->dwarf2_abbrevs, 0, + ABBREV_HASH_SIZE * sizeof (struct abbrev_info *)); + + dwarf2_read_section (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->abbrev); + abbrev_ptr = dwarf2_per_objfile->abbrev.buffer + cu_header->abbrev_offset; + abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + + allocated_attrs = ATTR_ALLOC_CHUNK; + cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev)); + + /* Loop until we reach an abbrev number of 0. */ + while (abbrev_number) { - char *message, *saved; + cur_abbrev = dwarf_alloc_abbrev (cu); - /* read_type_die already issued a complaint. */ - message = xstrprintf (_(""), - cu->objfile->name, - cu->header.offset, - die->offset); - saved = obstack_copy0 (&cu->objfile->objfile_obstack, - message, strlen (message)); - xfree (message); + /* read in abbrev header */ + cur_abbrev->number = abbrev_number; + cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr); + abbrev_ptr += 1; - this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, cu->objfile); + if (cur_abbrev->tag == DW_TAG_namespace) + cu->has_namespace_info = 1; + + /* now read in declarations */ + abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + while (abbrev_name) + { + if (cur_abbrev->num_attrs == allocated_attrs) + { + allocated_attrs += ATTR_ALLOC_CHUNK; + cur_attrs + = xrealloc (cur_attrs, (allocated_attrs + * sizeof (struct attr_abbrev))); + } + + /* Record whether this compilation unit might have + inter-compilation-unit references. If we don't know what form + this attribute will have, then it might potentially be a + DW_FORM_ref_addr, so we conservatively expect inter-CU + references. */ + + if (abbrev_form == DW_FORM_ref_addr + || abbrev_form == DW_FORM_indirect) + cu->has_form_ref_addr = 1; + + cur_attrs[cur_abbrev->num_attrs].name = abbrev_name; + cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form; + abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + } + + cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack, + (cur_abbrev->num_attrs + * sizeof (struct attr_abbrev))); + memcpy (cur_abbrev->attrs, cur_attrs, + cur_abbrev->num_attrs * sizeof (struct attr_abbrev)); + + hash_number = abbrev_number % ABBREV_HASH_SIZE; + cur_abbrev->next = cu->dwarf2_abbrevs[hash_number]; + cu->dwarf2_abbrevs[hash_number] = cur_abbrev; + + /* Get next abbreviation. + Under Irix6 the abbreviations for a compilation unit are not + always properly terminated with an abbrev number of 0. + Exit loop if we encounter an abbreviation which we have + already read (which means we are about to read the abbreviations + for the next compile unit) or if the end of the abbreviation + table is reached. */ + if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev.buffer) + >= dwarf2_per_objfile->abbrev.size) + break; + abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL) + break; } - return this_type; + + xfree (cur_attrs); } -static struct type * -read_type_die (struct die_info *die, struct dwarf2_cu *cu) +/* Release the memory used by the abbrev table for a compilation unit. */ + +static void +dwarf2_free_abbrev_table (void *ptr_to_cu) { - struct type *this_type; + struct dwarf2_cu *cu = ptr_to_cu; - this_type = get_die_type (die, cu); - if (this_type) - return this_type; + obstack_free (&cu->abbrev_obstack, NULL); + cu->dwarf2_abbrevs = NULL; +} - switch (die->tag) +/* Lookup an abbrev_info structure in the abbrev hash table. */ + +static struct abbrev_info * +dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu) +{ + unsigned int hash_number; + struct abbrev_info *abbrev; + + hash_number = number % ABBREV_HASH_SIZE; + abbrev = cu->dwarf2_abbrevs[hash_number]; + + while (abbrev) { - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - this_type = read_structure_type (die, cu); - break; - case DW_TAG_enumeration_type: - this_type = read_enumeration_type (die, cu); - break; - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: - case DW_TAG_inlined_subroutine: - this_type = read_subroutine_type (die, cu); - break; + if (abbrev->number == number) + return abbrev; + else + abbrev = abbrev->next; + } + return NULL; +} + +/* Returns nonzero if TAG represents a type that we might generate a partial + symbol for. */ + +static int +is_type_tag_for_partial (int tag) +{ + switch (tag) + { +#if 0 + /* Some types that would be reasonable to generate partial symbols for, + that we don't at present. */ case DW_TAG_array_type: - this_type = read_array_type (die, cu); - break; - case DW_TAG_set_type: - this_type = read_set_type (die, cu); - break; - case DW_TAG_pointer_type: - this_type = read_tag_pointer_type (die, cu); - break; + case DW_TAG_file_type: case DW_TAG_ptr_to_member_type: - this_type = read_tag_ptr_to_member_type (die, cu); - break; - case DW_TAG_reference_type: - this_type = read_tag_reference_type (die, cu); - break; - case DW_TAG_const_type: - this_type = read_tag_const_type (die, cu); - break; - case DW_TAG_volatile_type: - this_type = read_tag_volatile_type (die, cu); - break; + case DW_TAG_set_type: case DW_TAG_string_type: - this_type = read_tag_string_type (die, cu); - break; - case DW_TAG_typedef: - this_type = read_typedef (die, cu); - break; - case DW_TAG_subrange_type: - this_type = read_subrange_type (die, cu); - break; + case DW_TAG_subroutine_type: +#endif case DW_TAG_base_type: - this_type = read_base_type (die, cu); - break; - case DW_TAG_unspecified_type: - this_type = read_unspecified_type (die, cu); - break; - case DW_TAG_namespace: - this_type = read_namespace_type (die, cu); - break; - case DW_TAG_module: - this_type = read_module_type (die, cu); - break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_enumeration_type: + case DW_TAG_structure_type: + case DW_TAG_subrange_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + return 1; default: - complaint (&symfile_complaints, _("unexpected tag in read_type_die: '%s'"), - dwarf_tag_name (die->tag)); - break; + return 0; } - - return this_type; } -/* Return the name of the namespace/class that DIE is defined within, - or "" if we can't tell. The caller should not xfree the result. - - For example, if we're within the method foo() in the following - code: - - namespace N { - class C { - void foo () { - } - }; - } - - then determine_prefix on foo's die will return "N::C". */ +/* Load all DIEs that are interesting for partial symbols into memory. */ -static char * -determine_prefix (struct die_info *die, struct dwarf2_cu *cu) +static struct partial_die_info * +load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr, + int building_psymtab, struct dwarf2_cu *cu) { - struct die_info *parent, *spec_die; - struct dwarf2_cu *spec_cu; - struct type *parent_type; + struct partial_die_info *part_die; + struct partial_die_info *parent_die, *last_die, *first_die = NULL; + struct abbrev_info *abbrev; + unsigned int bytes_read; + unsigned int load_all = 0; - if (cu->language != language_cplus && cu->language != language_java - && cu->language != language_fortran) - return ""; + int nesting_level = 1; - /* We have to be careful in the presence of DW_AT_specification. - For example, with GCC 3.4, given the code + parent_die = NULL; + last_die = NULL; - namespace N { - void foo() { - // Definition of N::foo. - } - } + if (cu->per_cu && cu->per_cu->load_all_dies) + load_all = 1; - then we'll have a tree of DIEs like this: + cu->partial_dies + = htab_create_alloc_ex (cu->header.length / 12, + partial_die_hash, + partial_die_eq, + NULL, + &cu->comp_unit_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); - 1: DW_TAG_compile_unit - 2: DW_TAG_namespace // N - 3: DW_TAG_subprogram // declaration of N::foo - 4: DW_TAG_subprogram // definition of N::foo - DW_AT_specification // refers to die #3 + part_die = obstack_alloc (&cu->comp_unit_obstack, + sizeof (struct partial_die_info)); - Thus, when processing die #4, we have to pretend that we're in - the context of its DW_AT_specification, namely the contex of die - #3. */ - spec_cu = cu; - spec_die = die_specification (die, &spec_cu); - if (spec_die == NULL) - parent = die->parent; - else + while (1) { - parent = spec_die->parent; - cu = spec_cu; - } - - if (parent == NULL) - return ""; - else - switch (parent->tag) - { - case DW_TAG_namespace: - parent_type = read_type_die (parent, cu); - /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus - DW_TAG_namespace DIEs with a name of "::" for the global namespace. - Work around this problem here. */ - if (cu->language == language_cplus - && strcmp (TYPE_TAG_NAME (parent_type), "::") == 0) - return ""; - /* We give a name to even anonymous namespaces. */ - return TYPE_TAG_NAME (parent_type); - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_module: - parent_type = read_type_die (parent, cu); - if (TYPE_TAG_NAME (parent_type) != NULL) - return TYPE_TAG_NAME (parent_type); - else - /* An anonymous structure is only allowed non-static data - members; no typedefs, no member functions, et cetera. - So it does not need a prefix. */ - return ""; - default: - return determine_prefix (parent, cu); - } -} + abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); -/* Return a newly-allocated string formed by concatenating PREFIX and - SUFFIX with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then - simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null, - perform an obconcat, otherwise allocate storage for the result. The CU argument - is used to determine the language and hence, the appropriate separator. */ + /* A NULL abbrev means the end of a series of children. */ + if (abbrev == NULL) + { + if (--nesting_level == 0) + { + /* PART_DIE was probably the last thing allocated on the + comp_unit_obstack, so we could call obstack_free + here. We don't do that because the waste is small, + and will be cleaned up when we're done with this + compilation unit. This way, we're also more robust + against other users of the comp_unit_obstack. */ + return first_die; + } + info_ptr += bytes_read; + last_die = parent_die; + parent_die = parent_die->die_parent; + continue; + } -#define MAX_SEP_LEN 7 /* strlen ("__") + strlen ("_MOD_") */ + /* Check for template arguments. We never save these; if + they're seen, we just mark the parent, and go on our way. */ + if (parent_die != NULL + && cu->language == language_cplus + && (abbrev->tag == DW_TAG_template_type_param + || abbrev->tag == DW_TAG_template_value_param)) + { + parent_die->has_template_arguments = 1; -static char * -typename_concat (struct obstack *obs, const char *prefix, const char *suffix, - int physname, struct dwarf2_cu *cu) -{ - const char *lead = ""; - const char *sep; + if (!load_all) + { + /* We don't need a partial DIE for the template argument. */ + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, + cu); + continue; + } + } - if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0') - sep = ""; - else if (cu->language == language_java) - sep = "."; - else if (cu->language == language_fortran && physname) - { - /* This is gfortran specific mangling. Normally DW_AT_linkage_name or - DW_AT_MIPS_linkage_name is preferred and used instead. */ + /* We only recurse into subprograms looking for template arguments. + Skip their other children. */ + if (!load_all + && cu->language == language_cplus + && parent_die != NULL + && parent_die->tag == DW_TAG_subprogram) + { + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); + continue; + } - lead = "__"; - sep = "_MOD_"; - } - else - sep = "::"; + /* Check whether this DIE is interesting enough to save. Normally + we would not be interested in members here, but there may be + later variables referencing them via DW_AT_specification (for + static members). */ + if (!load_all + && !is_type_tag_for_partial (abbrev->tag) + && abbrev->tag != DW_TAG_constant + && abbrev->tag != DW_TAG_enumerator + && abbrev->tag != DW_TAG_subprogram + && abbrev->tag != DW_TAG_lexical_block + && abbrev->tag != DW_TAG_variable + && abbrev->tag != DW_TAG_namespace + && abbrev->tag != DW_TAG_module + && abbrev->tag != DW_TAG_member) + { + /* Otherwise we skip to the next sibling, if any. */ + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); + continue; + } - if (prefix == NULL) - prefix = ""; - if (suffix == NULL) - suffix = ""; + info_ptr = read_partial_die (part_die, abbrev, bytes_read, abfd, + buffer, info_ptr, cu); - if (obs == NULL) - { - char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1); + /* This two-pass algorithm for processing partial symbols has a + high cost in cache pressure. Thus, handle some simple cases + here which cover the majority of C partial symbols. DIEs + which neither have specification tags in them, nor could have + specification tags elsewhere pointing at them, can simply be + processed and discarded. - strcpy (retval, lead); - strcat (retval, prefix); - strcat (retval, sep); - strcat (retval, suffix); - return retval; - } - else - { - /* We have an obstack. */ - return obconcat (obs, lead, prefix, sep, suffix, (char *) NULL); - } -} + This segment is also optional; scan_partial_symbols and + add_partial_symbol will handle these DIEs if we chain + them in normally. When compilers which do not emit large + quantities of duplicate debug information are more common, + this code can probably be removed. */ -/* Return sibling of die, NULL if no sibling. */ + /* Any complete simple types at the top level (pretty much all + of them, for a language without namespaces), can be processed + directly. */ + if (parent_die == NULL + && part_die->has_specification == 0 + && part_die->is_declaration == 0 + && (part_die->tag == DW_TAG_typedef + || part_die->tag == DW_TAG_base_type + || part_die->tag == DW_TAG_subrange_type)) + { + if (building_psymtab && part_die->name != NULL) + add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, + VAR_DOMAIN, LOC_TYPEDEF, + &cu->objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu->language, cu->objfile); + info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); + continue; + } -static struct die_info * -sibling_die (struct die_info *die) -{ - return die->sibling; -} + /* If we're at the second level, and we're an enumerator, and + our parent has no specification (meaning possibly lives in a + namespace elsewhere), then we can add the partial symbol now + instead of queueing it. */ + if (part_die->tag == DW_TAG_enumerator + && parent_die != NULL + && parent_die->die_parent == NULL + && parent_die->tag == DW_TAG_enumeration_type + && parent_die->has_specification == 0) + { + if (part_die->name == NULL) + complaint (&symfile_complaints, + _("malformed enumerator DIE ignored")); + else if (building_psymtab) + add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, + VAR_DOMAIN, LOC_CONST, + (cu->language == language_cplus + || cu->language == language_java) + ? &cu->objfile->global_psymbols + : &cu->objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu->language, cu->objfile); -/* Get name of a die, return NULL if not found. */ + info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); + continue; + } -static char * -dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu, - struct obstack *obstack) -{ - if (name && cu->language == language_cplus) - { - char *canon_name = cp_canonicalize_string (name); + /* We'll save this DIE so link it in. */ + part_die->die_parent = parent_die; + part_die->die_sibling = NULL; + part_die->die_child = NULL; - if (canon_name != NULL) - { - if (strcmp (canon_name, name) != 0) - name = obsavestring (canon_name, strlen (canon_name), - obstack); - xfree (canon_name); - } - } + if (last_die && last_die == parent_die) + last_die->die_child = part_die; + else if (last_die) + last_die->die_sibling = part_die; - return name; -} + last_die = part_die; -/* Get name of a die, return NULL if not found. */ + if (first_die == NULL) + first_die = part_die; -static char * -dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) -{ - struct attribute *attr; + /* Maybe add the DIE to the hash table. Not all DIEs that we + find interesting need to be in the hash table, because we + also have the parent/sibling/child chains; only those that we + might refer to by offset later during partial symbol reading. - attr = dwarf2_attr (die, DW_AT_name, cu); - if (!attr || !DW_STRING (attr)) - return NULL; + For now this means things that might have be the target of a + DW_AT_specification, DW_AT_abstract_origin, or + DW_AT_extension. DW_AT_extension will refer only to + namespaces; DW_AT_abstract_origin refers to functions (and + many things under the function DIE, but we do not recurse + into function DIEs during partial symbol reading) and + possibly variables as well; DW_AT_specification refers to + declarations. Declarations ought to have the DW_AT_declaration + flag. It happens that GCC forgets to put it in sometimes, but + only for functions, not for types. - switch (die->tag) - { - case DW_TAG_compile_unit: - /* Compilation units have a DW_AT_name that is a filename, not - a source language identifier. */ - case DW_TAG_enumeration_type: - case DW_TAG_enumerator: - /* These tags always have simple identifiers already; no need - to canonicalize them. */ - return DW_STRING (attr); + Adding more things than necessary to the hash table is harmless + except for the performance cost. Adding too few will result in + wasted time in find_partial_die, when we reread the compilation + unit with load_all_dies set. */ - case DW_TAG_subprogram: - /* Java constructors will all be named "", so return - the class name when we see this special case. */ - if (cu->language == language_java - && DW_STRING (attr) != NULL - && strcmp (DW_STRING (attr), "") == 0) + if (load_all + || abbrev->tag == DW_TAG_constant + || abbrev->tag == DW_TAG_subprogram + || abbrev->tag == DW_TAG_variable + || abbrev->tag == DW_TAG_namespace + || part_die->is_declaration) { - struct dwarf2_cu *spec_cu = cu; - struct die_info *spec_die; + void **slot; - /* GCJ will output '' for Java constructor names. - For this special case, return the name of the parent class. */ + slot = htab_find_slot_with_hash (cu->partial_dies, part_die, + part_die->offset, INSERT); + *slot = part_die; + } - /* GCJ may output suprogram DIEs with AT_specification set. - If so, use the name of the specified DIE. */ - spec_die = die_specification (die, &spec_cu); - if (spec_die != NULL) - return dwarf2_name (spec_die, spec_cu); + part_die = obstack_alloc (&cu->comp_unit_obstack, + sizeof (struct partial_die_info)); - do - { - die = die->parent; - if (die->tag == DW_TAG_class_type) - return dwarf2_name (die, cu); - } - while (die->tag != DW_TAG_compile_unit); - } - break; + /* For some DIEs we want to follow their children (if any). For C + we have no reason to follow the children of structures; for other + languages we have to, so that we can get at method physnames + to infer fully qualified class names, for DW_AT_specification, + and for C++ template arguments. For C++, we also look one level + inside functions to find template arguments (if the name of the + function does not already contain the template arguments). - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - /* Some GCC versions emit spurious DW_AT_name attributes for unnamed - structures or unions. These were of the form "._%d" in GCC 4.1, - or simply "" or "" in GCC 4.3 - and GCC 4.4. We work around this problem by ignoring these. */ - if (strncmp (DW_STRING (attr), "._", 2) == 0 - || strncmp (DW_STRING (attr), "has_children + && (load_all + || last_die->tag == DW_TAG_namespace + || last_die->tag == DW_TAG_module + || last_die->tag == DW_TAG_enumeration_type + || (cu->language == language_cplus + && last_die->tag == DW_TAG_subprogram + && (last_die->name == NULL + || strchr (last_die->name, '<') == NULL)) + || (cu->language != language_c + && (last_die->tag == DW_TAG_class_type + || last_die->tag == DW_TAG_interface_type + || last_die->tag == DW_TAG_structure_type + || last_die->tag == DW_TAG_union_type)) + || (cu->language == language_ada + && (last_die->tag == DW_TAG_subprogram + || last_die->tag == DW_TAG_lexical_block)))) + { + nesting_level++; + parent_die = last_die; + continue; + } - default: - break; - } + /* Otherwise we skip to the next sibling, if any. */ + info_ptr = locate_pdi_sibling (last_die, buffer, info_ptr, abfd, cu); - if (!DW_STRING_IS_CANONICAL (attr)) - { - DW_STRING (attr) - = dwarf2_canonicalize_name (DW_STRING (attr), cu, - &cu->objfile->objfile_obstack); - DW_STRING_IS_CANONICAL (attr) = 1; + /* Back to the top, do it again. */ } - return DW_STRING (attr); } -/* Return the die that this die in an extension of, or NULL if there - is none. *EXT_CU is the CU containing DIE on input, and the CU - containing the return value on output. */ +/* Read a minimal amount of information into the minimal die structure. */ -static struct die_info * -dwarf2_extension (struct die_info *die, struct dwarf2_cu **ext_cu) +static gdb_byte * +read_partial_die (struct partial_die_info *part_die, + struct abbrev_info *abbrev, + unsigned int abbrev_len, bfd *abfd, + gdb_byte *buffer, gdb_byte *info_ptr, + struct dwarf2_cu *cu) { - struct attribute *attr; + unsigned int i; + struct attribute attr; + int has_low_pc_attr = 0; + int has_high_pc_attr = 0; - attr = dwarf2_attr (die, DW_AT_extension, *ext_cu); - if (attr == NULL) - return NULL; + memset (part_die, 0, sizeof (struct partial_die_info)); - return follow_die_ref (die, attr, ext_cu); -} + part_die->offset = info_ptr - buffer; -/* Convert a DIE tag into its string name. */ + info_ptr += abbrev_len; -static char * -dwarf_tag_name (unsigned tag) -{ - switch (tag) - { - case DW_TAG_padding: - return "DW_TAG_padding"; - case DW_TAG_array_type: - return "DW_TAG_array_type"; - case DW_TAG_class_type: - return "DW_TAG_class_type"; - case DW_TAG_entry_point: - return "DW_TAG_entry_point"; - case DW_TAG_enumeration_type: - return "DW_TAG_enumeration_type"; - case DW_TAG_formal_parameter: - return "DW_TAG_formal_parameter"; - case DW_TAG_imported_declaration: - return "DW_TAG_imported_declaration"; - case DW_TAG_label: - return "DW_TAG_label"; - case DW_TAG_lexical_block: - return "DW_TAG_lexical_block"; - case DW_TAG_member: - return "DW_TAG_member"; - case DW_TAG_pointer_type: - return "DW_TAG_pointer_type"; - case DW_TAG_reference_type: - return "DW_TAG_reference_type"; - case DW_TAG_compile_unit: - return "DW_TAG_compile_unit"; - case DW_TAG_string_type: - return "DW_TAG_string_type"; - case DW_TAG_structure_type: - return "DW_TAG_structure_type"; - case DW_TAG_subroutine_type: - return "DW_TAG_subroutine_type"; - case DW_TAG_typedef: - return "DW_TAG_typedef"; - case DW_TAG_union_type: - return "DW_TAG_union_type"; - case DW_TAG_unspecified_parameters: - return "DW_TAG_unspecified_parameters"; - case DW_TAG_variant: - return "DW_TAG_variant"; - case DW_TAG_common_block: - return "DW_TAG_common_block"; - case DW_TAG_common_inclusion: - return "DW_TAG_common_inclusion"; - case DW_TAG_inheritance: - return "DW_TAG_inheritance"; - case DW_TAG_inlined_subroutine: - return "DW_TAG_inlined_subroutine"; - case DW_TAG_module: - return "DW_TAG_module"; - case DW_TAG_ptr_to_member_type: - return "DW_TAG_ptr_to_member_type"; - case DW_TAG_set_type: - return "DW_TAG_set_type"; - case DW_TAG_subrange_type: - return "DW_TAG_subrange_type"; - case DW_TAG_with_stmt: - return "DW_TAG_with_stmt"; - case DW_TAG_access_declaration: - return "DW_TAG_access_declaration"; - case DW_TAG_base_type: - return "DW_TAG_base_type"; - case DW_TAG_catch_block: - return "DW_TAG_catch_block"; - case DW_TAG_const_type: - return "DW_TAG_const_type"; - case DW_TAG_constant: - return "DW_TAG_constant"; - case DW_TAG_enumerator: - return "DW_TAG_enumerator"; - case DW_TAG_file_type: - return "DW_TAG_file_type"; - case DW_TAG_friend: - return "DW_TAG_friend"; - case DW_TAG_namelist: - return "DW_TAG_namelist"; - case DW_TAG_namelist_item: - return "DW_TAG_namelist_item"; - case DW_TAG_packed_type: - return "DW_TAG_packed_type"; - case DW_TAG_subprogram: - return "DW_TAG_subprogram"; - case DW_TAG_template_type_param: - return "DW_TAG_template_type_param"; - case DW_TAG_template_value_param: - return "DW_TAG_template_value_param"; - case DW_TAG_thrown_type: - return "DW_TAG_thrown_type"; - case DW_TAG_try_block: - return "DW_TAG_try_block"; - case DW_TAG_variant_part: - return "DW_TAG_variant_part"; - case DW_TAG_variable: - return "DW_TAG_variable"; - case DW_TAG_volatile_type: - return "DW_TAG_volatile_type"; - case DW_TAG_dwarf_procedure: - return "DW_TAG_dwarf_procedure"; - case DW_TAG_restrict_type: - return "DW_TAG_restrict_type"; - case DW_TAG_interface_type: - return "DW_TAG_interface_type"; - case DW_TAG_namespace: - return "DW_TAG_namespace"; - case DW_TAG_imported_module: - return "DW_TAG_imported_module"; - case DW_TAG_unspecified_type: - return "DW_TAG_unspecified_type"; - case DW_TAG_partial_unit: - return "DW_TAG_partial_unit"; - case DW_TAG_imported_unit: - return "DW_TAG_imported_unit"; - case DW_TAG_condition: - return "DW_TAG_condition"; - case DW_TAG_shared_type: - return "DW_TAG_shared_type"; - case DW_TAG_type_unit: - return "DW_TAG_type_unit"; - case DW_TAG_MIPS_loop: - return "DW_TAG_MIPS_loop"; - case DW_TAG_HP_array_descriptor: - return "DW_TAG_HP_array_descriptor"; - case DW_TAG_format_label: - return "DW_TAG_format_label"; - case DW_TAG_function_template: - return "DW_TAG_function_template"; - case DW_TAG_class_template: - return "DW_TAG_class_template"; - case DW_TAG_GNU_BINCL: - return "DW_TAG_GNU_BINCL"; - case DW_TAG_GNU_EINCL: - return "DW_TAG_GNU_EINCL"; - case DW_TAG_upc_shared_type: - return "DW_TAG_upc_shared_type"; - case DW_TAG_upc_strict_type: - return "DW_TAG_upc_strict_type"; - case DW_TAG_upc_relaxed_type: - return "DW_TAG_upc_relaxed_type"; - case DW_TAG_PGI_kanji_type: - return "DW_TAG_PGI_kanji_type"; - case DW_TAG_PGI_interface_block: - return "DW_TAG_PGI_interface_block"; - default: - return "DW_TAG_"; - } -} + if (abbrev == NULL) + return info_ptr; -/* Convert a DWARF attribute code into its string name. */ + part_die->tag = abbrev->tag; + part_die->has_children = abbrev->has_children; -static char * -dwarf_attr_name (unsigned attr) -{ - switch (attr) + for (i = 0; i < abbrev->num_attrs; ++i) { - case DW_AT_sibling: - return "DW_AT_sibling"; - case DW_AT_location: - return "DW_AT_location"; - case DW_AT_name: - return "DW_AT_name"; - case DW_AT_ordering: - return "DW_AT_ordering"; - case DW_AT_subscr_data: - return "DW_AT_subscr_data"; - case DW_AT_byte_size: - return "DW_AT_byte_size"; - case DW_AT_bit_offset: - return "DW_AT_bit_offset"; - case DW_AT_bit_size: - return "DW_AT_bit_size"; - case DW_AT_element_list: - return "DW_AT_element_list"; - case DW_AT_stmt_list: - return "DW_AT_stmt_list"; - case DW_AT_low_pc: - return "DW_AT_low_pc"; - case DW_AT_high_pc: - return "DW_AT_high_pc"; - case DW_AT_language: - return "DW_AT_language"; - case DW_AT_member: - return "DW_AT_member"; - case DW_AT_discr: - return "DW_AT_discr"; - case DW_AT_discr_value: - return "DW_AT_discr_value"; - case DW_AT_visibility: - return "DW_AT_visibility"; - case DW_AT_import: - return "DW_AT_import"; - case DW_AT_string_length: - return "DW_AT_string_length"; - case DW_AT_common_reference: - return "DW_AT_common_reference"; - case DW_AT_comp_dir: - return "DW_AT_comp_dir"; - case DW_AT_const_value: - return "DW_AT_const_value"; - case DW_AT_containing_type: - return "DW_AT_containing_type"; - case DW_AT_default_value: - return "DW_AT_default_value"; - case DW_AT_inline: - return "DW_AT_inline"; - case DW_AT_is_optional: - return "DW_AT_is_optional"; - case DW_AT_lower_bound: - return "DW_AT_lower_bound"; - case DW_AT_producer: - return "DW_AT_producer"; - case DW_AT_prototyped: - return "DW_AT_prototyped"; - case DW_AT_return_addr: - return "DW_AT_return_addr"; - case DW_AT_start_scope: - return "DW_AT_start_scope"; - case DW_AT_bit_stride: - return "DW_AT_bit_stride"; - case DW_AT_upper_bound: - return "DW_AT_upper_bound"; - case DW_AT_abstract_origin: - return "DW_AT_abstract_origin"; - case DW_AT_accessibility: - return "DW_AT_accessibility"; - case DW_AT_address_class: - return "DW_AT_address_class"; - case DW_AT_artificial: - return "DW_AT_artificial"; - case DW_AT_base_types: - return "DW_AT_base_types"; - case DW_AT_calling_convention: - return "DW_AT_calling_convention"; - case DW_AT_count: - return "DW_AT_count"; - case DW_AT_data_member_location: + info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu); + + /* Store the data if it is of an attribute we want to keep in a + partial symbol table. */ + switch (attr.name) + { + case DW_AT_name: + switch (part_die->tag) + { + case DW_TAG_compile_unit: + case DW_TAG_type_unit: + /* Compilation units have a DW_AT_name that is a filename, not + a source language identifier. */ + case DW_TAG_enumeration_type: + case DW_TAG_enumerator: + /* These tags always have simple identifiers already; no need + to canonicalize them. */ + part_die->name = DW_STRING (&attr); + break; + default: + part_die->name + = dwarf2_canonicalize_name (DW_STRING (&attr), cu, + &cu->objfile->objfile_obstack); + break; + } + break; + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + /* Note that both forms of linkage name might appear. We + assume they will be the same, and we only store the last + one we see. */ + if (cu->language == language_ada) + part_die->name = DW_STRING (&attr); + part_die->linkage_name = DW_STRING (&attr); + break; + case DW_AT_low_pc: + has_low_pc_attr = 1; + part_die->lowpc = DW_ADDR (&attr); + break; + case DW_AT_high_pc: + has_high_pc_attr = 1; + part_die->highpc = DW_ADDR (&attr); + break; + case DW_AT_location: + /* Support the .debug_loc offsets. */ + if (attr_form_is_block (&attr)) + { + part_die->locdesc = DW_BLOCK (&attr); + } + else if (attr_form_is_section_offset (&attr)) + { + dwarf2_complex_location_expr_complaint (); + } + else + { + dwarf2_invalid_attrib_class_complaint ("DW_AT_location", + "partial symbol information"); + } + break; + case DW_AT_external: + part_die->is_external = DW_UNSND (&attr); + break; + case DW_AT_declaration: + part_die->is_declaration = DW_UNSND (&attr); + break; + case DW_AT_type: + part_die->has_type = 1; + break; + case DW_AT_abstract_origin: + case DW_AT_specification: + case DW_AT_extension: + part_die->has_specification = 1; + part_die->spec_offset = dwarf2_get_ref_die_offset (&attr); + break; + case DW_AT_sibling: + /* Ignore absolute siblings, they might point outside of + the current compile unit. */ + if (attr.form == DW_FORM_ref_addr) + complaint (&symfile_complaints, + _("ignoring absolute DW_AT_sibling")); + else + part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr); + break; + case DW_AT_byte_size: + part_die->has_byte_size = 1; + break; + case DW_AT_calling_convention: + /* DWARF doesn't provide a way to identify a program's source-level + entry point. DW_AT_calling_convention attributes are only meant + to describe functions' calling conventions. + + However, because it's a necessary piece of information in + Fortran, and because DW_CC_program is the only piece of debugging + information whose definition refers to a 'main program' at all, + several compilers have begun marking Fortran main programs with + DW_CC_program --- even when those functions use the standard + calling conventions. + + So until DWARF specifies a way to provide this information and + compilers pick up the new representation, we'll support this + practice. */ + if (DW_UNSND (&attr) == DW_CC_program + && cu->language == language_fortran) + { + set_main_name (part_die->name); + + /* As this DIE has a static linkage the name would be difficult + to look up later. */ + language_of_main = language_fortran; + } + break; + default: + break; + } + } + + if (has_low_pc_attr && has_high_pc_attr) + { + /* When using the GNU linker, .gnu.linkonce. sections are used to + eliminate duplicate copies of functions and vtables and such. + The linker will arbitrarily choose one and discard the others. + The AT_*_pc values for such functions refer to local labels in + these sections. If the section from that file was discarded, the + labels are not in the output, so the relocs get a value of 0. + If this is a discarded function, mark the pc bounds as invalid, + so that GDB will ignore it. */ + if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero) + { + struct gdbarch *gdbarch = get_objfile_arch (cu->objfile); + + complaint (&symfile_complaints, + _("DW_AT_low_pc %s is zero " + "for DIE at 0x%x [in module %s]"), + paddress (gdbarch, part_die->lowpc), + part_die->offset, cu->objfile->name); + } + /* dwarf2_get_pc_bounds has also the strict low < high requirement. */ + else if (part_die->lowpc >= part_die->highpc) + { + struct gdbarch *gdbarch = get_objfile_arch (cu->objfile); + + complaint (&symfile_complaints, + _("DW_AT_low_pc %s is not < DW_AT_high_pc %s " + "for DIE at 0x%x [in module %s]"), + paddress (gdbarch, part_die->lowpc), + paddress (gdbarch, part_die->highpc), + part_die->offset, cu->objfile->name); + } + else + part_die->has_pc_info = 1; + } + + return info_ptr; +} + +/* Find a cached partial DIE at OFFSET in CU. */ + +static struct partial_die_info * +find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu) +{ + struct partial_die_info *lookup_die = NULL; + struct partial_die_info part_die; + + part_die.offset = offset; + lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset); + + return lookup_die; +} + +/* Find a partial DIE at OFFSET, which may or may not be in CU, + except in the case of .debug_types DIEs which do not reference + outside their CU (they do however referencing other types via + DW_FORM_ref_sig8). */ + +static struct partial_die_info * +find_partial_die (unsigned int offset, struct dwarf2_cu *cu) +{ + struct dwarf2_per_cu_data *per_cu = NULL; + struct partial_die_info *pd = NULL; + + if (cu->per_cu->from_debug_types) + { + pd = find_partial_die_in_comp_unit (offset, cu); + if (pd != NULL) + return pd; + goto not_found; + } + + if (offset_in_cu_p (&cu->header, offset)) + { + pd = find_partial_die_in_comp_unit (offset, cu); + if (pd != NULL) + return pd; + } + + per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); + + if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL) + load_partial_comp_unit (per_cu, cu->objfile); + + per_cu->cu->last_used = 0; + pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + + if (pd == NULL && per_cu->load_all_dies == 0) + { + struct cleanup *back_to; + struct partial_die_info comp_unit_die; + struct abbrev_info *abbrev; + unsigned int bytes_read; + char *info_ptr; + + per_cu->load_all_dies = 1; + + /* Re-read the DIEs. */ + back_to = make_cleanup (null_cleanup, 0); + if (per_cu->cu->dwarf2_abbrevs == NULL) + { + dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu); + make_cleanup (dwarf2_free_abbrev_table, per_cu->cu); + } + info_ptr = (dwarf2_per_objfile->info.buffer + + per_cu->cu->header.offset + + per_cu->cu->header.first_die_offset); + abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu); + info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, + per_cu->cu->objfile->obfd, + dwarf2_per_objfile->info.buffer, info_ptr, + per_cu->cu); + if (comp_unit_die.has_children) + load_partial_dies (per_cu->cu->objfile->obfd, + dwarf2_per_objfile->info.buffer, info_ptr, + 0, per_cu->cu); + do_cleanups (back_to); + + pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + } + + not_found: + + if (pd == NULL) + internal_error (__FILE__, __LINE__, + _("could not find partial DIE 0x%x " + "in cache [from module %s]\n"), + offset, bfd_get_filename (cu->objfile->obfd)); + return pd; +} + +/* See if we can figure out if the class lives in a namespace. We do + this by looking for a member function; its demangled name will + contain namespace info, if there is any. */ + +static void +guess_partial_die_structure_name (struct partial_die_info *struct_pdi, + struct dwarf2_cu *cu) +{ + /* NOTE: carlton/2003-10-07: Getting the info this way changes + what template types look like, because the demangler + frequently doesn't give the same name as the debug info. We + could fix this by only using the demangled name to get the + prefix (but see comment in read_structure_type). */ + + struct partial_die_info *real_pdi; + struct partial_die_info *child_pdi; + + /* If this DIE (this DIE's specification, if any) has a parent, then + we should not do this. We'll prepend the parent's fully qualified + name when we create the partial symbol. */ + + real_pdi = struct_pdi; + while (real_pdi->has_specification) + real_pdi = find_partial_die (real_pdi->spec_offset, cu); + + if (real_pdi->die_parent != NULL) + return; + + for (child_pdi = struct_pdi->die_child; + child_pdi != NULL; + child_pdi = child_pdi->die_sibling) + { + if (child_pdi->tag == DW_TAG_subprogram + && child_pdi->linkage_name != NULL) + { + char *actual_class_name + = language_class_name_from_physname (cu->language_defn, + child_pdi->linkage_name); + if (actual_class_name != NULL) + { + struct_pdi->name + = obsavestring (actual_class_name, + strlen (actual_class_name), + &cu->objfile->objfile_obstack); + xfree (actual_class_name); + } + break; + } + } +} + +/* Adjust PART_DIE before generating a symbol for it. This function + may set the is_external flag or change the DIE's name. */ + +static void +fixup_partial_die (struct partial_die_info *part_die, + struct dwarf2_cu *cu) +{ + /* Once we've fixed up a die, there's no point in doing so again. + This also avoids a memory leak if we were to call + guess_partial_die_structure_name multiple times. */ + if (part_die->fixup_called) + return; + + /* If we found a reference attribute and the DIE has no name, try + to find a name in the referred to DIE. */ + + if (part_die->name == NULL && part_die->has_specification) + { + struct partial_die_info *spec_die; + + spec_die = find_partial_die (part_die->spec_offset, cu); + + fixup_partial_die (spec_die, cu); + + if (spec_die->name) + { + part_die->name = spec_die->name; + + /* Copy DW_AT_external attribute if it is set. */ + if (spec_die->is_external) + part_die->is_external = spec_die->is_external; + } + } + + /* Set default names for some unnamed DIEs. */ + + if (part_die->name == NULL && part_die->tag == DW_TAG_namespace) + part_die->name = CP_ANONYMOUS_NAMESPACE_STR; + + /* If there is no parent die to provide a namespace, and there are + children, see if we can determine the namespace from their linkage + name. + NOTE: We need to do this even if cu->has_namespace_info != 0. + gcc-4.5 -gdwarf-4 can drop the enclosing namespace. */ + if (cu->language == language_cplus + && dwarf2_per_objfile->types.asection != NULL + && part_die->die_parent == NULL + && part_die->has_children + && (part_die->tag == DW_TAG_class_type + || part_die->tag == DW_TAG_structure_type + || part_die->tag == DW_TAG_union_type)) + guess_partial_die_structure_name (part_die, cu); + + /* GCC might emit a nameless struct or union that has a linkage + name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */ + if (part_die->name == NULL + && (part_die->tag == DW_TAG_structure_type + || part_die->tag == DW_TAG_union_type + || part_die->tag == DW_TAG_class_type) + && part_die->linkage_name != NULL) + { + char *demangled; + + demangled = cplus_demangle (part_die->linkage_name, DMGL_TYPES); + if (demangled) + { + part_die->name = obsavestring (demangled, strlen (demangled), + &cu->objfile->objfile_obstack); + xfree (demangled); + } + } + + part_die->fixup_called = 1; +} + +/* Read an attribute value described by an attribute form. */ + +static gdb_byte * +read_attribute_value (struct attribute *attr, unsigned form, + bfd *abfd, gdb_byte *info_ptr, + struct dwarf2_cu *cu) +{ + struct comp_unit_head *cu_header = &cu->header; + unsigned int bytes_read; + struct dwarf_block *blk; + + attr->form = form; + switch (form) + { + case DW_FORM_ref_addr: + if (cu->header.version == 2) + DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read); + else + DW_ADDR (attr) = read_offset (abfd, info_ptr, + &cu->header, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_addr: + DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_block2: + blk = dwarf_alloc_block (cu); + blk->size = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_block4: + blk = dwarf_alloc_block (cu); + blk->size = read_4_bytes (abfd, info_ptr); + info_ptr += 4; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_data2: + DW_UNSND (attr) = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + break; + case DW_FORM_data4: + DW_UNSND (attr) = read_4_bytes (abfd, info_ptr); + info_ptr += 4; + break; + case DW_FORM_data8: + DW_UNSND (attr) = read_8_bytes (abfd, info_ptr); + info_ptr += 8; + break; + case DW_FORM_sec_offset: + DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_string: + DW_STRING (attr) = read_direct_string (abfd, info_ptr, &bytes_read); + DW_STRING_IS_CANONICAL (attr) = 0; + info_ptr += bytes_read; + break; + case DW_FORM_strp: + DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header, + &bytes_read); + DW_STRING_IS_CANONICAL (attr) = 0; + info_ptr += bytes_read; + break; + case DW_FORM_exprloc: + case DW_FORM_block: + blk = dwarf_alloc_block (cu); + blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_block1: + blk = dwarf_alloc_block (cu); + blk->size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + blk->data = read_n_bytes (abfd, info_ptr, blk->size); + info_ptr += blk->size; + DW_BLOCK (attr) = blk; + break; + case DW_FORM_data1: + DW_UNSND (attr) = read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_flag: + DW_UNSND (attr) = read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_flag_present: + DW_UNSND (attr) = 1; + break; + case DW_FORM_sdata: + DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_udata: + DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + break; + case DW_FORM_ref1: + DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr); + info_ptr += 1; + break; + case DW_FORM_ref2: + DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr); + info_ptr += 2; + break; + case DW_FORM_ref4: + DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr); + info_ptr += 4; + break; + case DW_FORM_ref8: + DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr); + info_ptr += 8; + break; + case DW_FORM_ref_sig8: + /* Convert the signature to something we can record in DW_UNSND + for later lookup. + NOTE: This is NULL if the type wasn't found. */ + DW_SIGNATURED_TYPE (attr) = + lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr)); + info_ptr += 8; + break; + case DW_FORM_ref_udata: + DW_ADDR (attr) = (cu->header.offset + + read_unsigned_leb128 (abfd, info_ptr, &bytes_read)); + info_ptr += bytes_read; + break; + case DW_FORM_indirect: + form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu); + break; + default: + error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"), + dwarf_form_name (form), + bfd_get_filename (abfd)); + } + + /* We have seen instances where the compiler tried to emit a byte + size attribute of -1 which ended up being encoded as an unsigned + 0xffffffff. Although 0xffffffff is technically a valid size value, + an object of this size seems pretty unlikely so we can relatively + safely treat these cases as if the size attribute was invalid and + treat them as zero by default. */ + if (attr->name == DW_AT_byte_size + && form == DW_FORM_data4 + && DW_UNSND (attr) >= 0xffffffff) + { + complaint + (&symfile_complaints, + _("Suspicious DW_AT_byte_size value treated as zero instead of %s"), + hex_string (DW_UNSND (attr))); + DW_UNSND (attr) = 0; + } + + return info_ptr; +} + +/* Read an attribute described by an abbreviated attribute. */ + +static gdb_byte * +read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, + bfd *abfd, gdb_byte *info_ptr, struct dwarf2_cu *cu) +{ + attr->name = abbrev->name; + return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu); +} + +/* Read dwarf information from a buffer. */ + +static unsigned int +read_1_byte (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_8 (abfd, buf); +} + +static int +read_1_signed_byte (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_signed_8 (abfd, buf); +} + +static unsigned int +read_2_bytes (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_16 (abfd, buf); +} + +static int +read_2_signed_bytes (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_signed_16 (abfd, buf); +} + +static unsigned int +read_4_bytes (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_32 (abfd, buf); +} + +static int +read_4_signed_bytes (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_signed_32 (abfd, buf); +} + +static ULONGEST +read_8_bytes (bfd *abfd, gdb_byte *buf) +{ + return bfd_get_64 (abfd, buf); +} + +static CORE_ADDR +read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu, + unsigned int *bytes_read) +{ + struct comp_unit_head *cu_header = &cu->header; + CORE_ADDR retval = 0; + + if (cu_header->signed_addr_p) + { + switch (cu_header->addr_size) + { + case 2: + retval = bfd_get_signed_16 (abfd, buf); + break; + case 4: + retval = bfd_get_signed_32 (abfd, buf); + break; + case 8: + retval = bfd_get_signed_64 (abfd, buf); + break; + default: + internal_error (__FILE__, __LINE__, + _("read_address: bad switch, signed [in module %s]"), + bfd_get_filename (abfd)); + } + } + else + { + switch (cu_header->addr_size) + { + case 2: + retval = bfd_get_16 (abfd, buf); + break; + case 4: + retval = bfd_get_32 (abfd, buf); + break; + case 8: + retval = bfd_get_64 (abfd, buf); + break; + default: + internal_error (__FILE__, __LINE__, + _("read_address: bad switch, " + "unsigned [in module %s]"), + bfd_get_filename (abfd)); + } + } + + *bytes_read = cu_header->addr_size; + return retval; +} + +/* Read the initial length from a section. The (draft) DWARF 3 + specification allows the initial length to take up either 4 bytes + or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8 + bytes describe the length and all offsets will be 8 bytes in length + instead of 4. + + An older, non-standard 64-bit format is also handled by this + function. The older format in question stores the initial length + as an 8-byte quantity without an escape value. Lengths greater + than 2^32 aren't very common which means that the initial 4 bytes + is almost always zero. Since a length value of zero doesn't make + sense for the 32-bit format, this initial zero can be considered to + be an escape value which indicates the presence of the older 64-bit + format. As written, the code can't detect (old format) lengths + greater than 4GB. If it becomes necessary to handle lengths + somewhat larger than 4GB, we could allow other small values (such + as the non-sensical values of 1, 2, and 3) to also be used as + escape values indicating the presence of the old format. + + The value returned via bytes_read should be used to increment the + relevant pointer after calling read_initial_length(). + + [ Note: read_initial_length() and read_offset() are based on the + document entitled "DWARF Debugging Information Format", revision + 3, draft 8, dated November 19, 2001. This document was obtained + from: + + http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf + + This document is only a draft and is subject to change. (So beware.) + + Details regarding the older, non-standard 64-bit format were + determined empirically by examining 64-bit ELF files produced by + the SGI toolchain on an IRIX 6.5 machine. + + - Kevin, July 16, 2002 + ] */ + +static LONGEST +read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read) +{ + LONGEST length = bfd_get_32 (abfd, buf); + + if (length == 0xffffffff) + { + length = bfd_get_64 (abfd, buf + 4); + *bytes_read = 12; + } + else if (length == 0) + { + /* Handle the (non-standard) 64-bit DWARF2 format used by IRIX. */ + length = bfd_get_64 (abfd, buf); + *bytes_read = 8; + } + else + { + *bytes_read = 4; + } + + return length; +} + +/* Cover function for read_initial_length. + Returns the length of the object at BUF, and stores the size of the + initial length in *BYTES_READ and stores the size that offsets will be in + *OFFSET_SIZE. + If the initial length size is not equivalent to that specified in + CU_HEADER then issue a complaint. + This is useful when reading non-comp-unit headers. */ + +static LONGEST +read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf, + const struct comp_unit_head *cu_header, + unsigned int *bytes_read, + unsigned int *offset_size) +{ + LONGEST length = read_initial_length (abfd, buf, bytes_read); + + gdb_assert (cu_header->initial_length_size == 4 + || cu_header->initial_length_size == 8 + || cu_header->initial_length_size == 12); + + if (cu_header->initial_length_size != *bytes_read) + complaint (&symfile_complaints, + _("intermixed 32-bit and 64-bit DWARF sections")); + + *offset_size = (*bytes_read == 4) ? 4 : 8; + return length; +} + +/* Read an offset from the data stream. The size of the offset is + given by cu_header->offset_size. */ + +static LONGEST +read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header, + unsigned int *bytes_read) +{ + LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size); + + *bytes_read = cu_header->offset_size; + return offset; +} + +/* Read an offset from the data stream. */ + +static LONGEST +read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size) +{ + LONGEST retval = 0; + + switch (offset_size) + { + case 4: + retval = bfd_get_32 (abfd, buf); + break; + case 8: + retval = bfd_get_64 (abfd, buf); + break; + default: + internal_error (__FILE__, __LINE__, + _("read_offset_1: bad switch [in module %s]"), + bfd_get_filename (abfd)); + } + + return retval; +} + +static gdb_byte * +read_n_bytes (bfd *abfd, gdb_byte *buf, unsigned int size) +{ + /* If the size of a host char is 8 bits, we can return a pointer + to the buffer, otherwise we have to copy the data to a buffer + allocated on the temporary obstack. */ + gdb_assert (HOST_CHAR_BIT == 8); + return buf; +} + +static char * +read_direct_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) +{ + /* If the size of a host char is 8 bits, we can return a pointer + to the string, otherwise we have to copy the string to a buffer + allocated on the temporary obstack. */ + gdb_assert (HOST_CHAR_BIT == 8); + if (*buf == '\0') + { + *bytes_read_ptr = 1; + return NULL; + } + *bytes_read_ptr = strlen ((char *) buf) + 1; + return (char *) buf; +} + +static char * +read_indirect_string (bfd *abfd, gdb_byte *buf, + const struct comp_unit_head *cu_header, + unsigned int *bytes_read_ptr) +{ + LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); + + dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str); + if (dwarf2_per_objfile->str.buffer == NULL) + { + error (_("DW_FORM_strp used without .debug_str section [in module %s]"), + bfd_get_filename (abfd)); + return NULL; + } + if (str_offset >= dwarf2_per_objfile->str.size) + { + error (_("DW_FORM_strp pointing outside of " + ".debug_str section [in module %s]"), + bfd_get_filename (abfd)); + return NULL; + } + gdb_assert (HOST_CHAR_BIT == 8); + if (dwarf2_per_objfile->str.buffer[str_offset] == '\0') + return NULL; + return (char *) (dwarf2_per_objfile->str.buffer + str_offset); +} + +static unsigned long +read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) +{ + unsigned long result; + unsigned int num_read; + int i, shift; + unsigned char byte; + + result = 0; + shift = 0; + num_read = 0; + i = 0; + while (1) + { + byte = bfd_get_8 (abfd, buf); + buf++; + num_read++; + result |= ((unsigned long)(byte & 127) << shift); + if ((byte & 128) == 0) + { + break; + } + shift += 7; + } + *bytes_read_ptr = num_read; + return result; +} + +static long +read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) +{ + long result; + int i, shift, num_read; + unsigned char byte; + + result = 0; + shift = 0; + num_read = 0; + i = 0; + while (1) + { + byte = bfd_get_8 (abfd, buf); + buf++; + num_read++; + result |= ((long)(byte & 127) << shift); + shift += 7; + if ((byte & 128) == 0) + { + break; + } + } + if ((shift < 8 * sizeof (result)) && (byte & 0x40)) + result |= -(((long)1) << shift); + *bytes_read_ptr = num_read; + return result; +} + +/* Return a pointer to just past the end of an LEB128 number in BUF. */ + +static gdb_byte * +skip_leb128 (bfd *abfd, gdb_byte *buf) +{ + int byte; + + while (1) + { + byte = bfd_get_8 (abfd, buf); + buf++; + if ((byte & 128) == 0) + return buf; + } +} + +static void +set_cu_language (unsigned int lang, struct dwarf2_cu *cu) +{ + switch (lang) + { + case DW_LANG_C89: + case DW_LANG_C99: + case DW_LANG_C: + cu->language = language_c; + break; + case DW_LANG_C_plus_plus: + cu->language = language_cplus; + break; + case DW_LANG_D: + cu->language = language_d; + break; + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + cu->language = language_fortran; + break; + case DW_LANG_Mips_Assembler: + cu->language = language_asm; + break; + case DW_LANG_Java: + cu->language = language_java; + break; + case DW_LANG_Ada83: + case DW_LANG_Ada95: + cu->language = language_ada; + break; + case DW_LANG_Modula2: + cu->language = language_m2; + break; + case DW_LANG_Pascal83: + cu->language = language_pascal; + break; + case DW_LANG_ObjC: + cu->language = language_objc; + break; + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + default: + cu->language = language_minimal; + break; + } + cu->language_defn = language_def (cu->language); +} + +/* Return the named attribute or NULL if not there. */ + +static struct attribute * +dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) +{ + unsigned int i; + struct attribute *spec = NULL; + + for (i = 0; i < die->num_attrs; ++i) + { + if (die->attrs[i].name == name) + return &die->attrs[i]; + if (die->attrs[i].name == DW_AT_specification + || die->attrs[i].name == DW_AT_abstract_origin) + spec = &die->attrs[i]; + } + + if (spec) + { + die = follow_die_ref (die, spec, &cu); + return dwarf2_attr (die, name, cu); + } + + return NULL; +} + +/* Return the named attribute or NULL if not there, + but do not follow DW_AT_specification, etc. + This is for use in contexts where we're reading .debug_types dies. + Following DW_AT_specification, DW_AT_abstract_origin will take us + back up the chain, and we want to go down. */ + +static struct attribute * +dwarf2_attr_no_follow (struct die_info *die, unsigned int name, + struct dwarf2_cu *cu) +{ + unsigned int i; + + for (i = 0; i < die->num_attrs; ++i) + if (die->attrs[i].name == name) + return &die->attrs[i]; + + return NULL; +} + +/* Return non-zero iff the attribute NAME is defined for the given DIE, + and holds a non-zero value. This function should only be used for + DW_FORM_flag or DW_FORM_flag_present attributes. */ + +static int +dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu) +{ + struct attribute *attr = dwarf2_attr (die, name, cu); + + return (attr && DW_UNSND (attr)); +} + +static int +die_is_declaration (struct die_info *die, struct dwarf2_cu *cu) +{ + /* A DIE is a declaration if it has a DW_AT_declaration attribute + which value is non-zero. However, we have to be careful with + DIEs having a DW_AT_specification attribute, because dwarf2_attr() + (via dwarf2_flag_true_p) follows this attribute. So we may + end up accidently finding a declaration attribute that belongs + to a different DIE referenced by the specification attribute, + even though the given DIE does not have a declaration attribute. */ + return (dwarf2_flag_true_p (die, DW_AT_declaration, cu) + && dwarf2_attr (die, DW_AT_specification, cu) == NULL); +} + +/* Return the die giving the specification for DIE, if there is + one. *SPEC_CU is the CU containing DIE on input, and the CU + containing the return value on output. If there is no + specification, but there is an abstract origin, that is + returned. */ + +static struct die_info * +die_specification (struct die_info *die, struct dwarf2_cu **spec_cu) +{ + struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, + *spec_cu); + + if (spec_attr == NULL) + spec_attr = dwarf2_attr (die, DW_AT_abstract_origin, *spec_cu); + + if (spec_attr == NULL) + return NULL; + else + return follow_die_ref (die, spec_attr, spec_cu); +} + +/* Free the line_header structure *LH, and any arrays and strings it + refers to. + NOTE: This is also used as a "cleanup" function. */ + +static void +free_line_header (struct line_header *lh) +{ + if (lh->standard_opcode_lengths) + xfree (lh->standard_opcode_lengths); + + /* Remember that all the lh->file_names[i].name pointers are + pointers into debug_line_buffer, and don't need to be freed. */ + if (lh->file_names) + xfree (lh->file_names); + + /* Similarly for the include directory names. */ + if (lh->include_dirs) + xfree (lh->include_dirs); + + xfree (lh); +} + +/* Add an entry to LH's include directory table. */ + +static void +add_include_dir (struct line_header *lh, char *include_dir) +{ + /* Grow the array if necessary. */ + if (lh->include_dirs_size == 0) + { + lh->include_dirs_size = 1; /* for testing */ + lh->include_dirs = xmalloc (lh->include_dirs_size + * sizeof (*lh->include_dirs)); + } + else if (lh->num_include_dirs >= lh->include_dirs_size) + { + lh->include_dirs_size *= 2; + lh->include_dirs = xrealloc (lh->include_dirs, + (lh->include_dirs_size + * sizeof (*lh->include_dirs))); + } + + lh->include_dirs[lh->num_include_dirs++] = include_dir; +} + +/* Add an entry to LH's file name table. */ + +static void +add_file_name (struct line_header *lh, + char *name, + unsigned int dir_index, + unsigned int mod_time, + unsigned int length) +{ + struct file_entry *fe; + + /* Grow the array if necessary. */ + if (lh->file_names_size == 0) + { + lh->file_names_size = 1; /* for testing */ + lh->file_names = xmalloc (lh->file_names_size + * sizeof (*lh->file_names)); + } + else if (lh->num_file_names >= lh->file_names_size) + { + lh->file_names_size *= 2; + lh->file_names = xrealloc (lh->file_names, + (lh->file_names_size + * sizeof (*lh->file_names))); + } + + fe = &lh->file_names[lh->num_file_names++]; + fe->name = name; + fe->dir_index = dir_index; + fe->mod_time = mod_time; + fe->length = length; + fe->included_p = 0; + fe->symtab = NULL; +} + +/* Read the statement program header starting at OFFSET in + .debug_line, according to the endianness of ABFD. Return a pointer + to a struct line_header, allocated using xmalloc. + + NOTE: the strings in the include directory and file name tables of + the returned object point into debug_line_buffer, and must not be + freed. */ + +static struct line_header * +dwarf_decode_line_header (unsigned int offset, bfd *abfd, + struct dwarf2_cu *cu) +{ + struct cleanup *back_to; + struct line_header *lh; + gdb_byte *line_ptr; + unsigned int bytes_read, offset_size; + int i; + char *cur_dir, *cur_file; + + dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line); + if (dwarf2_per_objfile->line.buffer == NULL) + { + complaint (&symfile_complaints, _("missing .debug_line section")); + return 0; + } + + /* Make sure that at least there's room for the total_length field. + That could be 12 bytes long, but we're just going to fudge that. */ + if (offset + 4 >= dwarf2_per_objfile->line.size) + { + dwarf2_statement_list_fits_in_line_number_section_complaint (); + return 0; + } + + lh = xmalloc (sizeof (*lh)); + memset (lh, 0, sizeof (*lh)); + back_to = make_cleanup ((make_cleanup_ftype *) free_line_header, + (void *) lh); + + line_ptr = dwarf2_per_objfile->line.buffer + offset; + + /* Read in the header. */ + lh->total_length = + read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header, + &bytes_read, &offset_size); + line_ptr += bytes_read; + if (line_ptr + lh->total_length > (dwarf2_per_objfile->line.buffer + + dwarf2_per_objfile->line.size)) + { + dwarf2_statement_list_fits_in_line_number_section_complaint (); + return 0; + } + lh->statement_program_end = line_ptr + lh->total_length; + lh->version = read_2_bytes (abfd, line_ptr); + line_ptr += 2; + lh->header_length = read_offset_1 (abfd, line_ptr, offset_size); + line_ptr += offset_size; + lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); + line_ptr += 1; + if (lh->version >= 4) + { + lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } + else + lh->maximum_ops_per_instruction = 1; + + if (lh->maximum_ops_per_instruction == 0) + { + lh->maximum_ops_per_instruction = 1; + complaint (&symfile_complaints, + _("invalid maximum_ops_per_instruction " + "in `.debug_line' section")); + } + + lh->default_is_stmt = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->line_base = read_1_signed_byte (abfd, line_ptr); + line_ptr += 1; + lh->line_range = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->opcode_base = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->standard_opcode_lengths + = xmalloc (lh->opcode_base * sizeof (lh->standard_opcode_lengths[0])); + + lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ + for (i = 1; i < lh->opcode_base; ++i) + { + lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } + + /* Read directory table. */ + while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + { + line_ptr += bytes_read; + add_include_dir (lh, cur_dir); + } + line_ptr += bytes_read; + + /* Read file name table. */ + while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + { + unsigned int dir_index, mod_time, length; + + line_ptr += bytes_read; + dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + + add_file_name (lh, cur_file, dir_index, mod_time, length); + } + line_ptr += bytes_read; + lh->statement_program_start = line_ptr; + + if (line_ptr > (dwarf2_per_objfile->line.buffer + + dwarf2_per_objfile->line.size)) + complaint (&symfile_complaints, + _("line number info header doesn't " + "fit in `.debug_line' section")); + + discard_cleanups (back_to); + return lh; +} + +/* This function exists to work around a bug in certain compilers + (particularly GCC 2.95), in which the first line number marker of a + function does not show up until after the prologue, right before + the second line number marker. This function shifts ADDRESS down + to the beginning of the function if necessary, and is called on + addresses passed to record_line. */ + +static CORE_ADDR +check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu) +{ + struct function_range *fn; + + /* Find the function_range containing address. */ + if (!cu->first_fn) + return address; + + if (!cu->cached_fn) + cu->cached_fn = cu->first_fn; + + fn = cu->cached_fn; + while (fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + fn = cu->first_fn; + while (fn && fn != cu->cached_fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + return address; + + found: + if (fn->seen_line) + return address; + if (address != fn->lowpc) + complaint (&symfile_complaints, + _("misplaced first line number at 0x%lx for '%s'"), + (unsigned long) address, fn->name); + fn->seen_line = 1; + return fn->lowpc; +} + +/* Subroutine of dwarf_decode_lines to simplify it. + Return the file name of the psymtab for included file FILE_INDEX + in line header LH of PST. + COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. + If space for the result is malloc'd, it will be freed by a cleanup. + Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */ + +static char * +psymtab_include_file_name (const struct line_header *lh, int file_index, + const struct partial_symtab *pst, + const char *comp_dir) +{ + const struct file_entry fe = lh->file_names [file_index]; + char *include_name = fe.name; + char *include_name_to_compare = include_name; + char *dir_name = NULL; + const char *pst_filename; + char *copied_name = NULL; + int file_is_pst; + + if (fe.dir_index) + dir_name = lh->include_dirs[fe.dir_index - 1]; + + if (!IS_ABSOLUTE_PATH (include_name) + && (dir_name != NULL || comp_dir != NULL)) + { + /* Avoid creating a duplicate psymtab for PST. + We do this by comparing INCLUDE_NAME and PST_FILENAME. + Before we do the comparison, however, we need to account + for DIR_NAME and COMP_DIR. + First prepend dir_name (if non-NULL). If we still don't + have an absolute path prepend comp_dir (if non-NULL). + However, the directory we record in the include-file's + psymtab does not contain COMP_DIR (to match the + corresponding symtab(s)). + + Example: + + bash$ cd /tmp + bash$ gcc -g ./hello.c + include_name = "hello.c" + dir_name = "." + DW_AT_comp_dir = comp_dir = "/tmp" + DW_AT_name = "./hello.c" */ + + if (dir_name != NULL) + { + include_name = concat (dir_name, SLASH_STRING, + include_name, (char *)NULL); + include_name_to_compare = include_name; + make_cleanup (xfree, include_name); + } + if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL) + { + include_name_to_compare = concat (comp_dir, SLASH_STRING, + include_name, (char *)NULL); + } + } + + pst_filename = pst->filename; + if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL) + { + copied_name = concat (pst->dirname, SLASH_STRING, + pst_filename, (char *)NULL); + pst_filename = copied_name; + } + + file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0; + + if (include_name_to_compare != include_name) + xfree (include_name_to_compare); + if (copied_name != NULL) + xfree (copied_name); + + if (file_is_pst) + return NULL; + return include_name; +} + +/* Ignore this record_line request. */ + +static void +noop_record_line (struct subfile *subfile, int line, CORE_ADDR pc) +{ + return; +} + +/* Decode the Line Number Program (LNP) for the given line_header + structure and CU. The actual information extracted and the type + of structures created from the LNP depends on the value of PST. + + 1. If PST is NULL, then this procedure uses the data from the program + to create all necessary symbol tables, and their linetables. + + 2. If PST is not NULL, this procedure reads the program to determine + the list of files included by the unit represented by PST, and + builds all the associated partial symbol tables. + + COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. + It is used for relative paths in the line table. + NOTE: When processing partial symtabs (pst != NULL), + comp_dir == pst->dirname. + + NOTE: It is important that psymtabs have the same file name (via strcmp) + as the corresponding symtab. Since COMP_DIR is not used in the name of the + symtab we don't use it in the name of the psymtabs we create. + E.g. expand_line_sal requires this when finding psymtabs to expand. + A good testcase for this is mb-inline.exp. */ + +static void +dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd, + struct dwarf2_cu *cu, struct partial_symtab *pst) +{ + gdb_byte *line_ptr, *extended_end; + gdb_byte *line_end; + unsigned int bytes_read, extended_len; + unsigned char op_code, extended_op, adj_opcode; + CORE_ADDR baseaddr; + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const int decode_for_pst_p = (pst != NULL); + struct subfile *last_subfile = NULL, *first_subfile = current_subfile; + void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc) + = record_line; + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + line_ptr = lh->statement_program_start; + line_end = lh->statement_program_end; + + /* Read the statement sequences until there's nothing left. */ + while (line_ptr < line_end) + { + /* state machine registers */ + CORE_ADDR address = 0; + unsigned int file = 1; + unsigned int line = 1; + unsigned int column = 0; + int is_stmt = lh->default_is_stmt; + int basic_block = 0; + int end_sequence = 0; + CORE_ADDR addr; + unsigned char op_index = 0; + + if (!decode_for_pst_p && lh->num_file_names >= file) + { + /* Start a subfile for the current file of the state machine. */ + /* lh->include_dirs and lh->file_names are 0-based, but the + directory and file name numbers in the statement program + are 1-based. */ + struct file_entry *fe = &lh->file_names[file - 1]; + char *dir = NULL; + + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + + dwarf2_start_subfile (fe->name, dir, comp_dir); + } + + /* Decode the table. */ + while (!end_sequence) + { + op_code = read_1_byte (abfd, line_ptr); + line_ptr += 1; + if (line_ptr > line_end) + { + dwarf2_debug_line_missing_end_sequence_complaint (); + break; + } + + if (op_code >= lh->opcode_base) + { + /* Special operand. */ + adj_opcode = op_code - lh->opcode_base; + address += (((op_index + (adj_opcode / lh->line_range)) + / lh->maximum_ops_per_instruction) + * lh->minimum_instruction_length); + op_index = ((op_index + (adj_opcode / lh->line_range)) + % lh->maximum_ops_per_instruction); + line += lh->line_base + (adj_opcode % lh->line_range); + if (lh->num_file_names < file || file == 0) + dwarf2_debug_line_missing_file_complaint (); + /* For now we ignore lines not starting on an + instruction boundary. */ + else if (op_index == 0) + { + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p && is_stmt) + { + if (last_subfile != current_subfile) + { + addr = gdbarch_addr_bits_remove (gdbarch, address); + if (last_subfile) + (*p_record_line) (last_subfile, 0, addr); + last_subfile = current_subfile; + } + /* Append row to matrix using current values. */ + addr = check_cu_functions (address, cu); + addr = gdbarch_addr_bits_remove (gdbarch, addr); + (*p_record_line) (current_subfile, line, addr); + } + } + basic_block = 0; + } + else switch (op_code) + { + case DW_LNS_extended_op: + extended_len = read_unsigned_leb128 (abfd, line_ptr, + &bytes_read); + line_ptr += bytes_read; + extended_end = line_ptr + extended_len; + extended_op = read_1_byte (abfd, line_ptr); + line_ptr += 1; + switch (extended_op) + { + case DW_LNE_end_sequence: + p_record_line = record_line; + end_sequence = 1; + break; + case DW_LNE_set_address: + address = read_address (abfd, line_ptr, cu, &bytes_read); + + if (address == 0 && !dwarf2_per_objfile->has_section_at_zero) + { + /* This line table is for a function which has been + GCd by the linker. Ignore it. PR gdb/12528 */ + + long line_offset + = line_ptr - dwarf2_per_objfile->line.buffer; + + complaint (&symfile_complaints, + _(".debug_line address at offset 0x%lx is 0 " + "[in module %s]"), + line_offset, cu->objfile->name); + p_record_line = noop_record_line; + } + + op_index = 0; + line_ptr += bytes_read; + address += baseaddr; + break; + case DW_LNE_define_file: + { + char *cur_file; + unsigned int dir_index, mod_time, length; + + cur_file = read_direct_string (abfd, line_ptr, + &bytes_read); + line_ptr += bytes_read; + dir_index = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + mod_time = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + length = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + add_file_name (lh, cur_file, dir_index, mod_time, length); + } + break; + case DW_LNE_set_discriminator: + /* The discriminator is not interesting to the debugger; + just ignore it. */ + line_ptr = extended_end; + break; + default: + complaint (&symfile_complaints, + _("mangled .debug_line section")); + return; + } + /* Make sure that we parsed the extended op correctly. If e.g. + we expected a different address size than the producer used, + we may have read the wrong number of bytes. */ + if (line_ptr != extended_end) + { + complaint (&symfile_complaints, + _("mangled .debug_line section")); + return; + } + break; + case DW_LNS_copy: + if (lh->num_file_names < file || file == 0) + dwarf2_debug_line_missing_file_complaint (); + else + { + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p && is_stmt) + { + if (last_subfile != current_subfile) + { + addr = gdbarch_addr_bits_remove (gdbarch, address); + if (last_subfile) + (*p_record_line) (last_subfile, 0, addr); + last_subfile = current_subfile; + } + addr = check_cu_functions (address, cu); + addr = gdbarch_addr_bits_remove (gdbarch, addr); + (*p_record_line) (current_subfile, line, addr); + } + } + basic_block = 0; + break; + case DW_LNS_advance_pc: + { + CORE_ADDR adjust + = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + + address += (((op_index + adjust) + / lh->maximum_ops_per_instruction) + * lh->minimum_instruction_length); + op_index = ((op_index + adjust) + % lh->maximum_ops_per_instruction); + line_ptr += bytes_read; + } + break; + case DW_LNS_advance_line: + line += read_signed_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_set_file: + { + /* The arrays lh->include_dirs and lh->file_names are + 0-based, but the directory and file name numbers in + the statement program are 1-based. */ + struct file_entry *fe; + char *dir = NULL; + + file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + if (lh->num_file_names < file || file == 0) + dwarf2_debug_line_missing_file_complaint (); + else + { + fe = &lh->file_names[file - 1]; + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + if (!decode_for_pst_p) + { + last_subfile = current_subfile; + dwarf2_start_subfile (fe->name, dir, comp_dir); + } + } + } + break; + case DW_LNS_set_column: + column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_negate_stmt: + is_stmt = (!is_stmt); + break; + case DW_LNS_set_basic_block: + basic_block = 1; + break; + /* Add to the address register of the state machine the + address increment value corresponding to special opcode + 255. I.e., this value is scaled by the minimum + instruction length since special opcode 255 would have + scaled the increment. */ + case DW_LNS_const_add_pc: + { + CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range; + + address += (((op_index + adjust) + / lh->maximum_ops_per_instruction) + * lh->minimum_instruction_length); + op_index = ((op_index + adjust) + % lh->maximum_ops_per_instruction); + } + break; + case DW_LNS_fixed_advance_pc: + address += read_2_bytes (abfd, line_ptr); + op_index = 0; + line_ptr += 2; + break; + default: + { + /* Unknown standard opcode, ignore it. */ + int i; + + for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++) + { + (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + } + } + } + } + if (lh->num_file_names < file || file == 0) + dwarf2_debug_line_missing_file_complaint (); + else + { + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p) + { + addr = gdbarch_addr_bits_remove (gdbarch, address); + (*p_record_line) (current_subfile, 0, addr); + } + } + } + + if (decode_for_pst_p) + { + int file_index; + + /* Now that we're done scanning the Line Header Program, we can + create the psymtab of each included file. */ + for (file_index = 0; file_index < lh->num_file_names; file_index++) + if (lh->file_names[file_index].included_p == 1) + { + char *include_name = + psymtab_include_file_name (lh, file_index, pst, comp_dir); + if (include_name != NULL) + dwarf2_create_include_psymtab (include_name, pst, objfile); + } + } + else + { + /* Make sure a symtab is created for every file, even files + which contain only variables (i.e. no code with associated + line numbers). */ + + int i; + struct file_entry *fe; + + for (i = 0; i < lh->num_file_names; i++) + { + char *dir = NULL; + + fe = &lh->file_names[i]; + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + dwarf2_start_subfile (fe->name, dir, comp_dir); + + /* Skip the main file; we don't need it, and it must be + allocated last, so that it will show up before the + non-primary symtabs in the objfile's symtab list. */ + if (current_subfile == first_subfile) + continue; + + if (current_subfile->symtab == NULL) + current_subfile->symtab = allocate_symtab (current_subfile->name, + cu->objfile); + fe->symtab = current_subfile->symtab; + } + } +} + +/* Start a subfile for DWARF. FILENAME is the name of the file and + DIRNAME the name of the source directory which contains FILENAME + or NULL if not known. COMP_DIR is the compilation directory for the + linetable's compilation unit or NULL if not known. + This routine tries to keep line numbers from identical absolute and + relative file names in a common subfile. + + Using the `list' example from the GDB testsuite, which resides in + /srcdir and compiling it with Irix6.2 cc in /compdir using a filename + of /srcdir/list0.c yields the following debugging information for list0.c: + + DW_AT_name: /srcdir/list0.c + DW_AT_comp_dir: /compdir + files.files[0].name: list0.h + files.files[0].dir: /srcdir + files.files[1].name: list0.c + files.files[1].dir: /srcdir + + The line number information for list0.c has to end up in a single + subfile, so that `break /srcdir/list0.c:1' works as expected. + start_subfile will ensure that this happens provided that we pass the + concatenation of files.files[1].dir and files.files[1].name as the + subfile's name. */ + +static void +dwarf2_start_subfile (char *filename, const char *dirname, + const char *comp_dir) +{ + char *fullname; + + /* While reading the DIEs, we call start_symtab(DW_AT_name, DW_AT_comp_dir). + `start_symtab' will always pass the contents of DW_AT_comp_dir as + second argument to start_subfile. To be consistent, we do the + same here. In order not to lose the line information directory, + we concatenate it to the filename when it makes sense. + Note that the Dwarf3 standard says (speaking of filenames in line + information): ``The directory index is ignored for file names + that represent full path names''. Thus ignoring dirname in the + `else' branch below isn't an issue. */ + + if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL) + fullname = concat (dirname, SLASH_STRING, filename, (char *)NULL); + else + fullname = filename; + + start_subfile (fullname, comp_dir); + + if (fullname != filename) + xfree (fullname); +} + +static void +var_decode_location (struct attribute *attr, struct symbol *sym, + struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct comp_unit_head *cu_header = &cu->header; + + /* NOTE drow/2003-01-30: There used to be a comment and some special + code here to turn a symbol with DW_AT_external and a + SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was + necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux + with some versions of binutils) where shared libraries could have + relocations against symbols in their debug information - the + minimal symbol would have the right address, but the debug info + would not. It's no longer necessary, because we will explicitly + apply relocations when we read in the debug information now. */ + + /* A DW_AT_location attribute with no contents indicates that a + variable has been optimized away. */ + if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + return; + } + + /* Handle one degenerate form of location expression specially, to + preserve GDB's previous behavior when section offsets are + specified. If this is just a DW_OP_addr then mark this symbol + as LOC_STATIC. */ + + if (attr_form_is_block (attr) + && DW_BLOCK (attr)->size == 1 + cu_header->addr_size + && DW_BLOCK (attr)->data[0] == DW_OP_addr) + { + unsigned int dummy; + + SYMBOL_VALUE_ADDRESS (sym) = + read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy); + SYMBOL_CLASS (sym) = LOC_STATIC; + fixup_symbol_section (sym, objfile); + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, + SYMBOL_SECTION (sym)); + return; + } + + /* NOTE drow/2002-01-30: It might be worthwhile to have a static + expression evaluator, and use LOC_COMPUTED only when necessary + (i.e. when the value of a register or memory location is + referenced, or a thread-local block, etc.). Then again, it might + not be worthwhile. I'm assuming that it isn't unless performance + or memory numbers show me otherwise. */ + + dwarf2_symbol_mark_computed (attr, sym, cu); + SYMBOL_CLASS (sym) = LOC_COMPUTED; + + if (SYMBOL_COMPUTED_OPS (sym) == &dwarf2_loclist_funcs) + cu->has_loclist = 1; +} + +/* Given a pointer to a DWARF information entry, figure out if we need + to make a symbol table entry for it, and if so, create a new entry + and return a pointer to it. + If TYPE is NULL, determine symbol type from the die, otherwise + used the passed type. + If SPACE is not NULL, use it to hold the new symbol. If it is + NULL, allocate a new symbol on the objfile's obstack. */ + +static struct symbol * +new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, + struct symbol *space) +{ + struct objfile *objfile = cu->objfile; + struct symbol *sym = NULL; + char *name; + struct attribute *attr = NULL; + struct attribute *attr2 = NULL; + CORE_ADDR baseaddr; + struct pending **list_to_add = NULL; + + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + name = dwarf2_name (die, cu); + if (name) + { + const char *linkagename; + int suppress_add = 0; + + if (space) + sym = space; + else + sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol); + OBJSTAT (objfile, n_syms++); + + /* Cache this symbol's name and the name's demangled form (if any). */ + SYMBOL_SET_LANGUAGE (sym, cu->language); + linkagename = dwarf2_physname (name, die, cu); + SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), 0, objfile); + + /* Fortran does not have mangling standard and the mangling does differ + between gfortran, iFort etc. */ + if (cu->language == language_fortran + && symbol_get_demangled_name (&(sym->ginfo)) == NULL) + symbol_set_demangled_name (&(sym->ginfo), + (char *) dwarf2_full_name (name, die, cu), + NULL); + + /* Default assumptions. + Use the passed type or decode it from the die. */ + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + if (type != NULL) + SYMBOL_TYPE (sym) = type; + else + SYMBOL_TYPE (sym) = die_type (die, cu); + attr = dwarf2_attr (die, + inlined_func ? DW_AT_call_line : DW_AT_decl_line, + cu); + if (attr) + { + SYMBOL_LINE (sym) = DW_UNSND (attr); + } + + attr = dwarf2_attr (die, + inlined_func ? DW_AT_call_file : DW_AT_decl_file, + cu); + if (attr) + { + int file_index = DW_UNSND (attr); + + if (cu->line_header == NULL + || file_index > cu->line_header->num_file_names) + complaint (&symfile_complaints, + _("file index out of range")); + else if (file_index > 0) + { + struct file_entry *fe; + + fe = &cu->line_header->file_names[file_index - 1]; + SYMBOL_SYMTAB (sym) = fe->symtab; + } + } + + switch (die->tag) + { + case DW_TAG_label: + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + if (attr) + { + SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr; + } + SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr; + SYMBOL_DOMAIN (sym) = LABEL_DOMAIN; + SYMBOL_CLASS (sym) = LOC_LABEL; + add_symbol_to_list (sym, cu->list_in_scope); + break; + case DW_TAG_subprogram: + /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by + finish_block. */ + SYMBOL_CLASS (sym) = LOC_BLOCK; + attr2 = dwarf2_attr (die, DW_AT_external, cu); + if ((attr2 && (DW_UNSND (attr2) != 0)) + || cu->language == language_ada) + { + /* Subprograms marked external are stored as a global symbol. + Ada subprograms, whether marked external or not, are always + stored as a global symbol, because we want to be able to + access them globally. For instance, we want to be able + to break on a nested subprogram without having to + specify the context. */ + list_to_add = &global_symbols; + } + else + { + list_to_add = cu->list_in_scope; + } + break; + case DW_TAG_inlined_subroutine: + /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by + finish_block. */ + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_INLINED (sym) = 1; + /* Do not add the symbol to any lists. It will be found via + BLOCK_FUNCTION from the blockvector. */ + break; + case DW_TAG_template_value_param: + suppress_add = 1; + /* Fall through. */ + case DW_TAG_constant: + case DW_TAG_variable: + case DW_TAG_member: + /* Compilation with minimal debug info may result in + variables with missing type entries. Change the + misleading `void' type to something sensible. */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID) + SYMBOL_TYPE (sym) + = objfile_type (objfile)->nodebug_data_symbol; + + attr = dwarf2_attr (die, DW_AT_const_value, cu); + /* In the case of DW_TAG_member, we should only be called for + static const members. */ + if (die->tag == DW_TAG_member) + { + /* dwarf2_add_field uses die_is_declaration, + so we do the same. */ + gdb_assert (die_is_declaration (die, cu)); + gdb_assert (attr); + } + if (attr) + { + dwarf2_const_value (attr, sym, cu); + attr2 = dwarf2_attr (die, DW_AT_external, cu); + if (!suppress_add) + { + if (attr2 && (DW_UNSND (attr2) != 0)) + list_to_add = &global_symbols; + else + list_to_add = cu->list_in_scope; + } + break; + } + attr = dwarf2_attr (die, DW_AT_location, cu); + if (attr) + { + var_decode_location (attr, sym, cu); + attr2 = dwarf2_attr (die, DW_AT_external, cu); + if (SYMBOL_CLASS (sym) == LOC_STATIC + && SYMBOL_VALUE_ADDRESS (sym) == 0 + && !dwarf2_per_objfile->has_section_at_zero) + { + /* When a static variable is eliminated by the linker, + the corresponding debug information is not stripped + out, but the variable address is set to null; + do not add such variables into symbol table. */ + } + else if (attr2 && (DW_UNSND (attr2) != 0)) + { + /* Workaround gfortran PR debug/40040 - it uses + DW_AT_location for variables in -fPIC libraries which may + get overriden by other libraries/executable and get + a different address. Resolve it by the minimal symbol + which may come from inferior's executable using copy + relocation. Make this workaround only for gfortran as for + other compilers GDB cannot guess the minimal symbol + Fortran mangling kind. */ + if (cu->language == language_fortran && die->parent + && die->parent->tag == DW_TAG_module + && cu->producer + && strncmp (cu->producer, "GNU Fortran ", 12) == 0) + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + + /* A variable with DW_AT_external is never static, + but it may be block-scoped. */ + list_to_add = (cu->list_in_scope == &file_symbols + ? &global_symbols : cu->list_in_scope); + } + else + list_to_add = cu->list_in_scope; + } + else + { + /* We do not know the address of this symbol. + If it is an external symbol and we have type information + for it, enter the symbol as a LOC_UNRESOLVED symbol. + The address of the variable will then be determined from + the minimal symbol table whenever the variable is + referenced. */ + attr2 = dwarf2_attr (die, DW_AT_external, cu); + if (attr2 && (DW_UNSND (attr2) != 0) + && dwarf2_attr (die, DW_AT_type, cu) != NULL) + { + /* A variable with DW_AT_external is never static, but it + may be block-scoped. */ + list_to_add = (cu->list_in_scope == &file_symbols + ? &global_symbols : cu->list_in_scope); + + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + } + else if (!die_is_declaration (die, cu)) + { + /* Use the default LOC_OPTIMIZED_OUT class. */ + gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT); + if (!suppress_add) + list_to_add = cu->list_in_scope; + } + } + break; + case DW_TAG_formal_parameter: + /* If we are inside a function, mark this as an argument. If + not, we might be looking at an argument to an inlined function + when we do not have enough information to show inlined frames; + pretend it's a local variable in that case so that the user can + still see it. */ + if (context_stack_depth > 0 + && context_stack[context_stack_depth - 1].name != NULL) + SYMBOL_IS_ARGUMENT (sym) = 1; + attr = dwarf2_attr (die, DW_AT_location, cu); + if (attr) + { + var_decode_location (attr, sym, cu); + } + attr = dwarf2_attr (die, DW_AT_const_value, cu); + if (attr) + { + dwarf2_const_value (attr, sym, cu); + } + attr = dwarf2_attr (die, DW_AT_variable_parameter, cu); + if (attr && DW_UNSND (attr)) + { + struct type *ref_type; + + ref_type = lookup_reference_type (SYMBOL_TYPE (sym)); + SYMBOL_TYPE (sym) = ref_type; + } + + list_to_add = cu->list_in_scope; + break; + case DW_TAG_unspecified_parameters: + /* From varargs functions; gdb doesn't seem to have any + interest in this information, so just ignore it for now. + (FIXME?) */ + break; + case DW_TAG_template_type_param: + suppress_add = 1; + /* Fall through. */ + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_set_type: + case DW_TAG_enumeration_type: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; + + { + /* NOTE: carlton/2003-11-10: C++ and Java class symbols shouldn't + really ever be static objects: otherwise, if you try + to, say, break of a class's method and you're in a file + which doesn't mention that class, it won't work unless + the check for all static symbols in lookup_symbol_aux + saves you. See the OtherFileClass tests in + gdb.c++/namespace.exp. */ + + if (!suppress_add) + { + list_to_add = (cu->list_in_scope == &file_symbols + && (cu->language == language_cplus + || cu->language == language_java) + ? &global_symbols : cu->list_in_scope); + + /* The semantics of C++ state that "struct foo { + ... }" also defines a typedef for "foo". A Java + class declaration also defines a typedef for the + class. */ + if (cu->language == language_cplus + || cu->language == language_java + || cu->language == language_ada) + { + /* The symbol's name is already allocated along + with this objfile, so we don't need to + duplicate it for the type. */ + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym); + } + } + } + break; + case DW_TAG_typedef: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + list_to_add = cu->list_in_scope; + break; + case DW_TAG_base_type: + case DW_TAG_subrange_type: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + list_to_add = cu->list_in_scope; + break; + case DW_TAG_enumerator: + attr = dwarf2_attr (die, DW_AT_const_value, cu); + if (attr) + { + dwarf2_const_value (attr, sym, cu); + } + { + /* NOTE: carlton/2003-11-10: See comment above in the + DW_TAG_class_type, etc. block. */ + + list_to_add = (cu->list_in_scope == &file_symbols + && (cu->language == language_cplus + || cu->language == language_java) + ? &global_symbols : cu->list_in_scope); + } + break; + case DW_TAG_namespace: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + list_to_add = &global_symbols; + break; + default: + /* Not a tag we recognize. Hopefully we aren't processing + trash data, but since we must specifically ignore things + we don't recognize, there is nothing else we should do at + this point. */ + complaint (&symfile_complaints, _("unsupported tag: '%s'"), + dwarf_tag_name (die->tag)); + break; + } + + if (suppress_add) + { + sym->hash_next = objfile->template_symbols; + objfile->template_symbols = sym; + list_to_add = NULL; + } + + if (list_to_add != NULL) + add_symbol_to_list (sym, list_to_add); + + /* For the benefit of old versions of GCC, check for anonymous + namespaces based on the demangled name. */ + if (!processing_has_namespace_info + && cu->language == language_cplus) + cp_scan_for_anonymous_namespaces (sym); + } + return (sym); +} + +/* A wrapper for new_symbol_full that always allocates a new symbol. */ + +static struct symbol * +new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +{ + return new_symbol_full (die, type, cu, NULL); +} + +/* Given an attr with a DW_FORM_dataN value in host byte order, + zero-extend it as appropriate for the symbol's type. The DWARF + standard (v4) is not entirely clear about the meaning of using + DW_FORM_dataN for a constant with a signed type, where the type is + wider than the data. The conclusion of a discussion on the DWARF + list was that this is unspecified. We choose to always zero-extend + because that is the interpretation long in use by GCC. */ + +static gdb_byte * +dwarf2_const_value_data (struct attribute *attr, struct type *type, + const char *name, struct obstack *obstack, + struct dwarf2_cu *cu, long *value, int bits) +{ + struct objfile *objfile = cu->objfile; + enum bfd_endian byte_order = bfd_big_endian (objfile->obfd) ? + BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; + LONGEST l = DW_UNSND (attr); + + if (bits < sizeof (*value) * 8) + { + l &= ((LONGEST) 1 << bits) - 1; + *value = l; + } + else if (bits == sizeof (*value) * 8) + *value = l; + else + { + gdb_byte *bytes = obstack_alloc (obstack, bits / 8); + store_unsigned_integer (bytes, bits / 8, byte_order, l); + return bytes; + } + + return NULL; +} + +/* Read a constant value from an attribute. Either set *VALUE, or if + the value does not fit in *VALUE, set *BYTES - either already + allocated on the objfile obstack, or newly allocated on OBSTACK, + or, set *BATON, if we translated the constant to a location + expression. */ + +static void +dwarf2_const_value_attr (struct attribute *attr, struct type *type, + const char *name, struct obstack *obstack, + struct dwarf2_cu *cu, + long *value, gdb_byte **bytes, + struct dwarf2_locexpr_baton **baton) +{ + struct objfile *objfile = cu->objfile; + struct comp_unit_head *cu_header = &cu->header; + struct dwarf_block *blk; + enum bfd_endian byte_order = (bfd_big_endian (objfile->obfd) ? + BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE); + + *value = 0; + *bytes = NULL; + *baton = NULL; + + switch (attr->form) + { + case DW_FORM_addr: + { + gdb_byte *data; + + if (TYPE_LENGTH (type) != cu_header->addr_size) + dwarf2_const_value_length_mismatch_complaint (name, + cu_header->addr_size, + TYPE_LENGTH (type)); + /* Symbols of this form are reasonably rare, so we just + piggyback on the existing location code rather than writing + a new implementation of symbol_computed_ops. */ + *baton = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct dwarf2_locexpr_baton)); + (*baton)->per_cu = cu->per_cu; + gdb_assert ((*baton)->per_cu); + + (*baton)->size = 2 + cu_header->addr_size; + data = obstack_alloc (&objfile->objfile_obstack, (*baton)->size); + (*baton)->data = data; + + data[0] = DW_OP_addr; + store_unsigned_integer (&data[1], cu_header->addr_size, + byte_order, DW_ADDR (attr)); + data[cu_header->addr_size + 1] = DW_OP_stack_value; + } + break; + case DW_FORM_string: + case DW_FORM_strp: + /* DW_STRING is already allocated on the objfile obstack, point + directly to it. */ + *bytes = (gdb_byte *) DW_STRING (attr); + break; + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + case DW_FORM_exprloc: + blk = DW_BLOCK (attr); + if (TYPE_LENGTH (type) != blk->size) + dwarf2_const_value_length_mismatch_complaint (name, blk->size, + TYPE_LENGTH (type)); + *bytes = blk->data; + break; + + /* The DW_AT_const_value attributes are supposed to carry the + symbol's value "represented as it would be on the target + architecture." By the time we get here, it's already been + converted to host endianness, so we just need to sign- or + zero-extend it as appropriate. */ + case DW_FORM_data1: + *bytes = dwarf2_const_value_data (attr, type, name, + obstack, cu, value, 8); + break; + case DW_FORM_data2: + *bytes = dwarf2_const_value_data (attr, type, name, + obstack, cu, value, 16); + break; + case DW_FORM_data4: + *bytes = dwarf2_const_value_data (attr, type, name, + obstack, cu, value, 32); + break; + case DW_FORM_data8: + *bytes = dwarf2_const_value_data (attr, type, name, + obstack, cu, value, 64); + break; + + case DW_FORM_sdata: + *value = DW_SND (attr); + break; + + case DW_FORM_udata: + *value = DW_UNSND (attr); + break; + + default: + complaint (&symfile_complaints, + _("unsupported const value attribute form: '%s'"), + dwarf_form_name (attr->form)); + *value = 0; + break; + } +} + + +/* Copy constant value from an attribute to a symbol. */ + +static void +dwarf2_const_value (struct attribute *attr, struct symbol *sym, + struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct comp_unit_head *cu_header = &cu->header; + long value; + gdb_byte *bytes; + struct dwarf2_locexpr_baton *baton; + + dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym), + SYMBOL_PRINT_NAME (sym), + &objfile->objfile_obstack, cu, + &value, &bytes, &baton); + + if (baton != NULL) + { + SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + SYMBOL_CLASS (sym) = LOC_COMPUTED; + } + else if (bytes != NULL) + { + SYMBOL_VALUE_BYTES (sym) = bytes; + SYMBOL_CLASS (sym) = LOC_CONST_BYTES; + } + else + { + SYMBOL_VALUE (sym) = value; + SYMBOL_CLASS (sym) = LOC_CONST; + } +} + +/* Return the type of the die in question using its DW_AT_type attribute. */ + +static struct type * +die_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *type_attr; + + type_attr = dwarf2_attr (die, DW_AT_type, cu); + if (!type_attr) + { + /* A missing DW_AT_type represents a void type. */ + return objfile_type (cu->objfile)->builtin_void; + } + + return lookup_die_type (die, type_attr, cu); +} + +/* True iff CU's producer generates GNAT Ada auxiliary information + that allows to find parallel types through that information instead + of having to do expensive parallel lookups by type name. */ + +static int +need_gnat_info (struct dwarf2_cu *cu) +{ + /* FIXME: brobecker/2010-10-12: As of now, only the AdaCore version + of GNAT produces this auxiliary information, without any indication + that it is produced. Part of enhancing the FSF version of GNAT + to produce that information will be to put in place an indicator + that we can use in order to determine whether the descriptive type + info is available or not. One suggestion that has been made is + to use a new attribute, attached to the CU die. For now, assume + that the descriptive type info is not available. */ + return 0; +} + +/* Return the auxiliary type of the die in question using its + DW_AT_GNAT_descriptive_type attribute. Returns NULL if the + attribute is not present. */ + +static struct type * +die_descriptive_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *type_attr; + + type_attr = dwarf2_attr (die, DW_AT_GNAT_descriptive_type, cu); + if (!type_attr) + return NULL; + + return lookup_die_type (die, type_attr, cu); +} + +/* If DIE has a descriptive_type attribute, then set the TYPE's + descriptive type accordingly. */ + +static void +set_descriptive_type (struct type *type, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct type *descriptive_type = die_descriptive_type (die, cu); + + if (descriptive_type) + { + ALLOCATE_GNAT_AUX_TYPE (type); + TYPE_DESCRIPTIVE_TYPE (type) = descriptive_type; + } +} + +/* Return the containing type of the die in question using its + DW_AT_containing_type attribute. */ + +static struct type * +die_containing_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *type_attr; + + type_attr = dwarf2_attr (die, DW_AT_containing_type, cu); + if (!type_attr) + error (_("Dwarf Error: Problem turning containing type into gdb type " + "[in module %s]"), cu->objfile->name); + + return lookup_die_type (die, type_attr, cu); +} + +/* Look up the type of DIE in CU using its type attribute ATTR. + If there is no type substitute an error marker. */ + +static struct type * +lookup_die_type (struct die_info *die, struct attribute *attr, + struct dwarf2_cu *cu) +{ + struct type *this_type; + + /* First see if we have it cached. */ + + if (is_ref_attr (attr)) + { + unsigned int offset = dwarf2_get_ref_die_offset (attr); + + this_type = get_die_type_at_offset (offset, cu->per_cu); + } + else if (attr->form == DW_FORM_ref_sig8) + { + struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr); + struct dwarf2_cu *sig_cu; + unsigned int offset; + + /* sig_type will be NULL if the signatured type is missing from + the debug info. */ + if (sig_type == NULL) + error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE " + "at 0x%x [in module %s]"), + die->offset, cu->objfile->name); + + gdb_assert (sig_type->per_cu.from_debug_types); + offset = sig_type->offset + sig_type->type_offset; + this_type = get_die_type_at_offset (offset, &sig_type->per_cu); + } + else + { + dump_die_for_error (die); + error (_("Dwarf Error: Bad type attribute %s [in module %s]"), + dwarf_attr_name (attr->name), cu->objfile->name); + } + + /* If not cached we need to read it in. */ + + if (this_type == NULL) + { + struct die_info *type_die; + struct dwarf2_cu *type_cu = cu; + + type_die = follow_die_ref_or_sig (die, attr, &type_cu); + /* If the type is cached, we should have found it above. */ + gdb_assert (get_die_type (type_die, type_cu) == NULL); + this_type = read_type_die_1 (type_die, type_cu); + } + + /* If we still don't have a type use an error marker. */ + + if (this_type == NULL) + { + char *message, *saved; + + /* read_type_die already issued a complaint. */ + message = xstrprintf (_(""), + cu->objfile->name, + cu->header.offset, + die->offset); + saved = obstack_copy0 (&cu->objfile->objfile_obstack, + message, strlen (message)); + xfree (message); + + this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, cu->objfile); + } + + return this_type; +} + +/* Return the type in DIE, CU. + Returns NULL for invalid types. + + This first does a lookup in the appropriate type_hash table, + and only reads the die in if necessary. + + NOTE: This can be called when reading in partial or full symbols. */ + +static struct type * +read_type_die (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *this_type; + + this_type = get_die_type (die, cu); + if (this_type) + return this_type; + + return read_type_die_1 (die, cu); +} + +/* Read the type in DIE, CU. + Returns NULL for invalid types. */ + +static struct type * +read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *this_type = NULL; + + switch (die->tag) + { + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + this_type = read_structure_type (die, cu); + break; + case DW_TAG_enumeration_type: + this_type = read_enumeration_type (die, cu); + break; + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + case DW_TAG_inlined_subroutine: + this_type = read_subroutine_type (die, cu); + break; + case DW_TAG_array_type: + this_type = read_array_type (die, cu); + break; + case DW_TAG_set_type: + this_type = read_set_type (die, cu); + break; + case DW_TAG_pointer_type: + this_type = read_tag_pointer_type (die, cu); + break; + case DW_TAG_ptr_to_member_type: + this_type = read_tag_ptr_to_member_type (die, cu); + break; + case DW_TAG_reference_type: + this_type = read_tag_reference_type (die, cu); + break; + case DW_TAG_const_type: + this_type = read_tag_const_type (die, cu); + break; + case DW_TAG_volatile_type: + this_type = read_tag_volatile_type (die, cu); + break; + case DW_TAG_string_type: + this_type = read_tag_string_type (die, cu); + break; + case DW_TAG_typedef: + this_type = read_typedef (die, cu); + break; + case DW_TAG_subrange_type: + this_type = read_subrange_type (die, cu); + break; + case DW_TAG_base_type: + this_type = read_base_type (die, cu); + break; + case DW_TAG_unspecified_type: + this_type = read_unspecified_type (die, cu); + break; + case DW_TAG_namespace: + this_type = read_namespace_type (die, cu); + break; + case DW_TAG_module: + this_type = read_module_type (die, cu); + break; + default: + complaint (&symfile_complaints, + _("unexpected tag in read_type_die: '%s'"), + dwarf_tag_name (die->tag)); + break; + } + + return this_type; +} + +/* See if we can figure out if the class lives in a namespace. We do + this by looking for a member function; its demangled name will + contain namespace info, if there is any. + Return the computed name or NULL. + Space for the result is allocated on the objfile's obstack. + This is the full-die version of guess_partial_die_structure_name. + In this case we know DIE has no useful parent. */ + +static char * +guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu) +{ + struct die_info *spec_die; + struct dwarf2_cu *spec_cu; + struct die_info *child; + + spec_cu = cu; + spec_die = die_specification (die, &spec_cu); + if (spec_die != NULL) + { + die = spec_die; + cu = spec_cu; + } + + for (child = die->child; + child != NULL; + child = child->sibling) + { + if (child->tag == DW_TAG_subprogram) + { + struct attribute *attr; + + attr = dwarf2_attr (child, DW_AT_linkage_name, cu); + if (attr == NULL) + attr = dwarf2_attr (child, DW_AT_MIPS_linkage_name, cu); + if (attr != NULL) + { + char *actual_name + = language_class_name_from_physname (cu->language_defn, + DW_STRING (attr)); + char *name = NULL; + + if (actual_name != NULL) + { + char *die_name = dwarf2_name (die, cu); + + if (die_name != NULL + && strcmp (die_name, actual_name) != 0) + { + /* Strip off the class name from the full name. + We want the prefix. */ + int die_name_len = strlen (die_name); + int actual_name_len = strlen (actual_name); + + /* Test for '::' as a sanity check. */ + if (actual_name_len > die_name_len + 2 + && actual_name[actual_name_len + - die_name_len - 1] == ':') + name = + obsavestring (actual_name, + actual_name_len - die_name_len - 2, + &cu->objfile->objfile_obstack); + } + } + xfree (actual_name); + return name; + } + } + } + + return NULL; +} + +/* Return the name of the namespace/class that DIE is defined within, + or "" if we can't tell. The caller should not xfree the result. + + For example, if we're within the method foo() in the following + code: + + namespace N { + class C { + void foo () { + } + }; + } + + then determine_prefix on foo's die will return "N::C". */ + +static char * +determine_prefix (struct die_info *die, struct dwarf2_cu *cu) +{ + struct die_info *parent, *spec_die; + struct dwarf2_cu *spec_cu; + struct type *parent_type; + + if (cu->language != language_cplus && cu->language != language_java + && cu->language != language_fortran) + return ""; + + /* We have to be careful in the presence of DW_AT_specification. + For example, with GCC 3.4, given the code + + namespace N { + void foo() { + // Definition of N::foo. + } + } + + then we'll have a tree of DIEs like this: + + 1: DW_TAG_compile_unit + 2: DW_TAG_namespace // N + 3: DW_TAG_subprogram // declaration of N::foo + 4: DW_TAG_subprogram // definition of N::foo + DW_AT_specification // refers to die #3 + + Thus, when processing die #4, we have to pretend that we're in + the context of its DW_AT_specification, namely the contex of die + #3. */ + spec_cu = cu; + spec_die = die_specification (die, &spec_cu); + if (spec_die == NULL) + parent = die->parent; + else + { + parent = spec_die->parent; + cu = spec_cu; + } + + if (parent == NULL) + return ""; + else if (parent->building_fullname) + { + const char *name; + const char *parent_name; + + /* It has been seen on RealView 2.2 built binaries, + DW_TAG_template_type_param types actually _defined_ as + children of the parent class: + + enum E {}; + template class Class{}; + Class class_e; + + 1: DW_TAG_class_type (Class) + 2: DW_TAG_enumeration_type (E) + 3: DW_TAG_enumerator (enum1:0) + 3: DW_TAG_enumerator (enum2:1) + ... + 2: DW_TAG_template_type_param + DW_AT_type DW_FORM_ref_udata (E) + + Besides being broken debug info, it can put GDB into an + infinite loop. Consider: + + When we're building the full name for Class, we'll start + at Class, and go look over its template type parameters, + finding E. We'll then try to build the full name of E, and + reach here. We're now trying to build the full name of E, + and look over the parent DIE for containing scope. In the + broken case, if we followed the parent DIE of E, we'd again + find Class, and once again go look at its template type + arguments, etc., etc. Simply don't consider such parent die + as source-level parent of this die (it can't be, the language + doesn't allow it), and break the loop here. */ + name = dwarf2_name (die, cu); + parent_name = dwarf2_name (parent, cu); + complaint (&symfile_complaints, + _("template param type '%s' defined within parent '%s'"), + name ? name : "", + parent_name ? parent_name : ""); + return ""; + } + else + switch (parent->tag) + { + case DW_TAG_namespace: + parent_type = read_type_die (parent, cu); + /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus + DW_TAG_namespace DIEs with a name of "::" for the global namespace. + Work around this problem here. */ + if (cu->language == language_cplus + && strcmp (TYPE_TAG_NAME (parent_type), "::") == 0) + return ""; + /* We give a name to even anonymous namespaces. */ + return TYPE_TAG_NAME (parent_type); + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_module: + parent_type = read_type_die (parent, cu); + if (TYPE_TAG_NAME (parent_type) != NULL) + return TYPE_TAG_NAME (parent_type); + else + /* An anonymous structure is only allowed non-static data + members; no typedefs, no member functions, et cetera. + So it does not need a prefix. */ + return ""; + case DW_TAG_compile_unit: + /* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */ + if (cu->language == language_cplus + && dwarf2_per_objfile->types.asection != NULL + && die->child != NULL + && (die->tag == DW_TAG_class_type + || die->tag == DW_TAG_structure_type + || die->tag == DW_TAG_union_type)) + { + char *name = guess_full_die_structure_name (die, cu); + if (name != NULL) + return name; + } + return ""; + default: + return determine_prefix (parent, cu); + } +} + +/* Return a newly-allocated string formed by concatenating PREFIX and SUFFIX + with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then + simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null, perform + an obconcat, otherwise allocate storage for the result. The CU argument is + used to determine the language and hence, the appropriate separator. */ + +#define MAX_SEP_LEN 7 /* strlen ("__") + strlen ("_MOD_") */ + +static char * +typename_concat (struct obstack *obs, const char *prefix, const char *suffix, + int physname, struct dwarf2_cu *cu) +{ + const char *lead = ""; + const char *sep; + + if (suffix == NULL || suffix[0] == '\0' + || prefix == NULL || prefix[0] == '\0') + sep = ""; + else if (cu->language == language_java) + sep = "."; + else if (cu->language == language_fortran && physname) + { + /* This is gfortran specific mangling. Normally DW_AT_linkage_name or + DW_AT_MIPS_linkage_name is preferred and used instead. */ + + lead = "__"; + sep = "_MOD_"; + } + else + sep = "::"; + + if (prefix == NULL) + prefix = ""; + if (suffix == NULL) + suffix = ""; + + if (obs == NULL) + { + char *retval + = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1); + + strcpy (retval, lead); + strcat (retval, prefix); + strcat (retval, sep); + strcat (retval, suffix); + return retval; + } + else + { + /* We have an obstack. */ + return obconcat (obs, lead, prefix, sep, suffix, (char *) NULL); + } +} + +/* Return sibling of die, NULL if no sibling. */ + +static struct die_info * +sibling_die (struct die_info *die) +{ + return die->sibling; +} + +/* Get name of a die, return NULL if not found. */ + +static char * +dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu, + struct obstack *obstack) +{ + if (name && cu->language == language_cplus) + { + char *canon_name = cp_canonicalize_string (name); + + if (canon_name != NULL) + { + if (strcmp (canon_name, name) != 0) + name = obsavestring (canon_name, strlen (canon_name), + obstack); + xfree (canon_name); + } + } + + return name; +} + +/* Get name of a die, return NULL if not found. */ + +static char * +dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_name, cu); + if ((!attr || !DW_STRING (attr)) + && die->tag != DW_TAG_class_type + && die->tag != DW_TAG_interface_type + && die->tag != DW_TAG_structure_type + && die->tag != DW_TAG_union_type) + return NULL; + + switch (die->tag) + { + case DW_TAG_compile_unit: + /* Compilation units have a DW_AT_name that is a filename, not + a source language identifier. */ + case DW_TAG_enumeration_type: + case DW_TAG_enumerator: + /* These tags always have simple identifiers already; no need + to canonicalize them. */ + return DW_STRING (attr); + + case DW_TAG_subprogram: + /* Java constructors will all be named "", so return + the class name when we see this special case. */ + if (cu->language == language_java + && DW_STRING (attr) != NULL + && strcmp (DW_STRING (attr), "") == 0) + { + struct dwarf2_cu *spec_cu = cu; + struct die_info *spec_die; + + /* GCJ will output '' for Java constructor names. + For this special case, return the name of the parent class. */ + + /* GCJ may output suprogram DIEs with AT_specification set. + If so, use the name of the specified DIE. */ + spec_die = die_specification (die, &spec_cu); + if (spec_die != NULL) + return dwarf2_name (spec_die, spec_cu); + + do + { + die = die->parent; + if (die->tag == DW_TAG_class_type) + return dwarf2_name (die, cu); + } + while (die->tag != DW_TAG_compile_unit); + } + break; + + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + /* Some GCC versions emit spurious DW_AT_name attributes for unnamed + structures or unions. These were of the form "._%d" in GCC 4.1, + or simply "" or "" in GCC 4.3 + and GCC 4.4. We work around this problem by ignoring these. */ + if (attr && DW_STRING (attr) + && (strncmp (DW_STRING (attr), "._", 2) == 0 + || strncmp (DW_STRING (attr), "objfile->objfile_obstack); + DW_STRING_IS_CANONICAL (attr) = 1; + xfree (demangled); + } + } + break; + + default: + break; + } + + if (!DW_STRING_IS_CANONICAL (attr)) + { + DW_STRING (attr) + = dwarf2_canonicalize_name (DW_STRING (attr), cu, + &cu->objfile->objfile_obstack); + DW_STRING_IS_CANONICAL (attr) = 1; + } + return DW_STRING (attr); +} + +/* Return the die that this die in an extension of, or NULL if there + is none. *EXT_CU is the CU containing DIE on input, and the CU + containing the return value on output. */ + +static struct die_info * +dwarf2_extension (struct die_info *die, struct dwarf2_cu **ext_cu) +{ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_extension, *ext_cu); + if (attr == NULL) + return NULL; + + return follow_die_ref (die, attr, ext_cu); +} + +/* Convert a DIE tag into its string name. */ + +static char * +dwarf_tag_name (unsigned tag) +{ + switch (tag) + { + case DW_TAG_padding: + return "DW_TAG_padding"; + case DW_TAG_array_type: + return "DW_TAG_array_type"; + case DW_TAG_class_type: + return "DW_TAG_class_type"; + case DW_TAG_entry_point: + return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: + return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: + return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: + return "DW_TAG_imported_declaration"; + case DW_TAG_label: + return "DW_TAG_label"; + case DW_TAG_lexical_block: + return "DW_TAG_lexical_block"; + case DW_TAG_member: + return "DW_TAG_member"; + case DW_TAG_pointer_type: + return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: + return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: + return "DW_TAG_compile_unit"; + case DW_TAG_string_type: + return "DW_TAG_string_type"; + case DW_TAG_structure_type: + return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: + return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: + return "DW_TAG_typedef"; + case DW_TAG_union_type: + return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: + return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: + return "DW_TAG_variant"; + case DW_TAG_common_block: + return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: + return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: + return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: + return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: + return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: + return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: + return "DW_TAG_set_type"; + case DW_TAG_subrange_type: + return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: + return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: + return "DW_TAG_access_declaration"; + case DW_TAG_base_type: + return "DW_TAG_base_type"; + case DW_TAG_catch_block: + return "DW_TAG_catch_block"; + case DW_TAG_const_type: + return "DW_TAG_const_type"; + case DW_TAG_constant: + return "DW_TAG_constant"; + case DW_TAG_enumerator: + return "DW_TAG_enumerator"; + case DW_TAG_file_type: + return "DW_TAG_file_type"; + case DW_TAG_friend: + return "DW_TAG_friend"; + case DW_TAG_namelist: + return "DW_TAG_namelist"; + case DW_TAG_namelist_item: + return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: + return "DW_TAG_packed_type"; + case DW_TAG_subprogram: + return "DW_TAG_subprogram"; + case DW_TAG_template_type_param: + return "DW_TAG_template_type_param"; + case DW_TAG_template_value_param: + return "DW_TAG_template_value_param"; + case DW_TAG_thrown_type: + return "DW_TAG_thrown_type"; + case DW_TAG_try_block: + return "DW_TAG_try_block"; + case DW_TAG_variant_part: + return "DW_TAG_variant_part"; + case DW_TAG_variable: + return "DW_TAG_variable"; + case DW_TAG_volatile_type: + return "DW_TAG_volatile_type"; + case DW_TAG_dwarf_procedure: + return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: + return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: + return "DW_TAG_interface_type"; + case DW_TAG_namespace: + return "DW_TAG_namespace"; + case DW_TAG_imported_module: + return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: + return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: + return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: + return "DW_TAG_imported_unit"; + case DW_TAG_condition: + return "DW_TAG_condition"; + case DW_TAG_shared_type: + return "DW_TAG_shared_type"; + case DW_TAG_type_unit: + return "DW_TAG_type_unit"; + case DW_TAG_MIPS_loop: + return "DW_TAG_MIPS_loop"; + case DW_TAG_HP_array_descriptor: + return "DW_TAG_HP_array_descriptor"; + case DW_TAG_format_label: + return "DW_TAG_format_label"; + case DW_TAG_function_template: + return "DW_TAG_function_template"; + case DW_TAG_class_template: + return "DW_TAG_class_template"; + case DW_TAG_GNU_BINCL: + return "DW_TAG_GNU_BINCL"; + case DW_TAG_GNU_EINCL: + return "DW_TAG_GNU_EINCL"; + case DW_TAG_upc_shared_type: + return "DW_TAG_upc_shared_type"; + case DW_TAG_upc_strict_type: + return "DW_TAG_upc_strict_type"; + case DW_TAG_upc_relaxed_type: + return "DW_TAG_upc_relaxed_type"; + case DW_TAG_PGI_kanji_type: + return "DW_TAG_PGI_kanji_type"; + case DW_TAG_PGI_interface_block: + return "DW_TAG_PGI_interface_block"; + default: + return "DW_TAG_"; + } +} + +/* Convert a DWARF attribute code into its string name. */ + +static char * +dwarf_attr_name (unsigned attr) +{ + switch (attr) + { + case DW_AT_sibling: + return "DW_AT_sibling"; + case DW_AT_location: + return "DW_AT_location"; + case DW_AT_name: + return "DW_AT_name"; + case DW_AT_ordering: + return "DW_AT_ordering"; + case DW_AT_subscr_data: + return "DW_AT_subscr_data"; + case DW_AT_byte_size: + return "DW_AT_byte_size"; + case DW_AT_bit_offset: + return "DW_AT_bit_offset"; + case DW_AT_bit_size: + return "DW_AT_bit_size"; + case DW_AT_element_list: + return "DW_AT_element_list"; + case DW_AT_stmt_list: + return "DW_AT_stmt_list"; + case DW_AT_low_pc: + return "DW_AT_low_pc"; + case DW_AT_high_pc: + return "DW_AT_high_pc"; + case DW_AT_language: + return "DW_AT_language"; + case DW_AT_member: + return "DW_AT_member"; + case DW_AT_discr: + return "DW_AT_discr"; + case DW_AT_discr_value: + return "DW_AT_discr_value"; + case DW_AT_visibility: + return "DW_AT_visibility"; + case DW_AT_import: + return "DW_AT_import"; + case DW_AT_string_length: + return "DW_AT_string_length"; + case DW_AT_common_reference: + return "DW_AT_common_reference"; + case DW_AT_comp_dir: + return "DW_AT_comp_dir"; + case DW_AT_const_value: + return "DW_AT_const_value"; + case DW_AT_containing_type: + return "DW_AT_containing_type"; + case DW_AT_default_value: + return "DW_AT_default_value"; + case DW_AT_inline: + return "DW_AT_inline"; + case DW_AT_is_optional: + return "DW_AT_is_optional"; + case DW_AT_lower_bound: + return "DW_AT_lower_bound"; + case DW_AT_producer: + return "DW_AT_producer"; + case DW_AT_prototyped: + return "DW_AT_prototyped"; + case DW_AT_return_addr: + return "DW_AT_return_addr"; + case DW_AT_start_scope: + return "DW_AT_start_scope"; + case DW_AT_bit_stride: + return "DW_AT_bit_stride"; + case DW_AT_upper_bound: + return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: + return "DW_AT_abstract_origin"; + case DW_AT_accessibility: + return "DW_AT_accessibility"; + case DW_AT_address_class: + return "DW_AT_address_class"; + case DW_AT_artificial: + return "DW_AT_artificial"; + case DW_AT_base_types: + return "DW_AT_base_types"; + case DW_AT_calling_convention: + return "DW_AT_calling_convention"; + case DW_AT_count: + return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; case DW_AT_decl_column: return "DW_AT_decl_column"; @@ -10059,6 +12736,8 @@ dwarf_attr_name (unsigned attr) return "DW_AT_body_end"; case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_GNU_odr_signature: + return "DW_AT_GNU_odr_signature"; /* VMS extensions. */ case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; @@ -10132,8 +12811,8 @@ dwarf_form_name (unsigned form) return "DW_FORM_exprloc"; case DW_FORM_flag_present: return "DW_FORM_flag_present"; - case DW_FORM_sig8: - return "DW_FORM_sig8"; + case DW_FORM_ref_sig8: + return "DW_FORM_ref_sig8"; default: return "DW_FORM_"; } @@ -10142,7 +12821,7 @@ dwarf_form_name (unsigned form) /* Convert a DWARF stack opcode into its string name. */ const char * -dwarf_stack_op_name (unsigned op, int def) +dwarf_stack_op_name (unsigned op) { switch (op) { @@ -10461,2146 +13140,3120 @@ dwarf_stack_op_name (unsigned op, int def) return "DW_OP_GNU_push_tls_address"; case DW_OP_GNU_uninit: return "DW_OP_GNU_uninit"; + case DW_OP_GNU_implicit_pointer: + return "DW_OP_GNU_implicit_pointer"; + default: + return NULL; + } +} + +static char * +dwarf_bool_name (unsigned mybool) +{ + if (mybool) + return "TRUE"; + else + return "FALSE"; +} + +/* Convert a DWARF type code into its string name. */ + +static char * +dwarf_type_encoding_name (unsigned enc) +{ + switch (enc) + { + case DW_ATE_void: + return "DW_ATE_void"; + case DW_ATE_address: + return "DW_ATE_address"; + case DW_ATE_boolean: + return "DW_ATE_boolean"; + case DW_ATE_complex_float: + return "DW_ATE_complex_float"; + case DW_ATE_float: + return "DW_ATE_float"; + case DW_ATE_signed: + return "DW_ATE_signed"; + case DW_ATE_signed_char: + return "DW_ATE_signed_char"; + case DW_ATE_unsigned: + return "DW_ATE_unsigned"; + case DW_ATE_unsigned_char: + return "DW_ATE_unsigned_char"; + /* DWARF 3. */ + case DW_ATE_imaginary_float: + return "DW_ATE_imaginary_float"; + case DW_ATE_packed_decimal: + return "DW_ATE_packed_decimal"; + case DW_ATE_numeric_string: + return "DW_ATE_numeric_string"; + case DW_ATE_edited: + return "DW_ATE_edited"; + case DW_ATE_signed_fixed: + return "DW_ATE_signed_fixed"; + case DW_ATE_unsigned_fixed: + return "DW_ATE_unsigned_fixed"; + case DW_ATE_decimal_float: + return "DW_ATE_decimal_float"; + /* DWARF 4. */ + case DW_ATE_UTF: + return "DW_ATE_UTF"; + /* HP extensions. */ + case DW_ATE_HP_float80: + return "DW_ATE_HP_float80"; + case DW_ATE_HP_complex_float80: + return "DW_ATE_HP_complex_float80"; + case DW_ATE_HP_float128: + return "DW_ATE_HP_float128"; + case DW_ATE_HP_complex_float128: + return "DW_ATE_HP_complex_float128"; + case DW_ATE_HP_floathpintel: + return "DW_ATE_HP_floathpintel"; + case DW_ATE_HP_imaginary_float80: + return "DW_ATE_HP_imaginary_float80"; + case DW_ATE_HP_imaginary_float128: + return "DW_ATE_HP_imaginary_float128"; + default: + return "DW_ATE_"; + } +} + +/* Convert a DWARF call frame info operation to its string name. */ + +#if 0 +static char * +dwarf_cfi_name (unsigned cfi_opc) +{ + switch (cfi_opc) + { + case DW_CFA_advance_loc: + return "DW_CFA_advance_loc"; + case DW_CFA_offset: + return "DW_CFA_offset"; + case DW_CFA_restore: + return "DW_CFA_restore"; + case DW_CFA_nop: + return "DW_CFA_nop"; + case DW_CFA_set_loc: + return "DW_CFA_set_loc"; + case DW_CFA_advance_loc1: + return "DW_CFA_advance_loc1"; + case DW_CFA_advance_loc2: + return "DW_CFA_advance_loc2"; + case DW_CFA_advance_loc4: + return "DW_CFA_advance_loc4"; + case DW_CFA_offset_extended: + return "DW_CFA_offset_extended"; + case DW_CFA_restore_extended: + return "DW_CFA_restore_extended"; + case DW_CFA_undefined: + return "DW_CFA_undefined"; + case DW_CFA_same_value: + return "DW_CFA_same_value"; + case DW_CFA_register: + return "DW_CFA_register"; + case DW_CFA_remember_state: + return "DW_CFA_remember_state"; + case DW_CFA_restore_state: + return "DW_CFA_restore_state"; + case DW_CFA_def_cfa: + return "DW_CFA_def_cfa"; + case DW_CFA_def_cfa_register: + return "DW_CFA_def_cfa_register"; + case DW_CFA_def_cfa_offset: + return "DW_CFA_def_cfa_offset"; + /* DWARF 3. */ + case DW_CFA_def_cfa_expression: + return "DW_CFA_def_cfa_expression"; + case DW_CFA_expression: + return "DW_CFA_expression"; + case DW_CFA_offset_extended_sf: + return "DW_CFA_offset_extended_sf"; + case DW_CFA_def_cfa_sf: + return "DW_CFA_def_cfa_sf"; + case DW_CFA_def_cfa_offset_sf: + return "DW_CFA_def_cfa_offset_sf"; + case DW_CFA_val_offset: + return "DW_CFA_val_offset"; + case DW_CFA_val_offset_sf: + return "DW_CFA_val_offset_sf"; + case DW_CFA_val_expression: + return "DW_CFA_val_expression"; + /* SGI/MIPS specific. */ + case DW_CFA_MIPS_advance_loc8: + return "DW_CFA_MIPS_advance_loc8"; + /* GNU extensions. */ + case DW_CFA_GNU_window_save: + return "DW_CFA_GNU_window_save"; + case DW_CFA_GNU_args_size: + return "DW_CFA_GNU_args_size"; + case DW_CFA_GNU_negative_offset_extended: + return "DW_CFA_GNU_negative_offset_extended"; + default: + return "DW_CFA_"; + } +} +#endif + +static void +dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) +{ + unsigned int i; + + print_spaces (indent, f); + fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n", + dwarf_tag_name (die->tag), die->abbrev, die->offset); + + if (die->parent != NULL) + { + print_spaces (indent, f); + fprintf_unfiltered (f, " parent at offset: 0x%x\n", + die->parent->offset); + } + + print_spaces (indent, f); + fprintf_unfiltered (f, " has children: %s\n", + dwarf_bool_name (die->child != NULL)); + + print_spaces (indent, f); + fprintf_unfiltered (f, " attributes:\n"); + + for (i = 0; i < die->num_attrs; ++i) + { + print_spaces (indent, f); + fprintf_unfiltered (f, " %s (%s) ", + dwarf_attr_name (die->attrs[i].name), + dwarf_form_name (die->attrs[i].form)); + + switch (die->attrs[i].form) + { + case DW_FORM_ref_addr: + case DW_FORM_addr: + fprintf_unfiltered (f, "address: "); + fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f); + break; + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + case DW_FORM_block1: + fprintf_unfiltered (f, "block: size %d", + DW_BLOCK (&die->attrs[i])->size); + break; + case DW_FORM_exprloc: + fprintf_unfiltered (f, "expression: size %u", + DW_BLOCK (&die->attrs[i])->size); + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)", + (long) (DW_ADDR (&die->attrs[i]))); + break; + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_udata: + case DW_FORM_sdata: + fprintf_unfiltered (f, "constant: %s", + pulongest (DW_UNSND (&die->attrs[i]))); + break; + case DW_FORM_sec_offset: + fprintf_unfiltered (f, "section offset: %s", + pulongest (DW_UNSND (&die->attrs[i]))); + break; + case DW_FORM_ref_sig8: + if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL) + fprintf_unfiltered (f, "signatured type, offset: 0x%x", + DW_SIGNATURED_TYPE (&die->attrs[i])->offset); + else + fprintf_unfiltered (f, "signatured type, offset: unknown"); + break; + case DW_FORM_string: + case DW_FORM_strp: + fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)", + DW_STRING (&die->attrs[i]) + ? DW_STRING (&die->attrs[i]) : "", + DW_STRING_IS_CANONICAL (&die->attrs[i]) ? "is" : "not"); + break; + case DW_FORM_flag: + if (DW_UNSND (&die->attrs[i])) + fprintf_unfiltered (f, "flag: TRUE"); + else + fprintf_unfiltered (f, "flag: FALSE"); + break; + case DW_FORM_flag_present: + fprintf_unfiltered (f, "flag: TRUE"); + break; + case DW_FORM_indirect: + /* The reader will have reduced the indirect form to + the "base form" so this form should not occur. */ + fprintf_unfiltered (f, + "unexpected attribute form: DW_FORM_indirect"); + break; + default: + fprintf_unfiltered (f, "unsupported attribute form: %d.", + die->attrs[i].form); + break; + } + fprintf_unfiltered (f, "\n"); + } +} + +static void +dump_die_for_error (struct die_info *die) +{ + dump_die_shallow (gdb_stderr, 0, die); +} + +static void +dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) +{ + int indent = level * 4; + + gdb_assert (die != NULL); + + if (level >= max_level) + return; + + dump_die_shallow (f, indent, die); + + if (die->child != NULL) + { + print_spaces (indent, f); + fprintf_unfiltered (f, " Children:"); + if (level + 1 < max_level) + { + fprintf_unfiltered (f, "\n"); + dump_die_1 (f, level + 1, max_level, die->child); + } + else + { + fprintf_unfiltered (f, + " [not printed, max nesting level reached]\n"); + } + } + + if (die->sibling != NULL && level > 0) + { + dump_die_1 (f, level, max_level, die->sibling); + } +} + +/* This is called from the pdie macro in gdbinit.in. + It's not static so gcc will keep a copy callable from gdb. */ + +void +dump_die (struct die_info *die, int max_level) +{ + dump_die_1 (gdb_stdlog, 0, max_level, die); +} + +static void +store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu) +{ + void **slot; + + slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset, INSERT); + + *slot = die; +} + +static int +is_ref_attr (struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + return 1; default: - return def ? "OP_" : NULL; + return 0; + } +} + +static unsigned int +dwarf2_get_ref_die_offset (struct attribute *attr) +{ + if (is_ref_attr (attr)) + return DW_ADDR (attr); + + complaint (&symfile_complaints, + _("unsupported die ref attribute form: '%s'"), + dwarf_form_name (attr->form)); + return 0; +} + +/* Return the constant value held by ATTR. Return DEFAULT_VALUE if + * the value held by the attribute is not constant. */ + +static LONGEST +dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) +{ + if (attr->form == DW_FORM_sdata) + return DW_SND (attr); + else if (attr->form == DW_FORM_udata + || attr->form == DW_FORM_data1 + || attr->form == DW_FORM_data2 + || attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + return DW_UNSND (attr); + else + { + complaint (&symfile_complaints, + _("Attribute value is not a constant (%s)"), + dwarf_form_name (attr->form)); + return default_value; + } +} + +/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation + unit and add it to our queue. + The result is non-zero if PER_CU was queued, otherwise the result is zero + meaning either PER_CU is already queued or it is already loaded. */ + +static int +maybe_queue_comp_unit (struct dwarf2_cu *this_cu, + struct dwarf2_per_cu_data *per_cu) +{ + /* We may arrive here during partial symbol reading, if we need full + DIEs to process an unusual case (e.g. template arguments). Do + not queue PER_CU, just tell our caller to load its DIEs. */ + if (dwarf2_per_objfile->reading_partial_symbols) + { + if (per_cu->cu == NULL || per_cu->cu->dies == NULL) + return 1; + return 0; + } + + /* Mark the dependence relation so that we don't flush PER_CU + too early. */ + dwarf2_add_dependence (this_cu, per_cu); + + /* If it's already on the queue, we have nothing to do. */ + if (per_cu->queued) + return 0; + + /* If the compilation unit is already loaded, just mark it as + used. */ + if (per_cu->cu != NULL) + { + per_cu->cu->last_used = 0; + return 0; + } + + /* Add it to the queue. */ + queue_comp_unit (per_cu, this_cu->objfile); + + return 1; +} + +/* Follow reference or signature attribute ATTR of SRC_DIE. + On entry *REF_CU is the CU of SRC_DIE. + On exit *REF_CU is the CU of the result. */ + +static struct die_info * +follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr, + struct dwarf2_cu **ref_cu) +{ + struct die_info *die; + + if (is_ref_attr (attr)) + die = follow_die_ref (src_die, attr, ref_cu); + else if (attr->form == DW_FORM_ref_sig8) + die = follow_die_sig (src_die, attr, ref_cu); + else + { + dump_die_for_error (src_die); + error (_("Dwarf Error: Expected reference attribute [in module %s]"), + (*ref_cu)->objfile->name); + } + + return die; +} + +/* Follow reference OFFSET. + On entry *REF_CU is the CU of the source die referencing OFFSET. + On exit *REF_CU is the CU of the result. + Returns NULL if OFFSET is invalid. */ + +static struct die_info * +follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu) +{ + struct die_info temp_die; + struct dwarf2_cu *target_cu, *cu = *ref_cu; + + gdb_assert (cu->per_cu != NULL); + + target_cu = cu; + + if (cu->per_cu->from_debug_types) + { + /* .debug_types CUs cannot reference anything outside their CU. + If they need to, they have to reference a signatured type via + DW_FORM_ref_sig8. */ + if (! offset_in_cu_p (&cu->header, offset)) + return NULL; + } + else if (! offset_in_cu_p (&cu->header, offset)) + { + struct dwarf2_per_cu_data *per_cu; + + per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); + + /* If necessary, add it to the queue and load its DIEs. */ + if (maybe_queue_comp_unit (cu, per_cu)) + load_full_comp_unit (per_cu, cu->objfile); + + target_cu = per_cu->cu; } + else if (cu->dies == NULL) + { + /* We're loading full DIEs during partial symbol reading. */ + gdb_assert (dwarf2_per_objfile->reading_partial_symbols); + load_full_comp_unit (cu->per_cu, cu->objfile); + } + + *ref_cu = target_cu; + temp_die.offset = offset; + return htab_find_with_hash (target_cu->die_hash, &temp_die, offset); } -static char * -dwarf_bool_name (unsigned mybool) +/* Follow reference attribute ATTR of SRC_DIE. + On entry *REF_CU is the CU of SRC_DIE. + On exit *REF_CU is the CU of the result. */ + +static struct die_info * +follow_die_ref (struct die_info *src_die, struct attribute *attr, + struct dwarf2_cu **ref_cu) { - if (mybool) - return "TRUE"; - else - return "FALSE"; + unsigned int offset = dwarf2_get_ref_die_offset (attr); + struct dwarf2_cu *cu = *ref_cu; + struct die_info *die; + + die = follow_die_offset (offset, ref_cu); + if (!die) + error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE " + "at 0x%x [in module %s]"), + offset, src_die->offset, cu->objfile->name); + + return die; } -/* Convert a DWARF type code into its string name. */ +/* Return DWARF block and its CU referenced by OFFSET at PER_CU. Returned + value is intended for DW_OP_call*. */ -static char * -dwarf_type_encoding_name (unsigned enc) +struct dwarf2_locexpr_baton +dwarf2_fetch_die_location_block (unsigned int offset, + struct dwarf2_per_cu_data *per_cu, + CORE_ADDR (*get_frame_pc) (void *baton), + void *baton) { - switch (enc) + struct dwarf2_cu *cu = per_cu->cu; + struct die_info *die; + struct attribute *attr; + struct dwarf2_locexpr_baton retval; + + dw2_setup (per_cu->objfile); + + die = follow_die_offset (offset, &cu); + if (!die) + error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"), + offset, per_cu->cu->objfile->name); + + attr = dwarf2_attr (die, DW_AT_location, cu); + if (!attr) { - case DW_ATE_void: - return "DW_ATE_void"; - case DW_ATE_address: - return "DW_ATE_address"; - case DW_ATE_boolean: - return "DW_ATE_boolean"; - case DW_ATE_complex_float: - return "DW_ATE_complex_float"; - case DW_ATE_float: - return "DW_ATE_float"; - case DW_ATE_signed: - return "DW_ATE_signed"; - case DW_ATE_signed_char: - return "DW_ATE_signed_char"; - case DW_ATE_unsigned: - return "DW_ATE_unsigned"; - case DW_ATE_unsigned_char: - return "DW_ATE_unsigned_char"; - /* DWARF 3. */ - case DW_ATE_imaginary_float: - return "DW_ATE_imaginary_float"; - case DW_ATE_packed_decimal: - return "DW_ATE_packed_decimal"; - case DW_ATE_numeric_string: - return "DW_ATE_numeric_string"; - case DW_ATE_edited: - return "DW_ATE_edited"; - case DW_ATE_signed_fixed: - return "DW_ATE_signed_fixed"; - case DW_ATE_unsigned_fixed: - return "DW_ATE_unsigned_fixed"; - case DW_ATE_decimal_float: - return "DW_ATE_decimal_float"; - /* DWARF 4. */ - case DW_ATE_UTF: - return "DW_ATE_UTF"; - /* HP extensions. */ - case DW_ATE_HP_float80: - return "DW_ATE_HP_float80"; - case DW_ATE_HP_complex_float80: - return "DW_ATE_HP_complex_float80"; - case DW_ATE_HP_float128: - return "DW_ATE_HP_float128"; - case DW_ATE_HP_complex_float128: - return "DW_ATE_HP_complex_float128"; - case DW_ATE_HP_floathpintel: - return "DW_ATE_HP_floathpintel"; - case DW_ATE_HP_imaginary_float80: - return "DW_ATE_HP_imaginary_float80"; - case DW_ATE_HP_imaginary_float128: - return "DW_ATE_HP_imaginary_float128"; - default: - return "DW_ATE_"; + /* DWARF: "If there is no such attribute, then there is no effect.". */ + + retval.data = NULL; + retval.size = 0; + } + else if (attr_form_is_section_offset (attr)) + { + struct dwarf2_loclist_baton loclist_baton; + CORE_ADDR pc = (*get_frame_pc) (baton); + size_t size; + + fill_in_loclist_baton (cu, &loclist_baton, attr); + + retval.data = dwarf2_find_location_expression (&loclist_baton, + &size, pc); + retval.size = size; + } + else + { + if (!attr_form_is_block (attr)) + error (_("Dwarf Error: DIE at 0x%x referenced in module %s " + "is neither DW_FORM_block* nor DW_FORM_exprloc"), + offset, per_cu->cu->objfile->name); + + retval.data = DW_BLOCK (attr)->data; + retval.size = DW_BLOCK (attr)->size; } + retval.per_cu = cu->per_cu; + return retval; } -/* Convert a DWARF call frame info operation to its string name. */ +/* Follow the signature attribute ATTR in SRC_DIE. + On entry *REF_CU is the CU of SRC_DIE. + On exit *REF_CU is the CU of the result. */ -#if 0 -static char * -dwarf_cfi_name (unsigned cfi_opc) +static struct die_info * +follow_die_sig (struct die_info *src_die, struct attribute *attr, + struct dwarf2_cu **ref_cu) { - switch (cfi_opc) + struct objfile *objfile = (*ref_cu)->objfile; + struct die_info temp_die; + struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr); + struct dwarf2_cu *sig_cu; + struct die_info *die; + + /* sig_type will be NULL if the signatured type is missing from + the debug info. */ + if (sig_type == NULL) + error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE " + "at 0x%x [in module %s]"), + src_die->offset, objfile->name); + + /* If necessary, add it to the queue and load its DIEs. */ + + if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu)) + read_signatured_type (objfile, sig_type); + + gdb_assert (sig_type->per_cu.cu != NULL); + + sig_cu = sig_type->per_cu.cu; + temp_die.offset = sig_cu->header.offset + sig_type->type_offset; + die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset); + if (die) { - case DW_CFA_advance_loc: - return "DW_CFA_advance_loc"; - case DW_CFA_offset: - return "DW_CFA_offset"; - case DW_CFA_restore: - return "DW_CFA_restore"; - case DW_CFA_nop: - return "DW_CFA_nop"; - case DW_CFA_set_loc: - return "DW_CFA_set_loc"; - case DW_CFA_advance_loc1: - return "DW_CFA_advance_loc1"; - case DW_CFA_advance_loc2: - return "DW_CFA_advance_loc2"; - case DW_CFA_advance_loc4: - return "DW_CFA_advance_loc4"; - case DW_CFA_offset_extended: - return "DW_CFA_offset_extended"; - case DW_CFA_restore_extended: - return "DW_CFA_restore_extended"; - case DW_CFA_undefined: - return "DW_CFA_undefined"; - case DW_CFA_same_value: - return "DW_CFA_same_value"; - case DW_CFA_register: - return "DW_CFA_register"; - case DW_CFA_remember_state: - return "DW_CFA_remember_state"; - case DW_CFA_restore_state: - return "DW_CFA_restore_state"; - case DW_CFA_def_cfa: - return "DW_CFA_def_cfa"; - case DW_CFA_def_cfa_register: - return "DW_CFA_def_cfa_register"; - case DW_CFA_def_cfa_offset: - return "DW_CFA_def_cfa_offset"; - /* DWARF 3. */ - case DW_CFA_def_cfa_expression: - return "DW_CFA_def_cfa_expression"; - case DW_CFA_expression: - return "DW_CFA_expression"; - case DW_CFA_offset_extended_sf: - return "DW_CFA_offset_extended_sf"; - case DW_CFA_def_cfa_sf: - return "DW_CFA_def_cfa_sf"; - case DW_CFA_def_cfa_offset_sf: - return "DW_CFA_def_cfa_offset_sf"; - case DW_CFA_val_offset: - return "DW_CFA_val_offset"; - case DW_CFA_val_offset_sf: - return "DW_CFA_val_offset_sf"; - case DW_CFA_val_expression: - return "DW_CFA_val_expression"; - /* SGI/MIPS specific. */ - case DW_CFA_MIPS_advance_loc8: - return "DW_CFA_MIPS_advance_loc8"; - /* GNU extensions. */ - case DW_CFA_GNU_window_save: - return "DW_CFA_GNU_window_save"; - case DW_CFA_GNU_args_size: - return "DW_CFA_GNU_args_size"; - case DW_CFA_GNU_negative_offset_extended: - return "DW_CFA_GNU_negative_offset_extended"; - default: - return "DW_CFA_"; + *ref_cu = sig_cu; + return die; } + + error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced " + "from DIE at 0x%x [in module %s]"), + sig_type->type_offset, src_die->offset, objfile->name); +} + +/* Given an offset of a signatured type, return its signatured_type. */ + +static struct signatured_type * +lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) +{ + gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset; + unsigned int length, initial_length_size; + unsigned int sig_offset; + struct signatured_type find_entry, *type_sig; + + length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size); + sig_offset = (initial_length_size + + 2 /*version*/ + + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/ + + 1 /*address_size*/); + find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset); + type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + + /* This is only used to lookup previously recorded types. + If we didn't find it, it's our bug. */ + gdb_assert (type_sig != NULL); + gdb_assert (offset == type_sig->offset); + + return type_sig; } -#endif + +/* Read in signatured type at OFFSET and build its CU and die(s). */ static void -dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) +read_signatured_type_at_offset (struct objfile *objfile, + unsigned int offset) { - unsigned int i; - - print_spaces (indent, f); - fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n", - dwarf_tag_name (die->tag), die->abbrev, die->offset); + struct signatured_type *type_sig; - if (die->parent != NULL) - { - print_spaces (indent, f); - fprintf_unfiltered (f, " parent at offset: 0x%x\n", - die->parent->offset); - } + dwarf2_read_section (objfile, &dwarf2_per_objfile->types); - print_spaces (indent, f); - fprintf_unfiltered (f, " has children: %s\n", - dwarf_bool_name (die->child != NULL)); + /* We have the section offset, but we need the signature to do the + hash table lookup. */ + type_sig = lookup_signatured_type_at_offset (objfile, offset); - print_spaces (indent, f); - fprintf_unfiltered (f, " attributes:\n"); + gdb_assert (type_sig->per_cu.cu == NULL); - for (i = 0; i < die->num_attrs; ++i) - { - print_spaces (indent, f); - fprintf_unfiltered (f, " %s (%s) ", - dwarf_attr_name (die->attrs[i].name), - dwarf_form_name (die->attrs[i].form)); + read_signatured_type (objfile, type_sig); - switch (die->attrs[i].form) - { - case DW_FORM_ref_addr: - case DW_FORM_addr: - fprintf_unfiltered (f, "address: "); - fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f); - break; - case DW_FORM_block2: - case DW_FORM_block4: - case DW_FORM_block: - case DW_FORM_block1: - fprintf_unfiltered (f, "block: size %d", DW_BLOCK (&die->attrs[i])->size); - break; - case DW_FORM_exprloc: - fprintf_unfiltered (f, "expression: size %u", - DW_BLOCK (&die->attrs[i])->size); - break; - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)", - (long) (DW_ADDR (&die->attrs[i]))); - break; - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_data8: - case DW_FORM_udata: - case DW_FORM_sdata: - fprintf_unfiltered (f, "constant: %s", - pulongest (DW_UNSND (&die->attrs[i]))); - break; - case DW_FORM_sec_offset: - fprintf_unfiltered (f, "section offset: %s", - pulongest (DW_UNSND (&die->attrs[i]))); - break; - case DW_FORM_sig8: - if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL) - fprintf_unfiltered (f, "signatured type, offset: 0x%x", - DW_SIGNATURED_TYPE (&die->attrs[i])->offset); - else - fprintf_unfiltered (f, "signatured type, offset: unknown"); - break; - case DW_FORM_string: - case DW_FORM_strp: - fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)", - DW_STRING (&die->attrs[i]) - ? DW_STRING (&die->attrs[i]) : "", - DW_STRING_IS_CANONICAL (&die->attrs[i]) ? "is" : "not"); - break; - case DW_FORM_flag: - if (DW_UNSND (&die->attrs[i])) - fprintf_unfiltered (f, "flag: TRUE"); - else - fprintf_unfiltered (f, "flag: FALSE"); - break; - case DW_FORM_flag_present: - fprintf_unfiltered (f, "flag: TRUE"); - break; - case DW_FORM_indirect: - /* the reader will have reduced the indirect form to - the "base form" so this form should not occur */ - fprintf_unfiltered (f, "unexpected attribute form: DW_FORM_indirect"); - break; - default: - fprintf_unfiltered (f, "unsupported attribute form: %d.", - die->attrs[i].form); - break; - } - fprintf_unfiltered (f, "\n"); - } + gdb_assert (type_sig->per_cu.cu != NULL); } -static void -dump_die_for_error (struct die_info *die) -{ - dump_die_shallow (gdb_stderr, 0, die); -} +/* Read in a signatured type and build its CU and DIEs. */ static void -dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) +read_signatured_type (struct objfile *objfile, + struct signatured_type *type_sig) { - int indent = level * 4; + gdb_byte *types_ptr; + struct die_reader_specs reader_specs; + struct dwarf2_cu *cu; + ULONGEST signature; + struct cleanup *back_to, *free_cu_cleanup; - gdb_assert (die != NULL); + dwarf2_read_section (objfile, &dwarf2_per_objfile->types); + types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset; - if (level >= max_level) - return; + gdb_assert (type_sig->per_cu.cu == NULL); - dump_die_shallow (f, indent, die); + cu = xmalloc (sizeof (*cu)); + init_one_comp_unit (cu, objfile); - if (die->child != NULL) - { - print_spaces (indent, f); - fprintf_unfiltered (f, " Children:"); - if (level + 1 < max_level) - { - fprintf_unfiltered (f, "\n"); - dump_die_1 (f, level + 1, max_level, die->child); - } - else - { - fprintf_unfiltered (f, " [not printed, max nesting level reached]\n"); - } - } + type_sig->per_cu.cu = cu; + cu->per_cu = &type_sig->per_cu; - if (die->sibling != NULL && level > 0) - { - dump_die_1 (f, level, max_level, die->sibling); - } + /* If an error occurs while loading, release our storage. */ + free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); + + types_ptr = read_type_comp_unit_head (&cu->header, &signature, + types_ptr, objfile->obfd); + gdb_assert (signature == type_sig->signature); + + cu->die_hash + = htab_create_alloc_ex (cu->header.length / 12, + die_hash, + die_eq, + NULL, + &cu->comp_unit_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + + dwarf2_read_abbrevs (cu->objfile->obfd, cu); + back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + + init_cu_die_reader (&reader_specs, cu); + + cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr, + NULL /*parent*/); + + /* We try not to read any attributes in this function, because not + all objfiles needed for references have been loaded yet, and symbol + table processing isn't initialized. But we have to set the CU language, + or we won't be able to build types correctly. */ + prepare_one_comp_unit (cu, cu->dies); + + do_cleanups (back_to); + + /* We've successfully allocated this compilation unit. Let our caller + clean it up when finished with it. */ + discard_cleanups (free_cu_cleanup); + + type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain; + dwarf2_per_objfile->read_in_chain = &type_sig->per_cu; } -/* This is called from the pdie macro in gdbinit.in. - It's not static so gcc will keep a copy callable from gdb. */ +/* Decode simple location descriptions. + Given a pointer to a dwarf block that defines a location, compute + the location and return the value. + + NOTE drow/2003-11-18: This function is called in two situations + now: for the address of static or global variables (partial symbols + only) and for offsets into structures which are expected to be + (more or less) constant. The partial symbol case should go away, + and only the constant case should remain. That will let this + function complain more accurately. A few special modes are allowed + without complaint for global variables (for instance, global + register values and thread-local values). + + A location description containing no operations indicates that the + object is optimized out. The return value is 0 for that case. + FIXME drow/2003-11-16: No callers check for this case any more; soon all + callers will only want a very basic result and this can become a + complaint. + + Note that stack[0] is unused except as a default error return. */ + +static CORE_ADDR +decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + int i; + int size = blk->size; + gdb_byte *data = blk->data; + CORE_ADDR stack[64]; + int stacki; + unsigned int bytes_read, unsnd; + gdb_byte op; + + i = 0; + stacki = 0; + stack[stacki] = 0; + stack[++stacki] = 0; + + while (i < size) + { + op = data[i++]; + switch (op) + { + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + stack[++stacki] = op - DW_OP_lit0; + break; -void -dump_die (struct die_info *die, int max_level) -{ - dump_die_1 (gdb_stdlog, 0, max_level, die); -} + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + stack[++stacki] = op - DW_OP_reg0; + if (i < size) + dwarf2_complex_location_expr_complaint (); + break; -static void -store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu) -{ - void **slot; + case DW_OP_regx: + unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + stack[++stacki] = unsnd; + if (i < size) + dwarf2_complex_location_expr_complaint (); + break; - slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset, INSERT); + case DW_OP_addr: + stack[++stacki] = read_address (objfile->obfd, &data[i], + cu, &bytes_read); + i += bytes_read; + break; - *slot = die; -} + case DW_OP_const1u: + stack[++stacki] = read_1_byte (objfile->obfd, &data[i]); + i += 1; + break; -static int -is_ref_attr (struct attribute *attr) -{ - switch (attr->form) - { - case DW_FORM_ref_addr: - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - return 1; - default: - return 0; - } -} + case DW_OP_const1s: + stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]); + i += 1; + break; -static unsigned int -dwarf2_get_ref_die_offset (struct attribute *attr) -{ - if (is_ref_attr (attr)) - return DW_ADDR (attr); + case DW_OP_const2u: + stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]); + i += 2; + break; - complaint (&symfile_complaints, - _("unsupported die ref attribute form: '%s'"), - dwarf_form_name (attr->form)); - return 0; -} + case DW_OP_const2s: + stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]); + i += 2; + break; -/* Return the constant value held by ATTR. Return DEFAULT_VALUE if - * the value held by the attribute is not constant. */ + case DW_OP_const4u: + stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]); + i += 4; + break; -static LONGEST -dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) -{ - if (attr->form == DW_FORM_sdata) - return DW_SND (attr); - else if (attr->form == DW_FORM_udata - || attr->form == DW_FORM_data1 - || attr->form == DW_FORM_data2 - || attr->form == DW_FORM_data4 - || attr->form == DW_FORM_data8) - return DW_UNSND (attr); - else - { - complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), - dwarf_form_name (attr->form)); - return default_value; - } -} + case DW_OP_const4s: + stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]); + i += 4; + break; -/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation - unit and add it to our queue. - The result is non-zero if PER_CU was queued, otherwise the result is zero - meaning either PER_CU is already queued or it is already loaded. */ + case DW_OP_constu: + stack[++stacki] = read_unsigned_leb128 (NULL, (data + i), + &bytes_read); + i += bytes_read; + break; -static int -maybe_queue_comp_unit (struct dwarf2_cu *this_cu, - struct dwarf2_per_cu_data *per_cu) -{ - /* Mark the dependence relation so that we don't flush PER_CU - too early. */ - dwarf2_add_dependence (this_cu, per_cu); + case DW_OP_consts: + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; - /* If it's already on the queue, we have nothing to do. */ - if (per_cu->queued) - return 0; + case DW_OP_dup: + stack[stacki + 1] = stack[stacki]; + stacki++; + break; - /* If the compilation unit is already loaded, just mark it as - used. */ - if (per_cu->cu != NULL) - { - per_cu->cu->last_used = 0; - return 0; - } + case DW_OP_plus: + stack[stacki - 1] += stack[stacki]; + stacki--; + break; - /* Add it to the queue. */ - queue_comp_unit (per_cu, this_cu->objfile); + case DW_OP_plus_uconst: + stack[stacki] += read_unsigned_leb128 (NULL, (data + i), + &bytes_read); + i += bytes_read; + break; - return 1; -} + case DW_OP_minus: + stack[stacki - 1] -= stack[stacki]; + stacki--; + break; -/* Follow reference or signature attribute ATTR of SRC_DIE. - On entry *REF_CU is the CU of SRC_DIE. - On exit *REF_CU is the CU of the result. */ + case DW_OP_deref: + /* If we're not the last op, then we definitely can't encode + this using GDB's address_class enum. This is valid for partial + global symbols, although the variable's address will be bogus + in the psymtab. */ + if (i < size) + dwarf2_complex_location_expr_complaint (); + break; -static struct die_info * -follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr, - struct dwarf2_cu **ref_cu) -{ - struct die_info *die; + case DW_OP_GNU_push_tls_address: + /* The top of the stack has the offset from the beginning + of the thread control block at which the variable is located. */ + /* Nothing should follow this operator, so the top of stack would + be returned. */ + /* This is valid for partial global symbols, but the variable's + address will be bogus in the psymtab. */ + if (i < size) + dwarf2_complex_location_expr_complaint (); + break; - if (is_ref_attr (attr)) - die = follow_die_ref (src_die, attr, ref_cu); - else if (attr->form == DW_FORM_sig8) - die = follow_die_sig (src_die, attr, ref_cu); - else - { - dump_die_for_error (src_die); - error (_("Dwarf Error: Expected reference attribute [in module %s]"), - (*ref_cu)->objfile->name); - } + case DW_OP_GNU_uninit: + break; - return die; -} + default: + { + const char *name = dwarf_stack_op_name (op); -/* Follow reference OFFSET. - On entry *REF_CU is the CU of source DIE referencing OFFSET. - On exit *REF_CU is the CU of the result. */ + if (name) + complaint (&symfile_complaints, _("unsupported stack op: '%s'"), + name); + else + complaint (&symfile_complaints, _("unsupported stack op: '%02x'"), + op); + } -static struct die_info * -follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu) -{ - struct die_info temp_die; - struct dwarf2_cu *target_cu, *cu = *ref_cu; + return (stack[stacki]); + } - gdb_assert (cu->per_cu != NULL); + /* Enforce maximum stack depth of SIZE-1 to avoid writing + outside of the allocated space. Also enforce minimum>0. */ + if (stacki >= ARRAY_SIZE (stack) - 1) + { + complaint (&symfile_complaints, + _("location description stack overflow")); + return 0; + } - if (cu->per_cu->from_debug_types) - { - /* .debug_types CUs cannot reference anything outside their CU. - If they need to, they have to reference a signatured type via - DW_FORM_sig8. */ - if (! offset_in_cu_p (&cu->header, offset)) - return NULL; - target_cu = cu; + if (stacki <= 0) + { + complaint (&symfile_complaints, + _("location description stack underflow")); + return 0; + } } - else if (! offset_in_cu_p (&cu->header, offset)) - { - struct dwarf2_per_cu_data *per_cu; - - per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); + return (stack[stacki]); +} - /* If necessary, add it to the queue and load its DIEs. */ - if (maybe_queue_comp_unit (cu, per_cu)) - load_full_comp_unit (per_cu, cu->objfile); +/* memory allocation interface */ - target_cu = per_cu->cu; - } - else - target_cu = cu; +static struct dwarf_block * +dwarf_alloc_block (struct dwarf2_cu *cu) +{ + struct dwarf_block *blk; - *ref_cu = target_cu; - temp_die.offset = offset; - return htab_find_with_hash (target_cu->die_hash, &temp_die, offset); + blk = (struct dwarf_block *) + obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block)); + return (blk); } -/* Follow reference attribute ATTR of SRC_DIE. - On entry *REF_CU is the CU of SRC_DIE. - On exit *REF_CU is the CU of the result. */ +static struct abbrev_info * +dwarf_alloc_abbrev (struct dwarf2_cu *cu) +{ + struct abbrev_info *abbrev; + + abbrev = (struct abbrev_info *) + obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info)); + memset (abbrev, 0, sizeof (struct abbrev_info)); + return (abbrev); +} static struct die_info * -follow_die_ref (struct die_info *src_die, struct attribute *attr, - struct dwarf2_cu **ref_cu) +dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs) { - unsigned int offset = dwarf2_get_ref_die_offset (attr); - struct dwarf2_cu *cu = *ref_cu; struct die_info *die; + size_t size = sizeof (struct die_info); - die = follow_die_offset (offset, ref_cu); - if (!die) - error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE " - "at 0x%x [in module %s]"), - offset, src_die->offset, cu->objfile->name); + if (num_attrs > 1) + size += (num_attrs - 1) * sizeof (struct attribute); - return die; + die = (struct die_info *) obstack_alloc (&cu->comp_unit_obstack, size); + memset (die, 0, sizeof (struct die_info)); + return (die); } -/* Return DWARF block and its CU referenced by OFFSET at PER_CU. Returned - value is intended for DW_OP_call*. */ + +/* Macro support. */ -struct dwarf2_locexpr_baton -dwarf2_fetch_die_location_block (unsigned int offset, - struct dwarf2_per_cu_data *per_cu) +/* Return the full name of file number I in *LH's file name table. + Use COMP_DIR as the name of the current directory of the + compilation. The result is allocated using xmalloc; the caller is + responsible for freeing it. */ +static char * +file_full_name (int file, struct line_header *lh, const char *comp_dir) { - struct dwarf2_cu *cu = per_cu->cu; - struct die_info *die; - struct attribute *attr; - struct dwarf2_locexpr_baton retval; + /* Is the file number a valid index into the line header's file name + table? Remember that file numbers start with one, not zero. */ + if (1 <= file && file <= lh->num_file_names) + { + struct file_entry *fe = &lh->file_names[file - 1]; - die = follow_die_offset (offset, &cu); - if (!die) - error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"), - offset, per_cu->cu->objfile->name); + if (IS_ABSOLUTE_PATH (fe->name)) + return xstrdup (fe->name); + else + { + const char *dir; + int dir_len; + char *full_name; - attr = dwarf2_attr (die, DW_AT_location, cu); - if (!attr) - { - /* DWARF: "If there is no such attribute, then there is no effect.". */ + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + else + dir = comp_dir; - retval.data = NULL; - retval.size = 0; + if (dir) + { + dir_len = strlen (dir); + full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1); + strcpy (full_name, dir); + full_name[dir_len] = '/'; + strcpy (full_name + dir_len + 1, fe->name); + return full_name; + } + else + return xstrdup (fe->name); + } } else { - if (!attr_form_is_block (attr)) - error (_("Dwarf Error: DIE at 0x%x referenced in module %s " - "is neither DW_FORM_block* nor DW_FORM_exprloc"), - offset, per_cu->cu->objfile->name); + /* The compiler produced a bogus file number. We can at least + record the macro definitions made in the file, even if we + won't be able to find the file by name. */ + char fake_name[80]; - retval.data = DW_BLOCK (attr)->data; - retval.size = DW_BLOCK (attr)->size; + sprintf (fake_name, "", file); + + complaint (&symfile_complaints, + _("bad file number in macro information (%d)"), + file); + + return xstrdup (fake_name); } - retval.per_cu = cu->per_cu; - return retval; } -/* Follow the signature attribute ATTR in SRC_DIE. - On entry *REF_CU is the CU of SRC_DIE. - On exit *REF_CU is the CU of the result. */ -static struct die_info * -follow_die_sig (struct die_info *src_die, struct attribute *attr, - struct dwarf2_cu **ref_cu) +static struct macro_source_file * +macro_start_file (int file, int line, + struct macro_source_file *current_file, + const char *comp_dir, + struct line_header *lh, struct objfile *objfile) { - struct objfile *objfile = (*ref_cu)->objfile; - struct die_info temp_die; - struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr); - struct dwarf2_cu *sig_cu; - struct die_info *die; + /* The full name of this source file. */ + char *full_name = file_full_name (file, lh, comp_dir); - /* sig_type will be NULL if the signatured type is missing from - the debug info. */ - if (sig_type == NULL) - error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE " - "at 0x%x [in module %s]"), - src_die->offset, objfile->name); + /* We don't create a macro table for this compilation unit + at all until we actually get a filename. */ + if (! pending_macros) + pending_macros = new_macro_table (&objfile->objfile_obstack, + objfile->macro_cache); - /* If necessary, add it to the queue and load its DIEs. */ + if (! current_file) + /* If we have no current file, then this must be the start_file + directive for the compilation unit's main source file. */ + current_file = macro_set_main (pending_macros, full_name); + else + current_file = macro_include (current_file, line, full_name); - if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu)) - read_signatured_type (objfile, sig_type); + xfree (full_name); - gdb_assert (sig_type->per_cu.cu != NULL); + return current_file; +} - sig_cu = sig_type->per_cu.cu; - temp_die.offset = sig_cu->header.offset + sig_type->type_offset; - die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset); - if (die) - { - *ref_cu = sig_cu; - return die; - } - error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE " - "at 0x%x [in module %s]"), - sig_type->type_offset, src_die->offset, objfile->name); +/* Copy the LEN characters at BUF to a xmalloc'ed block of memory, + followed by a null byte. */ +static char * +copy_string (const char *buf, int len) +{ + char *s = xmalloc (len + 1); + + memcpy (s, buf, len); + s[len] = '\0'; + return s; } -/* Given an offset of a signatured type, return its signatured_type. */ -static struct signatured_type * -lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) +static const char * +consume_improper_spaces (const char *p, const char *body) { - gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset; - unsigned int length, initial_length_size; - unsigned int sig_offset; - struct signatured_type find_entry, *type_sig; - - length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size); - sig_offset = (initial_length_size - + 2 /*version*/ - + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/ - + 1 /*address_size*/); - find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset); - type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + if (*p == ' ') + { + complaint (&symfile_complaints, + _("macro definition contains spaces " + "in formal argument list:\n`%s'"), + body); - /* This is only used to lookup previously recorded types. - If we didn't find it, it's our bug. */ - gdb_assert (type_sig != NULL); - gdb_assert (offset == type_sig->offset); + while (*p == ' ') + p++; + } - return type_sig; + return p; } -/* Read in signatured type at OFFSET and build its CU and die(s). */ static void -read_signatured_type_at_offset (struct objfile *objfile, - unsigned int offset) +parse_macro_definition (struct macro_source_file *file, int line, + const char *body) { - struct signatured_type *type_sig; + const char *p; + + /* The body string takes one of two forms. For object-like macro + definitions, it should be: + + " " + + For function-like macro definitions, it should be: + + "() " + or + "(" ( "," ) * ") " + + Spaces may appear only where explicitly indicated, and in the + . + + The Dwarf 2 spec says that an object-like macro's name is always + followed by a space, but versions of GCC around March 2002 omit + the space when the macro's definition is the empty string. + + The Dwarf 2 spec says that there should be no spaces between the + formal arguments in a function-like macro's formal argument list, + but versions of GCC around March 2002 include spaces after the + commas. */ + + + /* Find the extent of the macro name. The macro name is terminated + by either a space or null character (for an object-like macro) or + an opening paren (for a function-like macro). */ + for (p = body; *p; p++) + if (*p == ' ' || *p == '(') + break; + + if (*p == ' ' || *p == '\0') + { + /* It's an object-like macro. */ + int name_len = p - body; + char *name = copy_string (body, name_len); + const char *replacement; - dwarf2_read_section (objfile, &dwarf2_per_objfile->types); + if (*p == ' ') + replacement = body + name_len + 1; + else + { + dwarf2_macro_malformed_definition_complaint (body); + replacement = body + name_len; + } - /* We have the section offset, but we need the signature to do the - hash table lookup. */ - type_sig = lookup_signatured_type_at_offset (objfile, offset); + macro_define_object (file, line, name, replacement); - gdb_assert (type_sig->per_cu.cu == NULL); + xfree (name); + } + else if (*p == '(') + { + /* It's a function-like macro. */ + char *name = copy_string (body, p - body); + int argc = 0; + int argv_size = 1; + char **argv = xmalloc (argv_size * sizeof (*argv)); - read_signatured_type (objfile, type_sig); + p++; - gdb_assert (type_sig->per_cu.cu != NULL); -} + p = consume_improper_spaces (p, body); -/* Read in a signatured type and build its CU and DIEs. */ + /* Parse the formal argument list. */ + while (*p && *p != ')') + { + /* Find the extent of the current argument name. */ + const char *arg_start = p; -static void -read_signatured_type (struct objfile *objfile, - struct signatured_type *type_sig) -{ - gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset; - struct die_reader_specs reader_specs; - struct dwarf2_cu *cu; - ULONGEST signature; - struct cleanup *back_to, *free_cu_cleanup; - struct attribute *attr; + while (*p && *p != ',' && *p != ')' && *p != ' ') + p++; - gdb_assert (type_sig->per_cu.cu == NULL); + if (! *p || p == arg_start) + dwarf2_macro_malformed_definition_complaint (body); + else + { + /* Make sure argv has room for the new argument. */ + if (argc >= argv_size) + { + argv_size *= 2; + argv = xrealloc (argv, argv_size * sizeof (*argv)); + } - cu = xmalloc (sizeof (struct dwarf2_cu)); - memset (cu, 0, sizeof (struct dwarf2_cu)); - obstack_init (&cu->comp_unit_obstack); - cu->objfile = objfile; - type_sig->per_cu.cu = cu; - cu->per_cu = &type_sig->per_cu; + argv[argc++] = copy_string (arg_start, p - arg_start); + } - /* If an error occurs while loading, release our storage. */ - free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); + p = consume_improper_spaces (p, body); - types_ptr = read_type_comp_unit_head (&cu->header, &signature, - types_ptr, objfile->obfd); - gdb_assert (signature == type_sig->signature); + /* Consume the comma, if present. */ + if (*p == ',') + { + p++; - cu->die_hash - = htab_create_alloc_ex (cu->header.length / 12, - die_hash, - die_eq, - NULL, - &cu->comp_unit_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); + p = consume_improper_spaces (p, body); + } + } - dwarf2_read_abbrevs (cu->objfile->obfd, cu); - back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + if (*p == ')') + { + p++; - init_cu_die_reader (&reader_specs, cu); + if (*p == ' ') + /* Perfectly formed definition, no complaints. */ + macro_define_function (file, line, name, + argc, (const char **) argv, + p + 1); + else if (*p == '\0') + { + /* Complain, but do define it. */ + dwarf2_macro_malformed_definition_complaint (body); + macro_define_function (file, line, name, + argc, (const char **) argv, + p); + } + else + /* Just complain. */ + dwarf2_macro_malformed_definition_complaint (body); + } + else + /* Just complain. */ + dwarf2_macro_malformed_definition_complaint (body); - cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr, - NULL /*parent*/); + xfree (name); + { + int i; - /* We try not to read any attributes in this function, because not - all objfiles needed for references have been loaded yet, and symbol - table processing isn't initialized. But we have to set the CU language, - or we won't be able to build types correctly. */ - attr = dwarf2_attr (cu->dies, DW_AT_language, cu); - if (attr) - set_cu_language (DW_UNSND (attr), cu); + for (i = 0; i < argc; i++) + xfree (argv[i]); + } + xfree (argv); + } else - set_cu_language (language_minimal, cu); - - do_cleanups (back_to); - - /* We've successfully allocated this compilation unit. Let our caller - clean it up when finished with it. */ - discard_cleanups (free_cu_cleanup); - - type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain; - dwarf2_per_objfile->read_in_chain = &type_sig->per_cu; + dwarf2_macro_malformed_definition_complaint (body); } -/* Decode simple location descriptions. - Given a pointer to a dwarf block that defines a location, compute - the location and return the value. - - NOTE drow/2003-11-18: This function is called in two situations - now: for the address of static or global variables (partial symbols - only) and for offsets into structures which are expected to be - (more or less) constant. The partial symbol case should go away, - and only the constant case should remain. That will let this - function complain more accurately. A few special modes are allowed - without complaint for global variables (for instance, global - register values and thread-local values). - - A location description containing no operations indicates that the - object is optimized out. The return value is 0 for that case. - FIXME drow/2003-11-16: No callers check for this case any more; soon all - callers will only want a very basic result and this can become a - complaint. - - Note that stack[0] is unused except as a default error return. - Note that stack overflow is not yet handled. */ -static CORE_ADDR -decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) +static void +dwarf_decode_macros (struct line_header *lh, unsigned int offset, + char *comp_dir, bfd *abfd, + struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - int i; - int size = blk->size; - gdb_byte *data = blk->data; - CORE_ADDR stack[64]; - int stacki; - unsigned int bytes_read, unsnd; - gdb_byte op; - - i = 0; - stacki = 0; - stack[stacki] = 0; + gdb_byte *mac_ptr, *mac_end; + struct macro_source_file *current_file = 0; + enum dwarf_macinfo_record_type macinfo_type; + int at_commandline; - while (i < size) + dwarf2_read_section (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->macinfo); + if (dwarf2_per_objfile->macinfo.buffer == NULL) { - op = data[i++]; - switch (op) - { - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - stack[++stacki] = op - DW_OP_lit0; - break; + complaint (&symfile_complaints, _("missing .debug_macinfo section")); + return; + } - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - stack[++stacki] = op - DW_OP_reg0; - if (i < size) - dwarf2_complex_location_expr_complaint (); - break; + /* First pass: Find the name of the base filename. + This filename is needed in order to process all macros whose definition + (or undefinition) comes from the command line. These macros are defined + before the first DW_MACINFO_start_file entry, and yet still need to be + associated to the base file. - case DW_OP_regx: - unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read); - i += bytes_read; - stack[++stacki] = unsnd; - if (i < size) - dwarf2_complex_location_expr_complaint (); - break; + To determine the base file name, we scan the macro definitions until we + reach the first DW_MACINFO_start_file entry. We then initialize + CURRENT_FILE accordingly so that any macro definition found before the + first DW_MACINFO_start_file can still be associated to the base file. */ - case DW_OP_addr: - stack[++stacki] = read_address (objfile->obfd, &data[i], - cu, &bytes_read); - i += bytes_read; - break; + mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; + mac_end = dwarf2_per_objfile->macinfo.buffer + + dwarf2_per_objfile->macinfo.size; - case DW_OP_const1u: - stack[++stacki] = read_1_byte (objfile->obfd, &data[i]); - i += 1; + do + { + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + /* Complaint is printed during the second pass as GDB will probably + stop the first pass earlier upon finding + DW_MACINFO_start_file. */ break; + } - case DW_OP_const1s: - stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]); - i += 1; - break; + macinfo_type = read_1_byte (abfd, mac_ptr); + mac_ptr++; - case DW_OP_const2u: - stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]); - i += 2; + switch (macinfo_type) + { + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: break; - case DW_OP_const2s: - stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]); - i += 2; - break; + case DW_MACINFO_define: + case DW_MACINFO_undef: + /* Only skip the data by MAC_PTR. */ + { + unsigned int bytes_read; - case DW_OP_const4u: - stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]); - i += 4; + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } break; - case DW_OP_const4s: - stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]); - i += 4; - break; + case DW_MACINFO_start_file: + { + unsigned int bytes_read; + int line, file; - case DW_OP_constu: - stack[++stacki] = read_unsigned_leb128 (NULL, (data + i), - &bytes_read); - i += bytes_read; - break; + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; - case DW_OP_consts: - stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); - i += bytes_read; + current_file = macro_start_file (file, line, current_file, + comp_dir, lh, cu->objfile); + } break; - case DW_OP_dup: - stack[stacki + 1] = stack[stacki]; - stacki++; + case DW_MACINFO_end_file: + /* No data to skip by MAC_PTR. */ break; - case DW_OP_plus: - stack[stacki - 1] += stack[stacki]; - stacki--; + case DW_MACINFO_vendor_ext: + /* Only skip the data by MAC_PTR. */ + { + unsigned int bytes_read; + + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } break; - case DW_OP_plus_uconst: - stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read); - i += bytes_read; + default: break; + } + } while (macinfo_type != 0 && current_file == NULL); - case DW_OP_minus: - stack[stacki - 1] -= stack[stacki]; - stacki--; + /* Second pass: Process all entries. + + Use the AT_COMMAND_LINE flag to determine whether we are still processing + command-line macro definitions/undefinitions. This flag is unset when we + reach the first DW_MACINFO_start_file entry. */ + + mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; + + /* Determines if GDB is still before first DW_MACINFO_start_file. If true + GDB is still reading the definitions from command line. First + DW_MACINFO_start_file will need to be ignored as it was already executed + to create CURRENT_FILE for the main source holding also the command line + definitions. On first met DW_MACINFO_start_file this flag is reset to + normally execute all the remaining DW_MACINFO_start_file macinfos. */ + + at_commandline = 1; + + do + { + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + dwarf2_macros_too_long_complaint (); break; + } - case DW_OP_deref: - /* If we're not the last op, then we definitely can't encode - this using GDB's address_class enum. This is valid for partial - global symbols, although the variable's address will be bogus - in the psymtab. */ - if (i < size) - dwarf2_complex_location_expr_complaint (); + macinfo_type = read_1_byte (abfd, mac_ptr); + mac_ptr++; + + switch (macinfo_type) + { + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: break; - case DW_OP_GNU_push_tls_address: - /* The top of the stack has the offset from the beginning - of the thread control block at which the variable is located. */ - /* Nothing should follow this operator, so the top of stack would - be returned. */ - /* This is valid for partial global symbols, but the variable's - address will be bogus in the psymtab. */ - if (i < size) - dwarf2_complex_location_expr_complaint (); + case DW_MACINFO_define: + case DW_MACINFO_undef: + { + unsigned int bytes_read; + int line; + char *body; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + body = read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + if (! current_file) + { + /* DWARF violation as no main source is present. */ + complaint (&symfile_complaints, + _("debug info with no main source gives macro %s " + "on line %d: %s"), + macinfo_type == DW_MACINFO_define ? + _("definition") : + macinfo_type == DW_MACINFO_undef ? + _("undefinition") : + _("something-or-other"), line, body); + break; + } + if ((line == 0 && !at_commandline) + || (line != 0 && at_commandline)) + complaint (&symfile_complaints, + _("debug info gives %s macro %s with %s line %d: %s"), + at_commandline ? _("command-line") : _("in-file"), + macinfo_type == DW_MACINFO_define ? + _("definition") : + macinfo_type == DW_MACINFO_undef ? + _("undefinition") : + _("something-or-other"), + line == 0 ? _("zero") : _("non-zero"), line, body); + + if (macinfo_type == DW_MACINFO_define) + parse_macro_definition (current_file, line, body); + else if (macinfo_type == DW_MACINFO_undef) + macro_undef (current_file, line, body); + } + break; + + case DW_MACINFO_start_file: + { + unsigned int bytes_read; + int line, file; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + if ((line == 0 && !at_commandline) + || (line != 0 && at_commandline)) + complaint (&symfile_complaints, + _("debug info gives source %d included " + "from %s at %s line %d"), + file, at_commandline ? _("command-line") : _("file"), + line == 0 ? _("zero") : _("non-zero"), line); + + if (at_commandline) + { + /* This DW_MACINFO_start_file was executed in the pass one. */ + at_commandline = 0; + } + else + current_file = macro_start_file (file, line, + current_file, comp_dir, + lh, cu->objfile); + } + break; + + case DW_MACINFO_end_file: + if (! current_file) + complaint (&symfile_complaints, + _("macro debug info has an unmatched " + "`close_file' directive")); + else + { + current_file = current_file->included_by; + if (! current_file) + { + enum dwarf_macinfo_record_type next_type; + + /* GCC circa March 2002 doesn't produce the zero + type byte marking the end of the compilation + unit. Complain if it's not there, but exit no + matter what. */ + + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + dwarf2_macros_too_long_complaint (); + return; + } + + /* We don't increment mac_ptr here, so this is just + a look-ahead. */ + next_type = read_1_byte (abfd, mac_ptr); + if (next_type != 0) + complaint (&symfile_complaints, + _("no terminating 0-type entry for " + "macros in `.debug_macinfo' section")); + + return; + } + } break; - case DW_OP_GNU_uninit: - break; + case DW_MACINFO_vendor_ext: + { + unsigned int bytes_read; + int constant; - default: - complaint (&symfile_complaints, _("unsupported stack op: '%s'"), - dwarf_stack_op_name (op, 1)); - return (stack[stacki]); - } - } - return (stack[stacki]); -} + constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; -/* memory allocation interface */ + /* We don't recognize any vendor extensions. */ + } + break; + } + } while (macinfo_type != 0); +} -static struct dwarf_block * -dwarf_alloc_block (struct dwarf2_cu *cu) +/* Check if the attribute's form is a DW_FORM_block* + if so return true else false. */ +static int +attr_form_is_block (struct attribute *attr) { - struct dwarf_block *blk; - - blk = (struct dwarf_block *) - obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block)); - return (blk); + return (attr == NULL ? 0 : + attr->form == DW_FORM_block1 + || attr->form == DW_FORM_block2 + || attr->form == DW_FORM_block4 + || attr->form == DW_FORM_block + || attr->form == DW_FORM_exprloc); } -static struct abbrev_info * -dwarf_alloc_abbrev (struct dwarf2_cu *cu) -{ - struct abbrev_info *abbrev; +/* Return non-zero if ATTR's value is a section offset --- classes + lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise. + You may use DW_UNSND (attr) to retrieve such offsets. - abbrev = (struct abbrev_info *) - obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info)); - memset (abbrev, 0, sizeof (struct abbrev_info)); - return (abbrev); + Section 7.5.4, "Attribute Encodings", explains that no attribute + may have a value that belongs to more than one of these classes; it + would be ambiguous if we did, because we use the same forms for all + of them. */ +static int +attr_form_is_section_offset (struct attribute *attr) +{ + return (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8 + || attr->form == DW_FORM_sec_offset); } -static struct die_info * -dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs) -{ - struct die_info *die; - size_t size = sizeof (struct die_info); - if (num_attrs > 1) - size += (num_attrs - 1) * sizeof (struct attribute); +/* Return non-zero if ATTR's value falls in the 'constant' class, or + zero otherwise. When this function returns true, you can apply + dwarf2_get_attr_constant_value to it. - die = (struct die_info *) obstack_alloc (&cu->comp_unit_obstack, size); - memset (die, 0, sizeof (struct die_info)); - return (die); + However, note that for some attributes you must check + attr_form_is_section_offset before using this test. DW_FORM_data4 + and DW_FORM_data8 are members of both the constant class, and of + the classes that contain offsets into other debug sections + (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says + that, if an attribute's can be either a constant or one of the + section offset classes, DW_FORM_data4 and DW_FORM_data8 should be + taken as section offsets, not constants. */ +static int +attr_form_is_constant (struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + return 1; + default: + return 0; + } } - -/* Macro support. */ +/* A helper function that fills in a dwarf2_loclist_baton. */ +static void +fill_in_loclist_baton (struct dwarf2_cu *cu, + struct dwarf2_loclist_baton *baton, + struct attribute *attr) +{ + dwarf2_read_section (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->loc); -/* Return the full name of file number I in *LH's file name table. - Use COMP_DIR as the name of the current directory of the - compilation. The result is allocated using xmalloc; the caller is - responsible for freeing it. */ -static char * -file_full_name (int file, struct line_header *lh, const char *comp_dir) + baton->per_cu = cu->per_cu; + gdb_assert (baton->per_cu); + /* We don't know how long the location list is, but make sure we + don't run off the edge of the section. */ + baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr); + baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr); + baton->base_address = cu->base_address; +} + +static void +dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + struct dwarf2_cu *cu) { - /* Is the file number a valid index into the line header's file name - table? Remember that file numbers start with one, not zero. */ - if (1 <= file && file <= lh->num_file_names) + if (attr_form_is_section_offset (attr) + /* ".debug_loc" may not exist at all, or the offset may be outside + the section. If so, fall through to the complaint in the + other branch. */ + && DW_UNSND (attr) < dwarf2_section_size (dwarf2_per_objfile->objfile, + &dwarf2_per_objfile->loc)) { - struct file_entry *fe = &lh->file_names[file - 1]; + struct dwarf2_loclist_baton *baton; - if (IS_ABSOLUTE_PATH (fe->name)) - return xstrdup (fe->name); - else - { - const char *dir; - int dir_len; - char *full_name; + baton = obstack_alloc (&cu->objfile->objfile_obstack, + sizeof (struct dwarf2_loclist_baton)); - if (fe->dir_index) - dir = lh->include_dirs[fe->dir_index - 1]; - else - dir = comp_dir; + fill_in_loclist_baton (cu, baton, attr); - if (dir) - { - dir_len = strlen (dir); - full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1); - strcpy (full_name, dir); - full_name[dir_len] = '/'; - strcpy (full_name + dir_len + 1, fe->name); - return full_name; - } - else - return xstrdup (fe->name); - } + if (cu->base_known == 0) + complaint (&symfile_complaints, + _("Location list used without " + "specifying the CU base address.")); + + SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; } else { - /* The compiler produced a bogus file number. We can at least - record the macro definitions made in the file, even if we - won't be able to find the file by name. */ - char fake_name[80]; + struct dwarf2_locexpr_baton *baton; - sprintf (fake_name, "", file); + baton = obstack_alloc (&cu->objfile->objfile_obstack, + sizeof (struct dwarf2_locexpr_baton)); + baton->per_cu = cu->per_cu; + gdb_assert (baton->per_cu); - complaint (&symfile_complaints, - _("bad file number in macro information (%d)"), - file); + if (attr_form_is_block (attr)) + { + /* Note that we're just copying the block's data pointer + here, not the actual data. We're still pointing into the + info_buffer for SYM's objfile; right now we never release + that buffer, but when we do clean up properly this may + need to change. */ + baton->size = DW_BLOCK (attr)->size; + baton->data = DW_BLOCK (attr)->data; + } + else + { + dwarf2_invalid_attrib_class_complaint ("location description", + SYMBOL_NATURAL_NAME (sym)); + baton->size = 0; + baton->data = NULL; + } - return xstrdup (fake_name); + SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; } } +/* Return the OBJFILE associated with the compilation unit CU. If CU + came from a separate debuginfo file, then the master objfile is + returned. */ -static struct macro_source_file * -macro_start_file (int file, int line, - struct macro_source_file *current_file, - const char *comp_dir, - struct line_header *lh, struct objfile *objfile) +struct objfile * +dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *per_cu) { - /* The full name of this source file. */ - char *full_name = file_full_name (file, lh, comp_dir); + struct objfile *objfile = per_cu->objfile; - /* We don't create a macro table for this compilation unit - at all until we actually get a filename. */ - if (! pending_macros) - pending_macros = new_macro_table (&objfile->objfile_obstack, - objfile->macro_cache); + /* Return the master objfile, so that we can report and look up the + correct file containing this variable. */ + if (objfile->separate_debug_objfile_backlink) + objfile = objfile->separate_debug_objfile_backlink; - if (! current_file) - /* If we have no current file, then this must be the start_file - directive for the compilation unit's main source file. */ - current_file = macro_set_main (pending_macros, full_name); + return objfile; +} + +/* Return the address size given in the compilation unit header for CU. */ + +CORE_ADDR +dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) +{ + if (per_cu->cu) + return per_cu->cu->header.addr_size; else - current_file = macro_include (current_file, line, full_name); + { + /* If the CU is not currently read in, we re-read its header. */ + struct objfile *objfile = per_cu->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; + struct comp_unit_head cu_header; - xfree (full_name); + memset (&cu_header, 0, sizeof cu_header); + read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); + return cu_header.addr_size; + } +} - return current_file; +/* Return the offset size given in the compilation unit header for CU. */ + +int +dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) +{ + if (per_cu->cu) + return per_cu->cu->header.offset_size; + else + { + /* If the CU is not currently read in, we re-read its header. */ + struct objfile *objfile = per_cu->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; + struct comp_unit_head cu_header; + + memset (&cu_header, 0, sizeof cu_header); + read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); + return cu_header.offset_size; + } } +/* Return the text offset of the CU. The returned offset comes from + this CU's objfile. If this objfile came from a separate debuginfo + file, then the offset may be different from the corresponding + offset in the parent objfile. */ -/* Copy the LEN characters at BUF to a xmalloc'ed block of memory, - followed by a null byte. */ -static char * -copy_string (const char *buf, int len) +CORE_ADDR +dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) { - char *s = xmalloc (len + 1); + struct objfile *objfile = per_cu->objfile; - memcpy (s, buf, len); - s[len] = '\0'; - return s; + return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } +/* Locate the .debug_info compilation unit from CU's objfile which contains + the DIE at OFFSET. Raises an error on failure. */ -static const char * -consume_improper_spaces (const char *p, const char *body) +static struct dwarf2_per_cu_data * +dwarf2_find_containing_comp_unit (unsigned int offset, + struct objfile *objfile) { - if (*p == ' ') + struct dwarf2_per_cu_data *this_cu; + int low, high; + + low = 0; + high = dwarf2_per_objfile->n_comp_units - 1; + while (high > low) { - complaint (&symfile_complaints, - _("macro definition contains spaces in formal argument list:\n`%s'"), - body); + int mid = low + (high - low) / 2; - while (*p == ' ') - p++; + if (dwarf2_per_objfile->all_comp_units[mid]->offset >= offset) + high = mid; + else + low = mid + 1; } + gdb_assert (low == high); + if (dwarf2_per_objfile->all_comp_units[low]->offset > offset) + { + if (low == 0) + error (_("Dwarf Error: could not find partial DIE containing " + "offset 0x%lx [in module %s]"), + (long) offset, bfd_get_filename (objfile->obfd)); - return p; + gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset); + return dwarf2_per_objfile->all_comp_units[low-1]; + } + else + { + this_cu = dwarf2_per_objfile->all_comp_units[low]; + if (low == dwarf2_per_objfile->n_comp_units - 1 + && offset >= this_cu->offset + this_cu->length) + error (_("invalid dwarf2 offset %u"), offset); + gdb_assert (offset < this_cu->offset + this_cu->length); + return this_cu; + } } +/* Locate the compilation unit from OBJFILE which is located at exactly + OFFSET. Raises an error on failure. */ -static void -parse_macro_definition (struct macro_source_file *file, int line, - const char *body) +static struct dwarf2_per_cu_data * +dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile) { - const char *p; - - /* The body string takes one of two forms. For object-like macro - definitions, it should be: - - " " - - For function-like macro definitions, it should be: - - "() " - or - "(" ( "," ) * ") " + struct dwarf2_per_cu_data *this_cu; - Spaces may appear only where explicitly indicated, and in the - . + this_cu = dwarf2_find_containing_comp_unit (offset, objfile); + if (this_cu->offset != offset) + error (_("no compilation unit with offset %u."), offset); + return this_cu; +} - The Dwarf 2 spec says that an object-like macro's name is always - followed by a space, but versions of GCC around March 2002 omit - the space when the macro's definition is the empty string. +/* Initialize dwarf2_cu CU for OBJFILE in a pre-allocated space. */ - The Dwarf 2 spec says that there should be no spaces between the - formal arguments in a function-like macro's formal argument list, - but versions of GCC around March 2002 include spaces after the - commas. */ +static void +init_one_comp_unit (struct dwarf2_cu *cu, struct objfile *objfile) +{ + memset (cu, 0, sizeof (*cu)); + cu->objfile = objfile; + obstack_init (&cu->comp_unit_obstack); +} +/* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */ - /* Find the extent of the macro name. The macro name is terminated - by either a space or null character (for an object-like macro) or - an opening paren (for a function-like macro). */ - for (p = body; *p; p++) - if (*p == ' ' || *p == '(') - break; +static void +prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die) +{ + struct attribute *attr; - if (*p == ' ' || *p == '\0') + /* Set the language we're debugging. */ + attr = dwarf2_attr (comp_unit_die, DW_AT_language, cu); + if (attr) + set_cu_language (DW_UNSND (attr), cu); + else { - /* It's an object-like macro. */ - int name_len = p - body; - char *name = copy_string (body, name_len); - const char *replacement; - - if (*p == ' ') - replacement = body + name_len + 1; - else - { - dwarf2_macro_malformed_definition_complaint (body); - replacement = body + name_len; - } - - macro_define_object (file, line, name, replacement); - - xfree (name); + cu->language = language_minimal; + cu->language_defn = language_def (cu->language); } - else if (*p == '(') - { - /* It's a function-like macro. */ - char *name = copy_string (body, p - body); - int argc = 0; - int argv_size = 1; - char **argv = xmalloc (argv_size * sizeof (*argv)); - - p++; - - p = consume_improper_spaces (p, body); +} - /* Parse the formal argument list. */ - while (*p && *p != ')') - { - /* Find the extent of the current argument name. */ - const char *arg_start = p; +/* Release one cached compilation unit, CU. We unlink it from the tree + of compilation units, but we don't remove it from the read_in_chain; + the caller is responsible for that. + NOTE: DATA is a void * because this function is also used as a + cleanup routine. */ - while (*p && *p != ',' && *p != ')' && *p != ' ') - p++; +static void +free_one_comp_unit (void *data) +{ + struct dwarf2_cu *cu = data; - if (! *p || p == arg_start) - dwarf2_macro_malformed_definition_complaint (body); - else - { - /* Make sure argv has room for the new argument. */ - if (argc >= argv_size) - { - argv_size *= 2; - argv = xrealloc (argv, argv_size * sizeof (*argv)); - } + if (cu->per_cu != NULL) + cu->per_cu->cu = NULL; + cu->per_cu = NULL; - argv[argc++] = copy_string (arg_start, p - arg_start); - } + obstack_free (&cu->comp_unit_obstack, NULL); - p = consume_improper_spaces (p, body); + xfree (cu); +} - /* Consume the comma, if present. */ - if (*p == ',') - { - p++; +/* This cleanup function is passed the address of a dwarf2_cu on the stack + when we're finished with it. We can't free the pointer itself, but be + sure to unlink it from the cache. Also release any associated storage + and perform cache maintenance. - p = consume_improper_spaces (p, body); - } - } + Only used during partial symbol parsing. */ - if (*p == ')') - { - p++; +static void +free_stack_comp_unit (void *data) +{ + struct dwarf2_cu *cu = data; - if (*p == ' ') - /* Perfectly formed definition, no complaints. */ - macro_define_function (file, line, name, - argc, (const char **) argv, - p + 1); - else if (*p == '\0') - { - /* Complain, but do define it. */ - dwarf2_macro_malformed_definition_complaint (body); - macro_define_function (file, line, name, - argc, (const char **) argv, - p); - } - else - /* Just complain. */ - dwarf2_macro_malformed_definition_complaint (body); - } - else - /* Just complain. */ - dwarf2_macro_malformed_definition_complaint (body); + obstack_free (&cu->comp_unit_obstack, NULL); + cu->partial_dies = NULL; - xfree (name); - { - int i; + if (cu->per_cu != NULL) + { + /* This compilation unit is on the stack in our caller, so we + should not xfree it. Just unlink it. */ + cu->per_cu->cu = NULL; + cu->per_cu = NULL; - for (i = 0; i < argc; i++) - xfree (argv[i]); - } - xfree (argv); + /* If we had a per-cu pointer, then we may have other compilation + units loaded, so age them now. */ + age_cached_comp_units (); } - else - dwarf2_macro_malformed_definition_complaint (body); } +/* Free all cached compilation units. */ static void -dwarf_decode_macros (struct line_header *lh, unsigned int offset, - char *comp_dir, bfd *abfd, - struct dwarf2_cu *cu) +free_cached_comp_units (void *data) { - gdb_byte *mac_ptr, *mac_end; - struct macro_source_file *current_file = 0; - enum dwarf_macinfo_record_type macinfo_type; - int at_commandline; + struct dwarf2_per_cu_data *per_cu, **last_chain; - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->macinfo); - if (dwarf2_per_objfile->macinfo.buffer == NULL) + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) { - complaint (&symfile_complaints, _("missing .debug_macinfo section")); - return; + struct dwarf2_per_cu_data *next_cu; + + next_cu = per_cu->cu->read_in_chain; + + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; + + per_cu = next_cu; } +} - /* First pass: Find the name of the base filename. - This filename is needed in order to process all macros whose definition - (or undefinition) comes from the command line. These macros are defined - before the first DW_MACINFO_start_file entry, and yet still need to be - associated to the base file. +/* Increase the age counter on each cached compilation unit, and free + any that are too old. */ - To determine the base file name, we scan the macro definitions until we - reach the first DW_MACINFO_start_file entry. We then initialize - CURRENT_FILE accordingly so that any macro definition found before the - first DW_MACINFO_start_file can still be associated to the base file. */ +static void +age_cached_comp_units (void) +{ + struct dwarf2_per_cu_data *per_cu, **last_chain; - mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; - mac_end = dwarf2_per_objfile->macinfo.buffer - + dwarf2_per_objfile->macinfo.size; + dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain); + per_cu = dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + per_cu->cu->last_used ++; + if (per_cu->cu->last_used <= dwarf2_max_cache_age) + dwarf2_mark (per_cu->cu); + per_cu = per_cu->cu->read_in_chain; + } - do + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) { - /* Do we at least have room for a macinfo type byte? */ - if (mac_ptr >= mac_end) - { - /* Complaint is printed during the second pass as GDB will probably - stop the first pass earlier upon finding DW_MACINFO_start_file. */ - break; - } + struct dwarf2_per_cu_data *next_cu; - macinfo_type = read_1_byte (abfd, mac_ptr); - mac_ptr++; + next_cu = per_cu->cu->read_in_chain; - switch (macinfo_type) - { - /* A zero macinfo type indicates the end of the macro - information. */ - case 0: - break; + if (!per_cu->cu->mark) + { + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; + } + else + last_chain = &per_cu->cu->read_in_chain; - case DW_MACINFO_define: - case DW_MACINFO_undef: - /* Only skip the data by MAC_PTR. */ - { - unsigned int bytes_read; + per_cu = next_cu; + } +} - read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - read_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - } - break; +/* Remove a single compilation unit from the cache. */ - case DW_MACINFO_start_file: - { - unsigned int bytes_read; - int line, file; +static void +free_one_cached_comp_unit (void *target_cu) +{ + struct dwarf2_per_cu_data *per_cu, **last_chain; - line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + struct dwarf2_per_cu_data *next_cu; - current_file = macro_start_file (file, line, current_file, comp_dir, - lh, cu->objfile); - } - break; + next_cu = per_cu->cu->read_in_chain; - case DW_MACINFO_end_file: - /* No data to skip by MAC_PTR. */ + if (per_cu->cu == target_cu) + { + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; break; + } + else + last_chain = &per_cu->cu->read_in_chain; - case DW_MACINFO_vendor_ext: - /* Only skip the data by MAC_PTR. */ - { - unsigned int bytes_read; + per_cu = next_cu; + } +} - read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - read_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - } - break; +/* Release all extra memory associated with OBJFILE. */ - default: - break; - } - } while (macinfo_type != 0 && current_file == NULL); +void +dwarf2_free_objfile (struct objfile *objfile) +{ + dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); - /* Second pass: Process all entries. + if (dwarf2_per_objfile == NULL) + return; - Use the AT_COMMAND_LINE flag to determine whether we are still processing - command-line macro definitions/undefinitions. This flag is unset when we - reach the first DW_MACINFO_start_file entry. */ + /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ + free_cached_comp_units (NULL); - mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; + if (dwarf2_per_objfile->quick_file_names_table) + htab_delete (dwarf2_per_objfile->quick_file_names_table); - /* Determines if GDB is still before first DW_MACINFO_start_file. If true - GDB is still reading the definitions from command line. First - DW_MACINFO_start_file will need to be ignored as it was already executed - to create CURRENT_FILE for the main source holding also the command line - definitions. On first met DW_MACINFO_start_file this flag is reset to - normally execute all the remaining DW_MACINFO_start_file macinfos. */ + /* Everything else should be on the objfile obstack. */ +} - at_commandline = 1; +/* A pair of DIE offset and GDB type pointer. We store these + in a hash table separate from the DIEs, and preserve them + when the DIEs are flushed out of cache. */ - do - { - /* Do we at least have room for a macinfo type byte? */ - if (mac_ptr >= mac_end) - { - dwarf2_macros_too_long_complaint (); - break; - } +struct dwarf2_offset_and_type +{ + unsigned int offset; + struct type *type; +}; - macinfo_type = read_1_byte (abfd, mac_ptr); - mac_ptr++; +/* Hash function for a dwarf2_offset_and_type. */ - switch (macinfo_type) - { - /* A zero macinfo type indicates the end of the macro - information. */ - case 0: - break; +static hashval_t +offset_and_type_hash (const void *item) +{ + const struct dwarf2_offset_and_type *ofs = item; - case DW_MACINFO_define: - case DW_MACINFO_undef: - { - unsigned int bytes_read; - int line; - char *body; + return ofs->offset; +} - line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - body = read_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; +/* Equality function for a dwarf2_offset_and_type. */ - if (! current_file) - { - /* DWARF violation as no main source is present. */ - complaint (&symfile_complaints, - _("debug info with no main source gives macro %s " - "on line %d: %s"), - macinfo_type == DW_MACINFO_define ? - _("definition") : - macinfo_type == DW_MACINFO_undef ? - _("undefinition") : - _("something-or-other"), line, body); - break; - } - if ((line == 0 && !at_commandline) || (line != 0 && at_commandline)) - complaint (&symfile_complaints, - _("debug info gives %s macro %s with %s line %d: %s"), - at_commandline ? _("command-line") : _("in-file"), - macinfo_type == DW_MACINFO_define ? - _("definition") : - macinfo_type == DW_MACINFO_undef ? - _("undefinition") : - _("something-or-other"), - line == 0 ? _("zero") : _("non-zero"), line, body); +static int +offset_and_type_eq (const void *item_lhs, const void *item_rhs) +{ + const struct dwarf2_offset_and_type *ofs_lhs = item_lhs; + const struct dwarf2_offset_and_type *ofs_rhs = item_rhs; - if (macinfo_type == DW_MACINFO_define) - parse_macro_definition (current_file, line, body); - else if (macinfo_type == DW_MACINFO_undef) - macro_undef (current_file, line, body); - } - break; + return ofs_lhs->offset == ofs_rhs->offset; +} - case DW_MACINFO_start_file: - { - unsigned int bytes_read; - int line, file; +/* Set the type associated with DIE to TYPE. Save it in CU's hash + table if necessary. For convenience, return TYPE. - line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; + The DIEs reading must have careful ordering to: + * Not cause infite loops trying to read in DIEs as a prerequisite for + reading current DIE. + * Not trying to dereference contents of still incompletely read in types + while reading in other DIEs. + * Enable referencing still incompletely read in types just by a pointer to + the type without accessing its fields. - if ((line == 0 && !at_commandline) || (line != 0 && at_commandline)) - complaint (&symfile_complaints, - _("debug info gives source %d included " - "from %s at %s line %d"), - file, at_commandline ? _("command-line") : _("file"), - line == 0 ? _("zero") : _("non-zero"), line); + Therefore caller should follow these rules: + * Try to fetch any prerequisite types we may need to build this DIE type + before building the type and calling set_die_type. + * After building type call set_die_type for current DIE as soon as + possible before fetching more types to complete the current type. + * Make the type as complete as possible before fetching more types. */ + +static struct type * +set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +{ + struct dwarf2_offset_and_type **slot, ofs; + struct objfile *objfile = cu->objfile; + htab_t *type_hash_ptr; + + /* For Ada types, make sure that the gnat-specific data is always + initialized (if not already set). There are a few types where + we should not be doing so, because the type-specific area is + already used to hold some other piece of info (eg: TYPE_CODE_FLT + where the type-specific area is used to store the floatformat). + But this is not a problem, because the gnat-specific information + is actually not needed for these types. */ + if (need_gnat_info (cu) + && TYPE_CODE (type) != TYPE_CODE_FUNC + && TYPE_CODE (type) != TYPE_CODE_FLT + && !HAVE_GNAT_AUX_INFO (type)) + INIT_GNAT_SPECIFIC (type); - if (at_commandline) - { - /* This DW_MACINFO_start_file was executed in the pass one. */ - at_commandline = 0; - } - else - current_file = macro_start_file (file, line, - current_file, comp_dir, - lh, cu->objfile); - } - break; + if (cu->per_cu->from_debug_types) + type_hash_ptr = &dwarf2_per_objfile->debug_types_type_hash; + else + type_hash_ptr = &dwarf2_per_objfile->debug_info_type_hash; - case DW_MACINFO_end_file: - if (! current_file) - complaint (&symfile_complaints, - _("macro debug info has an unmatched `close_file' directive")); - else - { - current_file = current_file->included_by; - if (! current_file) - { - enum dwarf_macinfo_record_type next_type; + if (*type_hash_ptr == NULL) + { + *type_hash_ptr + = htab_create_alloc_ex (127, + offset_and_type_hash, + offset_and_type_eq, + NULL, + &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + } - /* GCC circa March 2002 doesn't produce the zero - type byte marking the end of the compilation - unit. Complain if it's not there, but exit no - matter what. */ + ofs.offset = die->offset; + ofs.type = type; + slot = (struct dwarf2_offset_and_type **) + htab_find_slot_with_hash (*type_hash_ptr, &ofs, ofs.offset, INSERT); + if (*slot) + complaint (&symfile_complaints, + _("A problem internal to GDB: DIE 0x%x has type already set"), + die->offset); + *slot = obstack_alloc (&objfile->objfile_obstack, sizeof (**slot)); + **slot = ofs; + return type; +} - /* Do we at least have room for a macinfo type byte? */ - if (mac_ptr >= mac_end) - { - dwarf2_macros_too_long_complaint (); - return; - } +/* Look up the type for the die at DIE_OFFSET in the appropriate type_hash + table, or return NULL if the die does not have a saved type. */ - /* We don't increment mac_ptr here, so this is just - a look-ahead. */ - next_type = read_1_byte (abfd, mac_ptr); - if (next_type != 0) - complaint (&symfile_complaints, - _("no terminating 0-type entry for macros in `.debug_macinfo' section")); +static struct type * +get_die_type_at_offset (unsigned int offset, + struct dwarf2_per_cu_data *per_cu) +{ + struct dwarf2_offset_and_type *slot, ofs; + htab_t type_hash; - return; - } - } - break; + if (per_cu->from_debug_types) + type_hash = dwarf2_per_objfile->debug_types_type_hash; + else + type_hash = dwarf2_per_objfile->debug_info_type_hash; + if (type_hash == NULL) + return NULL; - case DW_MACINFO_vendor_ext: - { - unsigned int bytes_read; - int constant; - char *string; + ofs.offset = offset; + slot = htab_find_with_hash (type_hash, &ofs, ofs.offset); + if (slot) + return slot->type; + else + return NULL; +} - constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - string = read_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; +/* Look up the type for DIE in the appropriate type_hash table, + or return NULL if DIE does not have a saved type. */ - /* We don't recognize any vendor extensions. */ - } - break; - } - } while (macinfo_type != 0); +static struct type * +get_die_type (struct die_info *die, struct dwarf2_cu *cu) +{ + return get_die_type_at_offset (die->offset, cu->per_cu); } -/* Check if the attribute's form is a DW_FORM_block* - if so return true else false. */ -static int -attr_form_is_block (struct attribute *attr) +/* Add a dependence relationship from CU to REF_PER_CU. */ + +static void +dwarf2_add_dependence (struct dwarf2_cu *cu, + struct dwarf2_per_cu_data *ref_per_cu) { - return (attr == NULL ? 0 : - attr->form == DW_FORM_block1 - || attr->form == DW_FORM_block2 - || attr->form == DW_FORM_block4 - || attr->form == DW_FORM_block - || attr->form == DW_FORM_exprloc); + void **slot; + + if (cu->dependencies == NULL) + cu->dependencies + = htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer, + NULL, &cu->comp_unit_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + + slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT); + if (*slot == NULL) + *slot = ref_per_cu; } -/* Return non-zero if ATTR's value is a section offset --- classes - lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise. - You may use DW_UNSND (attr) to retrieve such offsets. +/* Subroutine of dwarf2_mark to pass to htab_traverse. + Set the mark field in every compilation unit in the + cache that we must keep because we are keeping CU. */ - Section 7.5.4, "Attribute Encodings", explains that no attribute - may have a value that belongs to more than one of these classes; it - would be ambiguous if we did, because we use the same forms for all - of them. */ static int -attr_form_is_section_offset (struct attribute *attr) +dwarf2_mark_helper (void **slot, void *data) { - return (attr->form == DW_FORM_data4 - || attr->form == DW_FORM_data8 - || attr->form == DW_FORM_sec_offset); -} + struct dwarf2_per_cu_data *per_cu; + per_cu = (struct dwarf2_per_cu_data *) *slot; -/* Return non-zero if ATTR's value falls in the 'constant' class, or - zero otherwise. When this function returns true, you can apply - dwarf2_get_attr_constant_value to it. + /* cu->dependencies references may not yet have been ever read if QUIT aborts + reading of the chain. As such dependencies remain valid it is not much + useful to track and undo them during QUIT cleanups. */ + if (per_cu->cu == NULL) + return 1; - However, note that for some attributes you must check - attr_form_is_section_offset before using this test. DW_FORM_data4 - and DW_FORM_data8 are members of both the constant class, and of - the classes that contain offsets into other debug sections - (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says - that, if an attribute's can be either a constant or one of the - section offset classes, DW_FORM_data4 and DW_FORM_data8 should be - taken as section offsets, not constants. */ -static int -attr_form_is_constant (struct attribute *attr) + if (per_cu->cu->mark) + return 1; + per_cu->cu->mark = 1; + + if (per_cu->cu->dependencies != NULL) + htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL); + + return 1; +} + +/* Set the mark field in CU and in every other compilation unit in the + cache that we must keep because we are keeping CU. */ + +static void +dwarf2_mark (struct dwarf2_cu *cu) { - switch (attr->form) - { - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_data8: - return 1; - default: - return 0; - } + if (cu->mark) + return; + cu->mark = 1; + if (cu->dependencies != NULL) + htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL); } static void -dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, - struct dwarf2_cu *cu) +dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) { - if (attr_form_is_section_offset (attr) - /* ".debug_loc" may not exist at all, or the offset may be outside - the section. If so, fall through to the complaint in the - other branch. */ - && DW_UNSND (attr) < dwarf2_per_objfile->loc.size) + while (per_cu) { - struct dwarf2_loclist_baton *baton; - - baton = obstack_alloc (&cu->objfile->objfile_obstack, - sizeof (struct dwarf2_loclist_baton)); - baton->per_cu = cu->per_cu; - gdb_assert (baton->per_cu); + per_cu->cu->mark = 0; + per_cu = per_cu->cu->read_in_chain; + } +} - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->loc); +/* Trivial hash function for partial_die_info: the hash value of a DIE + is its offset in .debug_info for this objfile. */ - /* We don't know how long the location list is, but make sure we - don't run off the edge of the section. */ - baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr); - baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr); - baton->base_address = cu->base_address; - if (cu->base_known == 0) - complaint (&symfile_complaints, - _("Location list used without specifying the CU base address.")); +static hashval_t +partial_die_hash (const void *item) +{ + const struct partial_die_info *part_die = item; - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; - } - else - { - struct dwarf2_locexpr_baton *baton; + return part_die->offset; +} - baton = obstack_alloc (&cu->objfile->objfile_obstack, - sizeof (struct dwarf2_locexpr_baton)); - baton->per_cu = cu->per_cu; - gdb_assert (baton->per_cu); +/* Trivial comparison function for partial_die_info structures: two DIEs + are equal if they have the same offset. */ - if (attr_form_is_block (attr)) - { - /* Note that we're just copying the block's data pointer - here, not the actual data. We're still pointing into the - info_buffer for SYM's objfile; right now we never release - that buffer, but when we do clean up properly this may - need to change. */ - baton->size = DW_BLOCK (attr)->size; - baton->data = DW_BLOCK (attr)->data; - } - else - { - dwarf2_invalid_attrib_class_complaint ("location description", - SYMBOL_NATURAL_NAME (sym)); - baton->size = 0; - baton->data = NULL; - } +static int +partial_die_eq (const void *item_lhs, const void *item_rhs) +{ + const struct partial_die_info *part_die_lhs = item_lhs; + const struct partial_die_info *part_die_rhs = item_rhs; - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; - } + return part_die_lhs->offset == part_die_rhs->offset; } -/* Return the OBJFILE associated with the compilation unit CU. If CU - came from a separate debuginfo file, then the master objfile is - returned. */ +static struct cmd_list_element *set_dwarf2_cmdlist; +static struct cmd_list_element *show_dwarf2_cmdlist; -struct objfile * -dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *per_cu) +static void +set_dwarf2_cmd (char *args, int from_tty) { - struct objfile *objfile = per_cu->psymtab->objfile; - - /* Return the master objfile, so that we can report and look up the - correct file containing this variable. */ - if (objfile->separate_debug_objfile_backlink) - objfile = objfile->separate_debug_objfile_backlink; + help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout); +} - return objfile; +static void +show_dwarf2_cmd (char *args, int from_tty) +{ + cmd_show_list (show_dwarf2_cmdlist, from_tty, ""); } -/* Return the address size given in the compilation unit header for CU. */ +/* If section described by INFO was mmapped, munmap it now. */ -CORE_ADDR -dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) +static void +munmap_section_buffer (struct dwarf2_section_info *info) { - if (per_cu->cu) - return per_cu->cu->header.addr_size; - else + if (info->was_mmapped) { - /* If the CU is not currently read in, we re-read its header. */ - struct objfile *objfile = per_cu->psymtab->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; +#ifdef HAVE_MMAP + intptr_t begin = (intptr_t) info->buffer; + intptr_t map_begin = begin & ~(pagesize - 1); + size_t map_length = info->size + begin - map_begin; - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.addr_size; + gdb_assert (munmap ((void *) map_begin, map_length) == 0); +#else + /* Without HAVE_MMAP, we should never be here to begin with. */ + gdb_assert_not_reached ("no mmap support"); +#endif } } -/* Return the offset size given in the compilation unit header for CU. */ +/* munmap debug sections for OBJFILE, if necessary. */ -int -dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) +static void +dwarf2_per_objfile_free (struct objfile *objfile, void *d) { - if (per_cu->cu) - return per_cu->cu->header.offset_size; - else - { - /* If the CU is not currently read in, we re-read its header. */ - struct objfile *objfile = per_cu->psymtab->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; + struct dwarf2_per_objfile *data = d; - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.offset_size; - } + /* This is sorted according to the order they're defined in to make it easier + to keep in sync. */ + munmap_section_buffer (&data->info); + munmap_section_buffer (&data->abbrev); + munmap_section_buffer (&data->line); + munmap_section_buffer (&data->loc); + munmap_section_buffer (&data->macinfo); + munmap_section_buffer (&data->str); + munmap_section_buffer (&data->ranges); + munmap_section_buffer (&data->types); + munmap_section_buffer (&data->frame); + munmap_section_buffer (&data->eh_frame); + munmap_section_buffer (&data->gdb_index); } -/* Return the text offset of the CU. The returned offset comes from - this CU's objfile. If this objfile came from a separate debuginfo - file, then the offset may be different from the corresponding - offset in the parent objfile. */ + +/* The "save gdb-index" command. */ -CORE_ADDR -dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) +/* The contents of the hash table we create when building the string + table. */ +struct strtab_entry { - struct objfile *objfile = per_cu->psymtab->objfile; + offset_type offset; + const char *str; +}; - return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); +/* Hash function for a strtab_entry. */ + +static hashval_t +hash_strtab_entry (const void *e) +{ + const struct strtab_entry *entry = e; + return mapped_index_string_hash (entry->str); } -/* Locate the .debug_info compilation unit from CU's objfile which contains - the DIE at OFFSET. Raises an error on failure. */ +/* Equality function for a strtab_entry. */ -static struct dwarf2_per_cu_data * -dwarf2_find_containing_comp_unit (unsigned int offset, - struct objfile *objfile) +static int +eq_strtab_entry (const void *a, const void *b) { - struct dwarf2_per_cu_data *this_cu; - int low, high; + const struct strtab_entry *ea = a; + const struct strtab_entry *eb = b; + return !strcmp (ea->str, eb->str); +} - low = 0; - high = dwarf2_per_objfile->n_comp_units - 1; - while (high > low) - { - int mid = low + (high - low) / 2; +/* Create a strtab_entry hash table. */ - if (dwarf2_per_objfile->all_comp_units[mid]->offset >= offset) - high = mid; - else - low = mid + 1; - } - gdb_assert (low == high); - if (dwarf2_per_objfile->all_comp_units[low]->offset > offset) - { - if (low == 0) - error (_("Dwarf Error: could not find partial DIE containing " - "offset 0x%lx [in module %s]"), - (long) offset, bfd_get_filename (objfile->obfd)); +static htab_t +create_strtab (void) +{ + return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry, + xfree, xcalloc, xfree); +} - gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset); - return dwarf2_per_objfile->all_comp_units[low-1]; - } +/* Add a string to the constant pool. Return the string's offset in + host order. */ + +static offset_type +add_string (htab_t table, struct obstack *cpool, const char *str) +{ + void **slot; + struct strtab_entry entry; + struct strtab_entry *result; + + entry.str = str; + slot = htab_find_slot (table, &entry, INSERT); + if (*slot) + result = *slot; else { - this_cu = dwarf2_per_objfile->all_comp_units[low]; - if (low == dwarf2_per_objfile->n_comp_units - 1 - && offset >= this_cu->offset + this_cu->length) - error (_("invalid dwarf2 offset %u"), offset); - gdb_assert (offset < this_cu->offset + this_cu->length); - return this_cu; + result = XNEW (struct strtab_entry); + result->offset = obstack_object_size (cpool); + result->str = str; + obstack_grow_str0 (cpool, str); + *slot = result; } + return result->offset; } -/* Locate the compilation unit from OBJFILE which is located at exactly - OFFSET. Raises an error on failure. */ +/* An entry in the symbol table. */ +struct symtab_index_entry +{ + /* The name of the symbol. */ + const char *name; + /* The offset of the name in the constant pool. */ + offset_type index_offset; + /* A sorted vector of the indices of all the CUs that hold an object + of this name. */ + VEC (offset_type) *cu_indices; +}; -static struct dwarf2_per_cu_data * -dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile) +/* The symbol table. This is a power-of-2-sized hash table. */ +struct mapped_symtab { - struct dwarf2_per_cu_data *this_cu; + offset_type n_elements; + offset_type size; + struct symtab_index_entry **data; +}; - this_cu = dwarf2_find_containing_comp_unit (offset, objfile); - if (this_cu->offset != offset) - error (_("no compilation unit with offset %u."), offset); - return this_cu; +/* Hash function for a symtab_index_entry. */ + +static hashval_t +hash_symtab_entry (const void *e) +{ + const struct symtab_index_entry *entry = e; + return iterative_hash (VEC_address (offset_type, entry->cu_indices), + sizeof (offset_type) * VEC_length (offset_type, + entry->cu_indices), + 0); } -/* Malloc space for a dwarf2_cu for OBJFILE and initialize it. */ +/* Equality function for a symtab_index_entry. */ -static struct dwarf2_cu * -alloc_one_comp_unit (struct objfile *objfile) +static int +eq_symtab_entry (const void *a, const void *b) { - struct dwarf2_cu *cu = xcalloc (1, sizeof (struct dwarf2_cu)); - cu->objfile = objfile; - obstack_init (&cu->comp_unit_obstack); - return cu; + const struct symtab_index_entry *ea = a; + const struct symtab_index_entry *eb = b; + int len = VEC_length (offset_type, ea->cu_indices); + if (len != VEC_length (offset_type, eb->cu_indices)) + return 0; + return !memcmp (VEC_address (offset_type, ea->cu_indices), + VEC_address (offset_type, eb->cu_indices), + sizeof (offset_type) * len); } -/* Release one cached compilation unit, CU. We unlink it from the tree - of compilation units, but we don't remove it from the read_in_chain; - the caller is responsible for that. - NOTE: DATA is a void * because this function is also used as a - cleanup routine. */ +/* Destroy a symtab_index_entry. */ static void -free_one_comp_unit (void *data) +delete_symtab_entry (void *p) { - struct dwarf2_cu *cu = data; - - if (cu->per_cu != NULL) - cu->per_cu->cu = NULL; - cu->per_cu = NULL; + struct symtab_index_entry *entry = p; + VEC_free (offset_type, entry->cu_indices); + xfree (entry); +} - obstack_free (&cu->comp_unit_obstack, NULL); +/* Create a hash table holding symtab_index_entry objects. */ - xfree (cu); +static htab_t +create_symbol_hash_table (void) +{ + return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry, + delete_symtab_entry, xcalloc, xfree); } -/* This cleanup function is passed the address of a dwarf2_cu on the stack - when we're finished with it. We can't free the pointer itself, but be - sure to unlink it from the cache. Also release any associated storage - and perform cache maintenance. +/* Create a new mapped symtab object. */ - Only used during partial symbol parsing. */ +static struct mapped_symtab * +create_mapped_symtab (void) +{ + struct mapped_symtab *symtab = XNEW (struct mapped_symtab); + symtab->n_elements = 0; + symtab->size = 1024; + symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); + return symtab; +} + +/* Destroy a mapped_symtab. */ static void -free_stack_comp_unit (void *data) +cleanup_mapped_symtab (void *p) { - struct dwarf2_cu *cu = data; + struct mapped_symtab *symtab = p; + /* The contents of the array are freed when the other hash table is + destroyed. */ + xfree (symtab->data); + xfree (symtab); +} - obstack_free (&cu->comp_unit_obstack, NULL); - cu->partial_dies = NULL; +/* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to + the slot. */ - if (cu->per_cu != NULL) - { - /* This compilation unit is on the stack in our caller, so we - should not xfree it. Just unlink it. */ - cu->per_cu->cu = NULL; - cu->per_cu = NULL; +static struct symtab_index_entry ** +find_slot (struct mapped_symtab *symtab, const char *name) +{ + offset_type index, step, hash = mapped_index_string_hash (name); - /* If we had a per-cu pointer, then we may have other compilation - units loaded, so age them now. */ - age_cached_comp_units (); + index = hash & (symtab->size - 1); + step = ((hash * 17) & (symtab->size - 1)) | 1; + + for (;;) + { + if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name)) + return &symtab->data[index]; + index = (index + step) & (symtab->size - 1); } } -/* Free all cached compilation units. */ +/* Expand SYMTAB's hash table. */ static void -free_cached_comp_units (void *data) +hash_expand (struct mapped_symtab *symtab) { - struct dwarf2_per_cu_data *per_cu, **last_chain; - - per_cu = dwarf2_per_objfile->read_in_chain; - last_chain = &dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) - { - struct dwarf2_per_cu_data *next_cu; - - next_cu = per_cu->cu->read_in_chain; + offset_type old_size = symtab->size; + offset_type i; + struct symtab_index_entry **old_entries = symtab->data; - free_one_comp_unit (per_cu->cu); - *last_chain = next_cu; + symtab->size *= 2; + symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); - per_cu = next_cu; + for (i = 0; i < old_size; ++i) + { + if (old_entries[i]) + { + struct symtab_index_entry **slot = find_slot (symtab, + old_entries[i]->name); + *slot = old_entries[i]; + } } + + xfree (old_entries); } -/* Increase the age counter on each cached compilation unit, and free - any that are too old. */ +/* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX + is the index of the CU in which the symbol appears. */ static void -age_cached_comp_units (void) +add_index_entry (struct mapped_symtab *symtab, const char *name, + offset_type cu_index) { - struct dwarf2_per_cu_data *per_cu, **last_chain; + struct symtab_index_entry **slot; - dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain); - per_cu = dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) + ++symtab->n_elements; + if (4 * symtab->n_elements / 3 >= symtab->size) + hash_expand (symtab); + + slot = find_slot (symtab, name); + if (!*slot) { - per_cu->cu->last_used ++; - if (per_cu->cu->last_used <= dwarf2_max_cache_age) - dwarf2_mark (per_cu->cu); - per_cu = per_cu->cu->read_in_chain; + *slot = XNEW (struct symtab_index_entry); + (*slot)->name = name; + (*slot)->cu_indices = NULL; } + /* Don't push an index twice. Due to how we add entries we only + have to check the last one. */ + if (VEC_empty (offset_type, (*slot)->cu_indices) + || VEC_length (offset_type, (*slot)->cu_indices) != cu_index) + VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index); +} - per_cu = dwarf2_per_objfile->read_in_chain; - last_chain = &dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) +/* Add a vector of indices to the constant pool. */ + +static offset_type +add_indices_to_cpool (htab_t symbol_hash_table, struct obstack *cpool, + struct symtab_index_entry *entry) +{ + void **slot; + + slot = htab_find_slot (symbol_hash_table, entry, INSERT); + if (!*slot) { - struct dwarf2_per_cu_data *next_cu; + offset_type len = VEC_length (offset_type, entry->cu_indices); + offset_type val = MAYBE_SWAP (len); + offset_type iter; + int i; - next_cu = per_cu->cu->read_in_chain; + *slot = entry; + entry->index_offset = obstack_object_size (cpool); - if (!per_cu->cu->mark) + obstack_grow (cpool, &val, sizeof (val)); + for (i = 0; + VEC_iterate (offset_type, entry->cu_indices, i, iter); + ++i) { - free_one_comp_unit (per_cu->cu); - *last_chain = next_cu; + val = MAYBE_SWAP (iter); + obstack_grow (cpool, &val, sizeof (val)); } - else - last_chain = &per_cu->cu->read_in_chain; - - per_cu = next_cu; } + else + { + struct symtab_index_entry *old_entry = *slot; + entry->index_offset = old_entry->index_offset; + entry = old_entry; + } + return entry->index_offset; } -/* Remove a single compilation unit from the cache. */ +/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with + constant pool entries going into the obstack CPOOL. */ static void -free_one_cached_comp_unit (void *target_cu) +write_hash_table (struct mapped_symtab *symtab, + struct obstack *output, struct obstack *cpool) { - struct dwarf2_per_cu_data *per_cu, **last_chain; - - per_cu = dwarf2_per_objfile->read_in_chain; - last_chain = &dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) - { - struct dwarf2_per_cu_data *next_cu; - - next_cu = per_cu->cu->read_in_chain; + offset_type i; + htab_t symbol_hash_table; + htab_t str_table; - if (per_cu->cu == target_cu) - { - free_one_comp_unit (per_cu->cu); - *last_chain = next_cu; - break; - } - else - last_chain = &per_cu->cu->read_in_chain; + symbol_hash_table = create_symbol_hash_table (); + str_table = create_strtab (); - per_cu = next_cu; + /* We add all the index vectors to the constant pool first, to + ensure alignment is ok. */ + for (i = 0; i < symtab->size; ++i) + { + if (symtab->data[i]) + add_indices_to_cpool (symbol_hash_table, cpool, symtab->data[i]); } -} -/* Release all extra memory associated with OBJFILE. */ + /* Now write out the hash table. */ + for (i = 0; i < symtab->size; ++i) + { + offset_type str_off, vec_off; -void -dwarf2_free_objfile (struct objfile *objfile) -{ - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + if (symtab->data[i]) + { + str_off = add_string (str_table, cpool, symtab->data[i]->name); + vec_off = symtab->data[i]->index_offset; + } + else + { + /* While 0 is a valid constant pool index, it is not valid + to have 0 for both offsets. */ + str_off = 0; + vec_off = 0; + } - if (dwarf2_per_objfile == NULL) - return; + str_off = MAYBE_SWAP (str_off); + vec_off = MAYBE_SWAP (vec_off); - /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ - free_cached_comp_units (NULL); + obstack_grow (output, &str_off, sizeof (str_off)); + obstack_grow (output, &vec_off, sizeof (vec_off)); + } - /* Everything else should be on the objfile obstack. */ + htab_delete (str_table); + htab_delete (symbol_hash_table); } -/* A pair of DIE offset and GDB type pointer. We store these - in a hash table separate from the DIEs, and preserve them - when the DIEs are flushed out of cache. */ - -struct dwarf2_offset_and_type +/* Struct to map psymtab to CU index in the index file. */ +struct psymtab_cu_index_map { - unsigned int offset; - struct type *type; + struct partial_symtab *psymtab; + unsigned int cu_index; }; -/* Hash function for a dwarf2_offset_and_type. */ - static hashval_t -offset_and_type_hash (const void *item) +hash_psymtab_cu_index (const void *item) { - const struct dwarf2_offset_and_type *ofs = item; + const struct psymtab_cu_index_map *map = item; - return ofs->offset; + return htab_hash_pointer (map->psymtab); } -/* Equality function for a dwarf2_offset_and_type. */ - static int -offset_and_type_eq (const void *item_lhs, const void *item_rhs) +eq_psymtab_cu_index (const void *item_lhs, const void *item_rhs) { - const struct dwarf2_offset_and_type *ofs_lhs = item_lhs; - const struct dwarf2_offset_and_type *ofs_rhs = item_rhs; + const struct psymtab_cu_index_map *lhs = item_lhs; + const struct psymtab_cu_index_map *rhs = item_rhs; - return ofs_lhs->offset == ofs_rhs->offset; + return lhs->psymtab == rhs->psymtab; } -/* Set the type associated with DIE to TYPE. Save it in CU's hash - table if necessary. For convenience, return TYPE. - - The DIEs reading must have careful ordering to: - * Not cause infite loops trying to read in DIEs as a prerequisite for - reading current DIE. - * Not trying to dereference contents of still incompletely read in types - while reading in other DIEs. - * Enable referencing still incompletely read in types just by a pointer to - the type without accessing its fields. +/* Helper struct for building the address table. */ +struct addrmap_index_data +{ + struct objfile *objfile; + struct obstack *addr_obstack; + htab_t cu_index_htab; + + /* Non-zero if the previous_* fields are valid. + We can't write an entry until we see the next entry (since it is only then + that we know the end of the entry). */ + int previous_valid; + /* Index of the CU in the table of all CUs in the index file. */ + unsigned int previous_cu_index; + /* Start address of the CU. */ + CORE_ADDR previous_cu_start; +}; - Therefore caller should follow these rules: - * Try to fetch any prerequisite types we may need to build this DIE type - before building the type and calling set_die_type. - * After building typer call set_die_type for current DIE as soon as - possible before fetching more types to complete the current type. - * Make the type as complete as possible before fetching more types. */ +/* Write an address entry to OBSTACK. */ -static struct type * -set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +static void +add_address_entry (struct objfile *objfile, struct obstack *obstack, + CORE_ADDR start, CORE_ADDR end, unsigned int cu_index) { - struct dwarf2_offset_and_type **slot, ofs; - - /* For Ada types, make sure that the gnat-specific data is always - initialized (if not already set). There are a few types where - we should not be doing so, because the type-specific area is - already used to hold some other piece of info (eg: TYPE_CODE_FLT - where the type-specific area is used to store the floatformat). - But this is not a problem, because the gnat-specific information - is actually not needed for these types. */ - if (need_gnat_info (cu) - && TYPE_CODE (type) != TYPE_CODE_FUNC - && TYPE_CODE (type) != TYPE_CODE_FLT - && !HAVE_GNAT_AUX_INFO (type)) - INIT_GNAT_SPECIFIC (type); + offset_type cu_index_to_write; + char addr[8]; + CORE_ADDR baseaddr; - if (cu->type_hash == NULL) - { - gdb_assert (cu->per_cu != NULL); - cu->per_cu->type_hash - = htab_create_alloc_ex (cu->header.length / 24, - offset_and_type_hash, - offset_and_type_eq, - NULL, - &cu->objfile->objfile_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); - cu->type_hash = cu->per_cu->type_hash; - } + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - ofs.offset = die->offset; - ofs.type = type; - slot = (struct dwarf2_offset_and_type **) - htab_find_slot_with_hash (cu->type_hash, &ofs, ofs.offset, INSERT); - if (*slot) - complaint (&symfile_complaints, - _("A problem internal to GDB: DIE 0x%x has type already set"), - die->offset); - *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot)); - **slot = ofs; - return type; + store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, start - baseaddr); + obstack_grow (obstack, addr, 8); + store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, end - baseaddr); + obstack_grow (obstack, addr, 8); + cu_index_to_write = MAYBE_SWAP (cu_index); + obstack_grow (obstack, &cu_index_to_write, sizeof (offset_type)); } -/* Find the type for DIE in CU's type_hash, or return NULL if DIE does - not have a saved type. */ +/* Worker function for traversing an addrmap to build the address table. */ -static struct type * -get_die_type (struct die_info *die, struct dwarf2_cu *cu) +static int +add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj) { - struct dwarf2_offset_and_type *slot, ofs; - htab_t type_hash = cu->type_hash; + struct addrmap_index_data *data = datap; + struct partial_symtab *pst = obj; + offset_type cu_index; + void **slot; - if (type_hash == NULL) - return NULL; + if (data->previous_valid) + add_address_entry (data->objfile, data->addr_obstack, + data->previous_cu_start, start_addr, + data->previous_cu_index); - ofs.offset = die->offset; - slot = htab_find_with_hash (type_hash, &ofs, ofs.offset); - if (slot) - return slot->type; + data->previous_cu_start = start_addr; + if (pst != NULL) + { + struct psymtab_cu_index_map find_map, *map; + find_map.psymtab = pst; + map = htab_find (data->cu_index_htab, &find_map); + gdb_assert (map != NULL); + data->previous_cu_index = map->cu_index; + data->previous_valid = 1; + } else - return NULL; + data->previous_valid = 0; + + return 0; } -/* Add a dependence relationship from CU to REF_PER_CU. */ +/* Write OBJFILE's address map to OBSTACK. + CU_INDEX_HTAB is used to map addrmap entries to their CU indices + in the index file. */ static void -dwarf2_add_dependence (struct dwarf2_cu *cu, - struct dwarf2_per_cu_data *ref_per_cu) +write_address_map (struct objfile *objfile, struct obstack *obstack, + htab_t cu_index_htab) { - void **slot; + struct addrmap_index_data addrmap_index_data; - if (cu->dependencies == NULL) - cu->dependencies - = htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer, - NULL, &cu->comp_unit_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); + /* When writing the address table, we have to cope with the fact that + the addrmap iterator only provides the start of a region; we have to + wait until the next invocation to get the start of the next region. */ - slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT); - if (*slot == NULL) - *slot = ref_per_cu; + addrmap_index_data.objfile = objfile; + addrmap_index_data.addr_obstack = obstack; + addrmap_index_data.cu_index_htab = cu_index_htab; + addrmap_index_data.previous_valid = 0; + + addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker, + &addrmap_index_data); + + /* It's highly unlikely the last entry (end address = 0xff...ff) + is valid, but we should still handle it. + The end address is recorded as the start of the next region, but that + doesn't work here. To cope we pass 0xff...ff, this is a rare situation + anyway. */ + if (addrmap_index_data.previous_valid) + add_address_entry (objfile, obstack, + addrmap_index_data.previous_cu_start, (CORE_ADDR) -1, + addrmap_index_data.previous_cu_index); } -/* Subroutine of dwarf2_mark to pass to htab_traverse. - Set the mark field in every compilation unit in the - cache that we must keep because we are keeping CU. */ +/* Add a list of partial symbols to SYMTAB. */ -static int -dwarf2_mark_helper (void **slot, void *data) +static void +write_psymbols (struct mapped_symtab *symtab, + htab_t psyms_seen, + struct partial_symbol **psymp, + int count, + offset_type cu_index, + int is_static) { - struct dwarf2_per_cu_data *per_cu; + for (; count-- > 0; ++psymp) + { + void **slot, *lookup; - per_cu = (struct dwarf2_per_cu_data *) *slot; - if (per_cu->cu->mark) - return 1; - per_cu->cu->mark = 1; + if (SYMBOL_LANGUAGE (*psymp) == language_ada) + error (_("Ada is not currently supported by the index")); - if (per_cu->cu->dependencies != NULL) - htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL); + /* We only want to add a given psymbol once. However, we also + want to account for whether it is global or static. So, we + may add it twice, using slightly different values. */ + if (is_static) + { + uintptr_t val = 1 | (uintptr_t) *psymp; - return 1; + lookup = (void *) val; + } + else + lookup = *psymp; + + /* Only add a given psymbol once. */ + slot = htab_find_slot (psyms_seen, lookup, INSERT); + if (!*slot) + { + *slot = lookup; + add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index); + } + } } -/* Set the mark field in CU and in every other compilation unit in the - cache that we must keep because we are keeping CU. */ +/* Write the contents of an ("unfinished") obstack to FILE. Throw an + exception if there is an error. */ static void -dwarf2_mark (struct dwarf2_cu *cu) +write_obstack (FILE *file, struct obstack *obstack) { - if (cu->mark) - return; - cu->mark = 1; - if (cu->dependencies != NULL) - htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL); + if (fwrite (obstack_base (obstack), 1, obstack_object_size (obstack), + file) + != obstack_object_size (obstack)) + error (_("couldn't data write to file")); } +/* Unlink a file if the argument is not NULL. */ + static void -dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) +unlink_if_set (void *p) { - while (per_cu) - { - per_cu->cu->mark = 0; - per_cu = per_cu->cu->read_in_chain; - } + char **filename = p; + if (*filename) + unlink (*filename); } -/* Trivial hash function for partial_die_info: the hash value of a DIE - is its offset in .debug_info for this objfile. */ - -static hashval_t -partial_die_hash (const void *item) +/* A helper struct used when iterating over debug_types. */ +struct signatured_type_index_data { - const struct partial_die_info *part_die = item; - - return part_die->offset; -} + struct objfile *objfile; + struct mapped_symtab *symtab; + struct obstack *types_list; + htab_t psyms_seen; + int cu_index; +}; -/* Trivial comparison function for partial_die_info structures: two DIEs - are equal if they have the same offset. */ +/* A helper function that writes a single signatured_type to an + obstack. */ static int -partial_die_eq (const void *item_lhs, const void *item_rhs) +write_one_signatured_type (void **slot, void *d) { - const struct partial_die_info *part_die_lhs = item_lhs; - const struct partial_die_info *part_die_rhs = item_rhs; + struct signatured_type_index_data *info = d; + struct signatured_type *entry = (struct signatured_type *) *slot; + struct dwarf2_per_cu_data *per_cu = &entry->per_cu; + struct partial_symtab *psymtab = per_cu->v.psymtab; + gdb_byte val[8]; + + write_psymbols (info->symtab, + info->psyms_seen, + info->objfile->global_psymbols.list + + psymtab->globals_offset, + psymtab->n_global_syms, info->cu_index, + 0); + write_psymbols (info->symtab, + info->psyms_seen, + info->objfile->static_psymbols.list + + psymtab->statics_offset, + psymtab->n_static_syms, info->cu_index, + 1); + + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->offset); + obstack_grow (info->types_list, val, 8); + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset); + obstack_grow (info->types_list, val, 8); + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature); + obstack_grow (info->types_list, val, 8); + + ++info->cu_index; - return part_die_lhs->offset == part_die_rhs->offset; + return 1; } -static struct cmd_list_element *set_dwarf2_cmdlist; -static struct cmd_list_element *show_dwarf2_cmdlist; +/* A cleanup function for an htab_t. */ static void -set_dwarf2_cmd (char *args, int from_tty) +cleanup_htab (void *arg) { - help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout); + htab_delete (arg); } +/* Create an index file for OBJFILE in the directory DIR. */ + static void -show_dwarf2_cmd (char *args, int from_tty) +write_psymtabs_to_index (struct objfile *objfile, const char *dir) { - cmd_show_list (show_dwarf2_cmdlist, from_tty, ""); -} + struct cleanup *cleanup; + char *filename, *cleanup_filename; + struct obstack contents, addr_obstack, constant_pool, symtab_obstack; + struct obstack cu_list, types_cu_list; + int i; + FILE *out_file; + struct mapped_symtab *symtab; + offset_type val, size_of_contents, total_len; + struct stat st; + char buf[8]; + htab_t psyms_seen; + htab_t cu_index_htab; + struct psymtab_cu_index_map *psymtab_cu_index_map; + + if (!objfile->psymtabs) + return; + if (dwarf2_per_objfile->using_index) + error (_("Cannot use an index to create the index")); + + if (stat (objfile->name, &st) < 0) + perror_with_name (objfile->name); + + filename = concat (dir, SLASH_STRING, lbasename (objfile->name), + INDEX_SUFFIX, (char *) NULL); + cleanup = make_cleanup (xfree, filename); + + out_file = fopen (filename, "wb"); + if (!out_file) + error (_("Can't open `%s' for writing"), filename); + + cleanup_filename = filename; + make_cleanup (unlink_if_set, &cleanup_filename); + + symtab = create_mapped_symtab (); + make_cleanup (cleanup_mapped_symtab, symtab); + + obstack_init (&addr_obstack); + make_cleanup_obstack_free (&addr_obstack); + + obstack_init (&cu_list); + make_cleanup_obstack_free (&cu_list); + + obstack_init (&types_cu_list); + make_cleanup_obstack_free (&types_cu_list); + + psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer, + NULL, xcalloc, xfree); + make_cleanup (cleanup_htab, psyms_seen); + + /* While we're scanning CU's create a table that maps a psymtab pointer + (which is what addrmap records) to its index (which is what is recorded + in the index file). This will later be needed to write the address + table. */ + cu_index_htab = htab_create_alloc (100, + hash_psymtab_cu_index, + eq_psymtab_cu_index, + NULL, xcalloc, xfree); + make_cleanup (cleanup_htab, cu_index_htab); + psymtab_cu_index_map = (struct psymtab_cu_index_map *) + xmalloc (sizeof (struct psymtab_cu_index_map) + * dwarf2_per_objfile->n_comp_units); + make_cleanup (xfree, psymtab_cu_index_map); + + /* The CU list is already sorted, so we don't need to do additional + work here. Also, the debug_types entries do not appear in + all_comp_units, but only in their own hash table. */ + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { + struct dwarf2_per_cu_data *per_cu + = dwarf2_per_objfile->all_comp_units[i]; + struct partial_symtab *psymtab = per_cu->v.psymtab; + gdb_byte val[8]; + struct psymtab_cu_index_map *map; + void **slot; -/* If section described by INFO was mmapped, munmap it now. */ + write_psymbols (symtab, + psyms_seen, + objfile->global_psymbols.list + psymtab->globals_offset, + psymtab->n_global_syms, i, + 0); + write_psymbols (symtab, + psyms_seen, + objfile->static_psymbols.list + psymtab->statics_offset, + psymtab->n_static_syms, i, + 1); + + map = &psymtab_cu_index_map[i]; + map->psymtab = psymtab; + map->cu_index = i; + slot = htab_find_slot (cu_index_htab, map, INSERT); + gdb_assert (slot != NULL); + gdb_assert (*slot == NULL); + *slot = map; -static void -munmap_section_buffer (struct dwarf2_section_info *info) -{ - if (info->was_mmapped) + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->offset); + obstack_grow (&cu_list, val, 8); + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->length); + obstack_grow (&cu_list, val, 8); + } + + /* Dump the address map. */ + write_address_map (objfile, &addr_obstack, cu_index_htab); + + /* Write out the .debug_type entries, if any. */ + if (dwarf2_per_objfile->signatured_types) { -#ifdef HAVE_MMAP - intptr_t begin = (intptr_t) info->buffer; - intptr_t map_begin = begin & ~(pagesize - 1); - size_t map_length = info->size + begin - map_begin; + struct signatured_type_index_data sig_data; - gdb_assert (munmap ((void *) map_begin, map_length) == 0); -#else - /* Without HAVE_MMAP, we should never be here to begin with. */ - gdb_assert (0); -#endif + sig_data.objfile = objfile; + sig_data.symtab = symtab; + sig_data.types_list = &types_cu_list; + sig_data.psyms_seen = psyms_seen; + sig_data.cu_index = dwarf2_per_objfile->n_comp_units; + htab_traverse_noresize (dwarf2_per_objfile->signatured_types, + write_one_signatured_type, &sig_data); } + + obstack_init (&constant_pool); + make_cleanup_obstack_free (&constant_pool); + obstack_init (&symtab_obstack); + make_cleanup_obstack_free (&symtab_obstack); + write_hash_table (symtab, &symtab_obstack, &constant_pool); + + obstack_init (&contents); + make_cleanup_obstack_free (&contents); + size_of_contents = 6 * sizeof (offset_type); + total_len = size_of_contents; + + /* The version number. */ + val = MAYBE_SWAP (4); + obstack_grow (&contents, &val, sizeof (val)); + + /* The offset of the CU list from the start of the file. */ + val = MAYBE_SWAP (total_len); + obstack_grow (&contents, &val, sizeof (val)); + total_len += obstack_object_size (&cu_list); + + /* The offset of the types CU list from the start of the file. */ + val = MAYBE_SWAP (total_len); + obstack_grow (&contents, &val, sizeof (val)); + total_len += obstack_object_size (&types_cu_list); + + /* The offset of the address table from the start of the file. */ + val = MAYBE_SWAP (total_len); + obstack_grow (&contents, &val, sizeof (val)); + total_len += obstack_object_size (&addr_obstack); + + /* The offset of the symbol table from the start of the file. */ + val = MAYBE_SWAP (total_len); + obstack_grow (&contents, &val, sizeof (val)); + total_len += obstack_object_size (&symtab_obstack); + + /* The offset of the constant pool from the start of the file. */ + val = MAYBE_SWAP (total_len); + obstack_grow (&contents, &val, sizeof (val)); + total_len += obstack_object_size (&constant_pool); + + gdb_assert (obstack_object_size (&contents) == size_of_contents); + + write_obstack (out_file, &contents); + write_obstack (out_file, &cu_list); + write_obstack (out_file, &types_cu_list); + write_obstack (out_file, &addr_obstack); + write_obstack (out_file, &symtab_obstack); + write_obstack (out_file, &constant_pool); + + fclose (out_file); + + /* We want to keep the file, so we set cleanup_filename to NULL + here. See unlink_if_set. */ + cleanup_filename = NULL; + + do_cleanups (cleanup); } -/* munmap debug sections for OBJFILE, if necessary. */ +/* The mapped index file format is designed to be directly mmap()able + on any architecture. In most cases, a datum is represented using a + little-endian 32-bit integer value, called an offset_type. Big + endian machines must byte-swap the values before using them. + Exceptions to this rule are noted. The data is laid out such that + alignment is always respected. + + A mapped index consists of several sections. + + 1. The file header. This is a sequence of values, of offset_type + unless otherwise noted: + + [0] The version number, currently 4. Versions 1, 2 and 3 are + obsolete. + [1] The offset, from the start of the file, of the CU list. + [2] The offset, from the start of the file, of the types CU list. + Note that this section can be empty, in which case this offset will + be equal to the next offset. + [3] The offset, from the start of the file, of the address section. + [4] The offset, from the start of the file, of the symbol table. + [5] The offset, from the start of the file, of the constant pool. + + 2. The CU list. This is a sequence of pairs of 64-bit + little-endian values, sorted by the CU offset. The first element + in each pair is the offset of a CU in the .debug_info section. The + second element in each pair is the length of that CU. References + to a CU elsewhere in the map are done using a CU index, which is + just the 0-based index into this table. Note that if there are + type CUs, then conceptually CUs and type CUs form a single list for + the purposes of CU indices. + + 3. The types CU list. This is a sequence of triplets of 64-bit + little-endian values. In a triplet, the first value is the CU + offset, the second value is the type offset in the CU, and the + third value is the type signature. The types CU list is not + sorted. + + 4. The address section. The address section consists of a sequence + of address entries. Each address entry has three elements. + [0] The low address. This is a 64-bit little-endian value. + [1] The high address. This is a 64-bit little-endian value. + Like DW_AT_high_pc, the value is one byte beyond the end. + [2] The CU index. This is an offset_type value. + + 5. The symbol table. This is a hash table. The size of the hash + table is always a power of 2. The initial hash and the step are + currently defined by the `find_slot' function. + + Each slot in the hash table consists of a pair of offset_type + values. The first value is the offset of the symbol's name in the + constant pool. The second value is the offset of the CU vector in + the constant pool. + + If both values are 0, then this slot in the hash table is empty. + This is ok because while 0 is a valid constant pool index, it + cannot be a valid index for both a string and a CU vector. + + A string in the constant pool is stored as a \0-terminated string, + as you'd expect. + + A CU vector in the constant pool is a sequence of offset_type + values. The first value is the number of CU indices in the vector. + Each subsequent value is the index of a CU in the CU list. This + element in the hash table is used to indicate which CUs define the + symbol. + + 6. The constant pool. This is simply a bunch of bytes. It is + organized so that alignment is correct: CU vectors are stored + first, followed by strings. */ static void -dwarf2_per_objfile_free (struct objfile *objfile, void *d) +save_gdb_index_command (char *arg, int from_tty) { - struct dwarf2_per_objfile *data = d; + struct objfile *objfile; - /* This is sorted according to the order they're defined in to make it easier - to keep in sync. */ - munmap_section_buffer (&data->info); - munmap_section_buffer (&data->abbrev); - munmap_section_buffer (&data->line); - munmap_section_buffer (&data->loc); - munmap_section_buffer (&data->macinfo); - munmap_section_buffer (&data->str); - munmap_section_buffer (&data->ranges); - munmap_section_buffer (&data->types); - munmap_section_buffer (&data->frame); - munmap_section_buffer (&data->eh_frame); + if (!arg || !*arg) + error (_("usage: save gdb-index DIRECTORY")); + + ALL_OBJFILES (objfile) + { + struct stat st; + + /* If the objfile does not correspond to an actual file, skip it. */ + if (stat (objfile->name, &st) < 0) + continue; + + dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + if (dwarf2_per_objfile) + { + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + write_psymtabs_to_index (objfile, arg); + } + if (except.reason < 0) + exception_fprintf (gdb_stderr, except, + _("Error while writing index for `%s': "), + objfile->name); + } + } } + + int dwarf2_always_disassemble; static void show_dwarf2_always_disassemble (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Whether to always disassemble DWARF expressions is %s.\n"), + fprintf_filtered (file, + _("Whether to always disassemble " + "DWARF expressions is %s.\n"), + value); +} + +static void +show_check_physname (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Whether to check \"physname\" is %s.\n"), value); } @@ -12609,6 +16262,8 @@ void _initialize_dwarf2_read (void); void _initialize_dwarf2_read (void) { + struct cmd_list_element *c; + dwarf2_objfile_data_key = register_objfile_data_with_cleanup (NULL, dwarf2_per_objfile_free); @@ -12656,4 +16311,19 @@ The value is the maximum depth to print."), NULL, NULL, &setdebuglist, &showdebuglist); + + add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\ +Set cross-checking of \"physname\" code against demangler."), _("\ +Show cross-checking of \"physname\" code against demangler."), _("\ +When enabled, GDB's internal \"physname\" code is checked against\n\ +the demangler."), + NULL, show_check_physname, + &setdebuglist, &showdebuglist); + + c = add_cmd ("gdb-index", class_files, save_gdb_index_command, + _("\ +Save a gdb-index file.\n\ +Usage: save gdb-index DIRECTORY"), + &save_cmdlist); + set_cmd_completer (c, filename_completer); } diff --git a/contrib/gdb-7/gdb/elfread.c b/contrib/gdb-7/gdb/elfread.c index 8c00938777..226ce276fe 100644 --- a/contrib/gdb-7/gdb/elfread.c +++ b/contrib/gdb-7/gdb/elfread.c @@ -1,7 +1,7 @@ /* Read ELF (Executable and Linking Format) object files for GDB. Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -37,9 +37,19 @@ #include "complaints.h" #include "demangle.h" #include "psympriv.h" +#include "filenames.h" +#include "gdbtypes.h" +#include "value.h" +#include "infcall.h" +#include "gdbthread.h" +#include "regcache.h" extern void _initialize_elfread (void); +/* Forward declarations. */ +static const struct sym_fns elf_sym_fns_gdb_index; +static const struct sym_fns elf_sym_fns_lazy_psyms; + /* The struct elfinfo is available only during ELF symbol table and psymtab reading. It is destroyed at the completion of psymtab-reading. It's local to elf_symfile_read. */ @@ -53,6 +63,13 @@ struct elfinfo static void free_elfinfo (void *); +/* Minimal symbols located at the GOT entries for .plt - that is the real + pointer where the given entry will jump to. It gets updated by the real + function address during lazy ld.so resolving in the inferior. These + minimal symbols are indexed for -completion. */ + +#define SYMBOL_GOT_PLT_SUFFIX "@got.plt" + /* Locate the segments in ABFD. */ static struct symfile_segment_data * @@ -149,7 +166,7 @@ elf_symfile_segments (bfd *abfd) FIXME: The section names should not be hardwired strings (what should they be? I don't think most object file formats have enough - section flags to specify what kind of debug section it is + section flags to specify what kind of debug section it is. -kingdon). */ static void @@ -180,7 +197,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, { struct gdbarch *gdbarch = get_objfile_arch (objfile); - if (ms_type == mst_text || ms_type == mst_file_text) + if (ms_type == mst_text || ms_type == mst_file_text + || ms_type == mst_text_gnu_ifunc) address = gdbarch_smash_text_address (gdbarch, address); return prim_record_minimal_symbol_full (name, name_len, copy_name, address, @@ -246,7 +264,7 @@ elf_symtab_read (struct objfile *objfile, int type, if (sym->name == NULL || *sym->name == '\0') { /* Skip names that don't exist (shouldn't happen), or names - that are null strings (may happen). */ + that are null strings (may happen). */ continue; } @@ -275,7 +293,7 @@ elf_symtab_read (struct objfile *objfile, int type, of the corresponding entry in the procedure linkage table, plus the desired section offset. If its value is zero then the dynamic linker has to resolve - the symbol. We are unable to find any meaningful address + the symbol. We are unable to find any meaningful address for this symbol in the executable file, so we skip it. */ symaddr = sym->value; if (symaddr == 0) @@ -336,8 +354,8 @@ elf_symtab_read (struct objfile *objfile, int type, /* Select global/local/weak symbols. Note that bfd puts abs symbols in their own section, so all symbols we are - interested in will have a section. */ - /* Bfd symbols are section relative. */ + interested in will have a section. */ + /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; /* Relocate all non-absolute and non-TLS symbols by the section offset. */ @@ -348,7 +366,7 @@ elf_symtab_read (struct objfile *objfile, int type, } /* For non-absolute symbols, use the type of the section they are relative to, to intuit text/data. Bfd provides - no way of figuring this out for absolute symbols. */ + no way of figuring this out for absolute symbols. */ if (sym->section == &bfd_abs_section) { /* This is a hack to get the minimal symbol type @@ -376,7 +394,7 @@ elf_symtab_read (struct objfile *objfile, int type, } /* If it is an Irix dynamic symbol, skip section name - symbols, relocate all others by section offset. */ + symbols, relocate all others by section offset. */ if (ms_type != mst_abs) { if (sym->name[0] == '.') @@ -388,7 +406,10 @@ elf_symtab_read (struct objfile *objfile, int type, { if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { - ms_type = mst_text; + if (sym->flags & BSF_GNU_INDIRECT_FUNCTION) + ms_type = mst_text_gnu_ifunc; + else + ms_type = mst_text; } else if ((sym->name[0] == '.' && sym->name[1] == 'L') || ((sym->flags & BSF_LOCAL) @@ -457,8 +478,7 @@ elf_symtab_read (struct objfile *objfile, int type, need to allocate max_index aadditional elements. */ size = (sizeof (struct stab_section_info) - + (sizeof (CORE_ADDR) - * max_index)); + + (sizeof (CORE_ADDR) * max_index)); sectinfo = (struct stab_section_info *) xmalloc (size); memset (sectinfo, 0, size); @@ -466,7 +486,8 @@ elf_symtab_read (struct objfile *objfile, int type, if (filesym == NULL) { complaint (&symfile_complaints, - _("elf/stab section information %s without a preceding file symbol"), + _("elf/stab section information %s " + "without a preceding file symbol"), sym->name); } else @@ -477,7 +498,8 @@ elf_symtab_read (struct objfile *objfile, int type, } if (sectinfo->sections[special_local_sect] != 0) complaint (&symfile_complaints, - _("duplicated elf/stab section information for %s"), + _("duplicated elf/stab section " + "information for %s"), sectinfo->filename); /* BFD symbols are section relative. */ symaddr = sym->value + sym->section->vma; @@ -513,7 +535,7 @@ elf_symtab_read (struct objfile *objfile, int type, hob with actions like finding what function the PC is in. Ignore them if they aren't text, data, or bss. */ /* ms_type = mst_unknown; */ - continue; /* Skip this symbol. */ + continue; /* Skip this symbol. */ } msym = record_minimal_symbol (sym->name, strlen (sym->name), copy_names, symaddr, @@ -569,6 +591,468 @@ elf_symtab_read (struct objfile *objfile, int type, } } +/* Build minimal symbols named `function@got.plt' (see SYMBOL_GOT_PLT_SUFFIX) + for later look ups of which function to call when user requests + a STT_GNU_IFUNC function. As the STT_GNU_IFUNC type is found at the target + library defining `function' we cannot yet know while reading OBJFILE which + of the SYMBOL_GOT_PLT_SUFFIX entries will be needed and later + DYN_SYMBOL_TABLE is no longer easily available for OBJFILE. */ + +static void +elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) +{ + bfd *obfd = objfile->obfd; + const struct elf_backend_data *bed = get_elf_backend_data (obfd); + asection *plt, *relplt, *got_plt; + unsigned u; + int plt_elf_idx; + bfd_size_type reloc_count, reloc; + char *string_buffer = NULL; + size_t string_buffer_size = 0; + struct cleanup *back_to; + struct gdbarch *gdbarch = objfile->gdbarch; + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + size_t ptr_size = TYPE_LENGTH (ptr_type); + + if (objfile->separate_debug_objfile_backlink) + return; + + plt = bfd_get_section_by_name (obfd, ".plt"); + if (plt == NULL) + return; + plt_elf_idx = elf_section_data (plt)->this_idx; + + got_plt = bfd_get_section_by_name (obfd, ".got.plt"); + if (got_plt == NULL) + return; + + /* This search algorithm is from _bfd_elf_canonicalize_dynamic_reloc. */ + for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next) + if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx + && (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL + || elf_section_data (relplt)->this_hdr.sh_type == SHT_RELA)) + break; + if (relplt == NULL) + return; + + if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) + return; + + back_to = make_cleanup (free_current_contents, &string_buffer); + + reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize; + for (reloc = 0; reloc < reloc_count; reloc++) + { + const char *name, *name_got_plt; + struct minimal_symbol *msym; + CORE_ADDR address; + const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); + size_t name_len; + + name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr); + name_len = strlen (name); + address = relplt->relocation[reloc].address; + + /* Does the pointer reside in the .got.plt section? */ + if (!(bfd_get_section_vma (obfd, got_plt) <= address + && address < bfd_get_section_vma (obfd, got_plt) + + bfd_get_section_size (got_plt))) + continue; + + /* We cannot check if NAME is a reference to mst_text_gnu_ifunc as in + OBJFILE the symbol is undefined and the objfile having NAME defined + may not yet have been loaded. */ + + if (string_buffer_size < name_len + got_suffix_len) + { + string_buffer_size = 2 * (name_len + got_suffix_len); + string_buffer = xrealloc (string_buffer, string_buffer_size); + } + memcpy (string_buffer, name, name_len); + memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX, + got_suffix_len); + + msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len, + 1, address, mst_slot_got_plt, got_plt, + objfile); + if (msym) + MSYMBOL_SIZE (msym) = ptr_size; + } + + do_cleanups (back_to); +} + +/* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked. */ + +static const struct objfile_data *elf_objfile_gnu_ifunc_cache_data; + +/* Map function names to CORE_ADDR in elf_objfile_gnu_ifunc_cache_data. */ + +struct elf_gnu_ifunc_cache +{ + /* This is always a function entry address, not a function descriptor. */ + CORE_ADDR addr; + + char name[1]; +}; + +/* htab_hash for elf_objfile_gnu_ifunc_cache_data. */ + +static hashval_t +elf_gnu_ifunc_cache_hash (const void *a_voidp) +{ + const struct elf_gnu_ifunc_cache *a = a_voidp; + + return htab_hash_string (a->name); +} + +/* htab_eq for elf_objfile_gnu_ifunc_cache_data. */ + +static int +elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp) +{ + const struct elf_gnu_ifunc_cache *a = a_voidp; + const struct elf_gnu_ifunc_cache *b = b_voidp; + + return strcmp (a->name, b->name) == 0; +} + +/* Record the target function address of a STT_GNU_IFUNC function NAME is the + function entry address ADDR. Return 1 if NAME and ADDR are considered as + valid and therefore they were successfully recorded, return 0 otherwise. + + Function does not expect a duplicate entry. Use + elf_gnu_ifunc_resolve_by_cache first to check if the entry for NAME already + exists. */ + +static int +elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) +{ + struct minimal_symbol *msym; + asection *sect; + struct objfile *objfile; + htab_t htab; + struct elf_gnu_ifunc_cache entry_local, *entry_p; + void **slot; + + msym = lookup_minimal_symbol_by_pc (addr); + if (msym == NULL) + return 0; + if (SYMBOL_VALUE_ADDRESS (msym) != addr) + return 0; + /* minimal symbols have always SYMBOL_OBJ_SECTION non-NULL. */ + sect = SYMBOL_OBJ_SECTION (msym)->the_bfd_section; + objfile = SYMBOL_OBJ_SECTION (msym)->objfile; + + /* If .plt jumps back to .plt the symbol is still deferred for later + resolution and it has no use for GDB. Besides ".text" this symbol can + reside also in ".opd" for ppc64 function descriptor. */ + if (strcmp (bfd_get_section_name (objfile->obfd, sect), ".plt") == 0) + return 0; + + htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); + if (htab == NULL) + { + htab = htab_create_alloc_ex (1, elf_gnu_ifunc_cache_hash, + elf_gnu_ifunc_cache_eq, + NULL, &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + set_objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data, htab); + } + + entry_local.addr = addr; + obstack_grow (&objfile->objfile_obstack, &entry_local, + offsetof (struct elf_gnu_ifunc_cache, name)); + obstack_grow_str0 (&objfile->objfile_obstack, name); + entry_p = obstack_finish (&objfile->objfile_obstack); + + slot = htab_find_slot (htab, entry_p, INSERT); + if (*slot != NULL) + { + struct elf_gnu_ifunc_cache *entry_found_p = *slot; + struct gdbarch *gdbarch = objfile->gdbarch; + + if (entry_found_p->addr != addr) + { + /* This case indicates buggy inferior program, the resolved address + should never change. */ + + warning (_("gnu-indirect-function \"%s\" has changed its resolved " + "function_address from %s to %s"), + name, paddress (gdbarch, entry_found_p->addr), + paddress (gdbarch, addr)); + } + + /* New ENTRY_P is here leaked/duplicate in the OBJFILE obstack. */ + } + *slot = entry_p; + + return 1; +} + +/* Try to find the target resolved function entry address of a STT_GNU_IFUNC + function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P + is not NULL) and the function returns 1. It returns 0 otherwise. + + Only the elf_objfile_gnu_ifunc_cache_data hash table is searched by this + function. */ + +static int +elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p) +{ + struct objfile *objfile; + + ALL_PSPACE_OBJFILES (current_program_space, objfile) + { + htab_t htab; + struct elf_gnu_ifunc_cache *entry_p; + void **slot; + + htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); + if (htab == NULL) + continue; + + entry_p = alloca (sizeof (*entry_p) + strlen (name)); + strcpy (entry_p->name, name); + + slot = htab_find_slot (htab, entry_p, NO_INSERT); + if (slot == NULL) + continue; + entry_p = *slot; + gdb_assert (entry_p != NULL); + + if (addr_p) + *addr_p = entry_p->addr; + return 1; + } + + return 0; +} + +/* Try to find the target resolved function entry address of a STT_GNU_IFUNC + function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P + is not NULL) and the function returns 1. It returns 0 otherwise. + + Only the SYMBOL_GOT_PLT_SUFFIX locations are searched by this function. + elf_gnu_ifunc_resolve_by_cache must have been already called for NAME to + prevent cache entries duplicates. */ + +static int +elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) +{ + char *name_got_plt; + struct objfile *objfile; + const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); + + name_got_plt = alloca (strlen (name) + got_suffix_len + 1); + sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name); + + ALL_PSPACE_OBJFILES (current_program_space, objfile) + { + bfd *obfd = objfile->obfd; + struct gdbarch *gdbarch = objfile->gdbarch; + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + size_t ptr_size = TYPE_LENGTH (ptr_type); + CORE_ADDR pointer_address, addr; + asection *plt; + gdb_byte *buf = alloca (ptr_size); + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol (name_got_plt, NULL, objfile); + if (msym == NULL) + continue; + if (MSYMBOL_TYPE (msym) != mst_slot_got_plt) + continue; + pointer_address = SYMBOL_VALUE_ADDRESS (msym); + + plt = bfd_get_section_by_name (obfd, ".plt"); + if (plt == NULL) + continue; + + if (MSYMBOL_SIZE (msym) != ptr_size) + continue; + if (target_read_memory (pointer_address, buf, ptr_size) != 0) + continue; + addr = extract_typed_address (buf, ptr_type); + addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, + ¤t_target); + + if (addr_p) + *addr_p = addr; + if (elf_gnu_ifunc_record_cache (name, addr)) + return 1; + } + + return 0; +} + +/* Try to find the target resolved function entry address of a STT_GNU_IFUNC + function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P + is not NULL) and the function returns 1. It returns 0 otherwise. + + Both the elf_objfile_gnu_ifunc_cache_data hash table and + SYMBOL_GOT_PLT_SUFFIX locations are searched by this function. */ + +static int +elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p) +{ + if (elf_gnu_ifunc_resolve_by_cache (name, addr_p)) + return 1; + + if (elf_gnu_ifunc_resolve_by_got (name, addr_p)) + return 1; + + return 0; +} + +/* Call STT_GNU_IFUNC - a function returning addresss of a real function to + call. PC is theSTT_GNU_IFUNC resolving function entry. The value returned + is the entry point of the resolved STT_GNU_IFUNC target function to call. + */ + +static CORE_ADDR +elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + char *name_at_pc; + CORE_ADDR start_at_pc, address; + struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; + struct value *function, *address_val; + + /* Try first any non-intrusive methods without an inferior call. */ + + if (find_pc_partial_function (pc, &name_at_pc, &start_at_pc, NULL) + && start_at_pc == pc) + { + if (elf_gnu_ifunc_resolve_name (name_at_pc, &address)) + return address; + } + else + name_at_pc = NULL; + + function = allocate_value (func_func_type); + set_value_address (function, pc); + + /* STT_GNU_IFUNC resolver functions have no parameters. FUNCTION is the + function entry address. ADDRESS may be a function descriptor. */ + + address_val = call_function_by_hand (function, 0, NULL); + address = value_as_address (address_val); + address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, + ¤t_target); + + if (name_at_pc) + elf_gnu_ifunc_record_cache (name_at_pc, address); + + return address; +} + +/* Handle inferior hit of bp_gnu_ifunc_resolver, see its definition. */ + +static void +elf_gnu_ifunc_resolver_stop (struct breakpoint *b) +{ + struct breakpoint *b_return; + struct frame_info *prev_frame = get_prev_frame (get_current_frame ()); + struct frame_id prev_frame_id = get_stack_frame_id (prev_frame); + CORE_ADDR prev_pc = get_frame_pc (prev_frame); + int thread_id = pid_to_thread_id (inferior_ptid); + + gdb_assert (b->type == bp_gnu_ifunc_resolver); + + for (b_return = b->related_breakpoint; b_return != b; + b_return = b_return->related_breakpoint) + { + gdb_assert (b_return->type == bp_gnu_ifunc_resolver_return); + gdb_assert (b_return->loc != NULL && b_return->loc->next == NULL); + gdb_assert (frame_id_p (b_return->frame_id)); + + if (b_return->thread == thread_id + && b_return->loc->requested_address == prev_pc + && frame_id_eq (b_return->frame_id, prev_frame_id)) + break; + } + + if (b_return == b) + { + struct symtab_and_line sal; + + /* No need to call find_pc_line for symbols resolving as this is only + a helper breakpointer never shown to the user. */ + + init_sal (&sal); + sal.pspace = current_inferior ()->pspace; + sal.pc = prev_pc; + sal.section = find_pc_overlay (sal.pc); + sal.explicit_pc = 1; + b_return = set_momentary_breakpoint (get_frame_arch (prev_frame), sal, + prev_frame_id, + bp_gnu_ifunc_resolver_return); + + /* Add new b_return to the ring list b->related_breakpoint. */ + gdb_assert (b_return->related_breakpoint == b_return); + b_return->related_breakpoint = b->related_breakpoint; + b->related_breakpoint = b_return; + } +} + +/* Handle inferior hit of bp_gnu_ifunc_resolver_return, see its definition. */ + +static void +elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) +{ + struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); + struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; + struct type *value_type = TYPE_TARGET_TYPE (func_func_type); + struct regcache *regcache = get_thread_regcache (inferior_ptid); + struct value *value; + CORE_ADDR resolved_address, resolved_pc; + struct symtab_and_line sal; + struct symtabs_and_lines sals, sals_end; + + gdb_assert (b->type == bp_gnu_ifunc_resolver_return); + + value = allocate_value (value_type); + gdbarch_return_value (gdbarch, func_func_type, value_type, regcache, + value_contents_raw (value), NULL); + resolved_address = value_as_address (value); + resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, + resolved_address, + ¤t_target); + + while (b->related_breakpoint != b) + { + struct breakpoint *b_next = b->related_breakpoint; + + switch (b->type) + { + case bp_gnu_ifunc_resolver: + break; + case bp_gnu_ifunc_resolver_return: + delete_breakpoint (b); + break; + default: + internal_error (__FILE__, __LINE__, + _("handle_inferior_event: Invalid " + "gnu-indirect-function breakpoint type %d"), + (int) b->type); + } + b = b_next; + } + gdb_assert (b->type == bp_gnu_ifunc_resolver); + + gdb_assert (current_program_space == b->pspace); + elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc); + + sal = find_pc_line (resolved_pc, 0); + sals.nelts = 1; + sals.sals = &sal; + sals_end.nelts = 0; + + b->type = bp_breakpoint; + update_breakpoint_locations (b, sals, sals_end); +} + struct build_id { size_t size; @@ -614,7 +1098,8 @@ build_id_verify (const char *filename, struct build_id *check) warning (_("File \"%s\" has no build-id, file skipped"), filename); else if (found->size != check->size || memcmp (found->data, check->data, found->size) != 0) - warning (_("File \"%s\" has a different build-id, file skipped"), filename); + warning (_("File \"%s\" has a different build-id, file skipped"), + filename); else retval = 1; @@ -698,7 +1183,8 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) build_id_name = build_id_to_debug_filename (build_id); xfree (build_id); /* Prevent looping on a stripped .debug file. */ - if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0) + if (build_id_name != NULL + && filename_cmp (build_id_name, objfile->name) == 0) { warning (_("\"%s\": separate debug info file has no debug info"), build_id_name); @@ -753,19 +1239,22 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) memset ((char *) &ei, 0, sizeof (ei)); - /* Allocate struct to keep track of the symfile */ + /* Allocate struct to keep track of the symfile. */ objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *) xmalloc (sizeof (struct dbx_symfile_info)); - memset ((char *) objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info)); + memset ((char *) objfile->deprecated_sym_stab_info, + 0, sizeof (struct dbx_symfile_info)); make_cleanup (free_elfinfo, (void *) objfile); - /* Process the normal ELF symbol table first. This may write some - chain of info into the dbx_symfile_info in objfile->deprecated_sym_stab_info, - which can later be used by elfstab_offset_sections. */ + /* Process the normal ELF symbol table first. This may write some + chain of info into the dbx_symfile_info in + objfile->deprecated_sym_stab_info, which can later be used by + elfstab_offset_sections. */ storage_needed = bfd_get_symtab_upper_bound (objfile->obfd); if (storage_needed < 0) - error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd), + error (_("Can't read symbols from %s: %s"), + bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); if (storage_needed > 0) @@ -775,7 +1264,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table); if (symcount < 0) - error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd), + error (_("Can't read symbols from %s: %s"), + bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0); @@ -787,16 +1277,25 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) if (storage_needed > 0) { - dyn_symbol_table = (asymbol **) xmalloc (storage_needed); - make_cleanup (xfree, dyn_symbol_table); + /* Memory gets permanently referenced from ABFD after + bfd_get_synthetic_symtab so it must not get freed before ABFD gets. + It happens only in the case when elf_slurp_reloc_table sees + asection->relocation NULL. Determining which section is asection is + done by _bfd_elf_get_synthetic_symtab which is all a bfd + implementation detail, though. */ + + dyn_symbol_table = bfd_alloc (abfd, storage_needed); dynsymcount = bfd_canonicalize_dynamic_symtab (objfile->obfd, dyn_symbol_table); if (dynsymcount < 0) - error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd), + error (_("Can't read symbols from %s: %s"), + bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0); + + elf_rel_plt_read (objfile, dyn_symbol_table); } /* Add synthetic symbols - for instance, names for any PLT entries. */ @@ -814,7 +1313,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) for (i = 0; i < synthcount; i++) synth_symbol_table[i] = synthsyms + i; make_cleanup (xfree, synth_symbol_table); - elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table, 1); + elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, + synth_symbol_table, 1); } /* Install any minimal symbols that have been collected as the current @@ -827,9 +1327,9 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) do_cleanups (back_to); /* Now process debugging information, which is contained in - special ELF sections. */ + special ELF sections. */ - /* We first have to find them... */ + /* We first have to find them... */ bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei); /* ELF debugging information is inserted into the psymtab in the @@ -842,7 +1342,7 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) and .debug_info (DWARF2) sections then .mdebug is inserted first (searched last) and DWARF2 is inserted last (searched first). If we don't do this then the XCOFF info is found first - for code in - an included file XCOFF info is useless. */ + an included file XCOFF info is useless. */ if (ei.mdebugsect) { @@ -869,16 +1369,30 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) str_sect->filepos, bfd_section_size (abfd, str_sect)); } + if (dwarf2_has_info (objfile)) { - /* DWARF 2 sections */ - dwarf2_build_psymtabs (objfile); + /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF debug + information present in OBJFILE. If there is such debug info present + never use .gdb_index. */ + + if (!objfile_has_partial_symbols (objfile) + && dwarf2_initialize_objfile (objfile)) + objfile->sf = &elf_sym_fns_gdb_index; + else + { + /* It is ok to do this even if the stabs reader made some + partial symbols, because OBJF_PSYMTABS_READ has not been + set, and so our lazy reader function will still be called + when needed. */ + objfile->sf = &elf_sym_fns_lazy_psyms; + } } - - /* If the file has its own symbol tables it has no separate debug info. - `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS. - `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */ - if (!objfile_has_partial_symbols (objfile)) + /* If the file has its own symbol tables it has no separate debug + info. `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to + SYMTABS/PSYMTABS. `.gnu_debuglink' may no longer be present with + `.note.gnu.build-id'. */ + else if (!objfile_has_partial_symbols (objfile)) { char *debugfile; @@ -897,6 +1411,15 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) } } +/* Callback to lazily read psymtabs. */ + +static void +read_psyms (struct objfile *objfile) +{ + if (dwarf2_has_info (objfile)) + dwarf2_build_psymtabs (objfile); +} + /* This cleans up the objfile's deprecated_sym_stab_info pointer, and the chain of stab_section_info's, that might be dangling from it. */ @@ -924,7 +1447,8 @@ free_elfinfo (void *objp) file is specified (not just adding some symbols from another file, e.g. a shared library). - We reinitialize buildsym, since we may be reading stabs from an ELF file. */ + We reinitialize buildsym, since we may be reading stabs from an ELF + file. */ static void elf_new_init (struct objfile *ignore) @@ -936,7 +1460,7 @@ elf_new_init (struct objfile *ignore) /* Perform any local cleanups required when we are done with a particular objfile. I.E, we are in the process of discarding all symbol information for an objfile, freeing up all memory held for it, and unlinking the - objfile struct from the global list of known objfiles. */ + objfile struct from the global list of known objfiles. */ static void elf_symfile_finish (struct objfile *objfile) @@ -956,7 +1480,7 @@ elf_symfile_finish (struct objfile *objfile) a pointer to "private data" which we can fill with goodies. For now at least, we have nothing in particular to do, so this function is - just a stub. */ + just a stub. */ static void elf_symfile_init (struct objfile *objfile) @@ -978,25 +1502,23 @@ elf_symfile_init (struct objfile *objfile) void elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) { - char *filename = pst->filename; + const char *filename = pst->filename; struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info; struct stab_section_info *maybe = dbx->stab_section_info; struct stab_section_info *questionable = 0; int i; - char *p; /* The ELF symbol info doesn't include path names, so strip the path (if any) from the psymtab filename. */ - while (0 != (p = strchr (filename, '/'))) - filename = p + 1; + filename = lbasename (filename); /* FIXME: This linear search could speed up significantly if it was chained in the right order to match how we search it, - and if we unchained when we found a match. */ + and if we unchained when we found a match. */ for (; maybe; maybe = maybe->next) { if (filename[0] == maybe->filename[0] - && strcmp (filename, maybe->filename) == 0) + && filename_cmp (filename, maybe->filename) == 0) { /* We found a match. But there might be several source files (from different directories) with the same name. */ @@ -1009,7 +1531,8 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) if (maybe == 0 && questionable != 0) { complaint (&symfile_complaints, - _("elf/stab section information questionable for %s"), filename); + _("elf/stab section information questionable for %s"), + filename); maybe = questionable; } @@ -1033,24 +1556,71 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) /* Register that we are able to handle ELF object file formats. */ -static struct sym_fns elf_sym_fns = +static const struct sym_fns elf_sym_fns = { bfd_target_elf_flavour, - elf_new_init, /* sym_new_init: init anything gbl to entire symtab */ - elf_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - elf_symfile_read, /* sym_read: read a symbol file into symtab */ - elf_symfile_finish, /* sym_finish: finished with file, cleanup */ - default_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */ - elf_symfile_segments, /* sym_segments: Get segment information from - a file. */ - NULL, /* sym_read_linetable */ - default_symfile_relocate, /* sym_relocate: Relocate a debug section. */ - &psym_functions, - NULL /* next: pointer to next struct sym_fns */ + elf_new_init, /* init anything gbl to entire symtab */ + elf_symfile_init, /* read initial info, setup for sym_read() */ + elf_symfile_read, /* read a symbol file into symtab */ + NULL, /* sym_read_psymbols */ + elf_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* Translate ext. to int. relocation */ + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &psym_functions +}; + +/* The same as elf_sym_fns, but not registered and lazily reads + psymbols. */ + +static const struct sym_fns elf_sym_fns_lazy_psyms = +{ + bfd_target_elf_flavour, + elf_new_init, /* init anything gbl to entire symtab */ + elf_symfile_init, /* read initial info, setup for sym_read() */ + elf_symfile_read, /* read a symbol file into symtab */ + read_psyms, /* sym_read_psymbols */ + elf_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* Translate ext. to int. relocation */ + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &psym_functions +}; + +/* The same as elf_sym_fns, but not registered and uses the + DWARF-specific GNU index rather than psymtab. */ +static const struct sym_fns elf_sym_fns_gdb_index = +{ + bfd_target_elf_flavour, + elf_new_init, /* init anything gbl to entire symab */ + elf_symfile_init, /* read initial info, setup for sym_red() */ + elf_symfile_read, /* read a symbol file into symtab */ + NULL, /* sym_read_psymbols */ + elf_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* Translate ext. to int. relocatin */ + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &dwarf2_gdb_index_functions +}; + +/* STT_GNU_IFUNC resolver vector to be installed to gnu_ifunc_fns_p. */ + +static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = +{ + elf_gnu_ifunc_resolve_addr, + elf_gnu_ifunc_resolve_name, + elf_gnu_ifunc_resolver_stop, + elf_gnu_ifunc_resolver_return_stop }; void _initialize_elfread (void) { add_symtab_fns (&elf_sym_fns); + + elf_objfile_gnu_ifunc_cache_data = register_objfile_data (); + gnu_ifunc_fns_p = &elf_gnu_ifunc_fns; } diff --git a/contrib/gdb-7/gdb/environ.c b/contrib/gdb-7/gdb/environ.c index ebd6431801..62d23e6d4f 100644 --- a/contrib/gdb-7/gdb/environ.c +++ b/contrib/gdb-7/gdb/environ.c @@ -1,7 +1,7 @@ /* environ.c -- library for manipulating environments for GNU. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 2000, 2005 - 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -175,7 +175,7 @@ unset_in_environ (struct gdb_environ *e, char *var) xfree (s); /* Walk through the vector, shuffling args down by one, including the NULL terminator. Can't use memcpy() here since the regions - overlap, and memmove() might not be available. */ + overlap, and memmove() might not be available. */ while ((vector[0] = vector[1]) != NULL) { vector++; diff --git a/contrib/gdb-7/gdb/environ.h b/contrib/gdb-7/gdb/environ.h index cf8b26bcbb..7a9347848c 100644 --- a/contrib/gdb-7/gdb/environ.h +++ b/contrib/gdb-7/gdb/environ.h @@ -1,5 +1,5 @@ /* Header for environment manipulation library. - Copyright (C) 1989, 1992, 2000, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 1989, 1992, 2000, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify diff --git a/contrib/gdb-7/gdb/eval.c b/contrib/gdb-7/gdb/eval.c index ff17c34018..bbc7b8a71f 100644 --- a/contrib/gdb-7/gdb/eval.c +++ b/contrib/gdb-7/gdb/eval.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -27,8 +27,8 @@ #include "expression.h" #include "target.h" #include "frame.h" -#include "language.h" /* For CAST_IS_CONVERSION */ -#include "f-lang.h" /* for array bound stuff */ +#include "language.h" /* For CAST_IS_CONVERSION. */ +#include "f-lang.h" /* For array bound stuff. */ #include "cp-abi.h" #include "infcall.h" #include "objc-lang.h" @@ -52,7 +52,7 @@ /* This is defined in valops.c */ extern int overload_resolution; -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static struct value *evaluate_subexp_for_sizeof (struct expression *, int *); @@ -93,24 +93,8 @@ parse_and_eval_address (char *exp) return addr; } -/* Like parse_and_eval_address but takes a pointer to a char * variable - and advanced that variable across the characters parsed. */ - -CORE_ADDR -parse_and_eval_address_1 (char **expptr) -{ - struct expression *expr = parse_exp_1 (expptr, (struct block *) 0, 0); - CORE_ADDR addr; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); - - addr = value_as_address (evaluate_expression (expr)); - do_cleanups (old_chain); - return addr; -} - /* Like parse_and_eval_address, but treats the value of the expression - as an integer, not an address, returns a LONGEST, not a CORE_ADDR */ + as an integer, not an address, returns a LONGEST, not a CORE_ADDR. */ LONGEST parse_and_eval_long (char *exp) { @@ -288,7 +272,7 @@ extract_field_op (struct expression *exp, int *subexp) } /* If the next expression is an OP_LABELED, skips past it, - returning the label. Otherwise, does nothing and returns NULL. */ + returning the label. Otherwise, does nothing and returns NULL. */ static char * get_label (struct expression *exp, int *pos) @@ -329,7 +313,7 @@ evaluate_struct_tuple (struct value *struct_val, int bitpos, bitsize; bfd_byte *addr; - /* Skip past the labels, and count them. */ + /* Skip past the labels, and count them. */ while (get_label (exp, pos) != NULL) nlabels++; @@ -390,7 +374,7 @@ evaluate_struct_tuple (struct value *struct_val, } else { - /* Unlabelled tuple element - go to next field. */ + /* Unlabelled tuple element - go to next field. */ if (variantno >= 0) { subfieldno++; @@ -425,15 +409,15 @@ evaluate_struct_tuple (struct value *struct_val, The value fieldno is the index of the top-level (normal or anonymous union) field in struct_field, while the value subfieldno is the index of the actual real (named inner) field - in substruct_type. */ + in substruct_type. */ field_type = TYPE_FIELD_TYPE (substruct_type, subfieldno); if (val == 0) val = evaluate_subexp (field_type, exp, pos, noside); - /* Now actually set the field in struct_val. */ + /* Now actually set the field in struct_val. */ - /* Assign val to field fieldno. */ + /* Assign val to field fieldno. */ if (value_type (val) != field_type) val = value_cast (field_type, val); @@ -603,6 +587,7 @@ binop_promote (const struct language_defn *language, struct gdbarch *gdbarch, case language_cplus: case language_asm: case language_objc: + case language_opencl: /* No promotion required. */ break; @@ -690,7 +675,24 @@ binop_promote (const struct language_defn *language, struct gdbarch *gdbarch, : builtin->builtin_long_long); } break; - + case language_opencl: + if (result_len <= TYPE_LENGTH (lookup_signed_typename + (language, gdbarch, "int"))) + { + promoted_type = + (unsigned_operation + ? lookup_unsigned_typename (language, gdbarch, "int") + : lookup_signed_typename (language, gdbarch, "int")); + } + else if (result_len <= TYPE_LENGTH (lookup_signed_typename + (language, gdbarch, "long"))) + { + promoted_type = + (unsigned_operation + ? lookup_unsigned_typename (language, gdbarch, "long") + : lookup_signed_typename (language, gdbarch,"long")); + } + break; default: /* For other languages the result type is unchanged from gdb version 6.7 for backward compatibility. @@ -736,7 +738,7 @@ ptrmath_type_p (const struct language_defn *lang, struct type *type) return 1; case TYPE_CODE_ARRAY: - return lang->c_style_arrays; + return TYPE_VECTOR (type) ? 0 : lang->c_style_arrays; default: return 0; @@ -834,7 +836,7 @@ evaluate_subexp_standard (struct type *expect_type, We need a full value object returned here for whatis_exp () to call evaluate_type () and then pass the full value to value_rtti_target_type () if we are dealing with a pointer - or reference to a base class and print object is on. */ + or reference to a base class and print object is on. */ { volatile struct gdb_exception except; @@ -849,7 +851,8 @@ evaluate_subexp_standard (struct type *expect_type, if (except.reason < 0) { if (noside == EVAL_AVOID_SIDE_EFFECTS) - ret = value_zero (SYMBOL_TYPE (exp->elts[pc + 2].symbol), not_lval); + ret = value_zero (SYMBOL_TYPE (exp->elts[pc + 2].symbol), + not_lval); else throw_exception (except); } @@ -908,7 +911,8 @@ evaluate_subexp_standard (struct type *expect_type, type = language_string_char_type (exp->language_defn, exp->gdbarch); return value_string (&exp->elts[pc + 2].string, tem, type); - case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */ + case OP_OBJC_NSSTRING: /* Objective C Foundation Class + NSString constant. */ tem = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); if (noside == EVAL_SKIP) @@ -984,7 +988,7 @@ evaluate_subexp_standard (struct type *expect_type, else { if (index > high_bound) - /* to avoid memory corruption */ + /* To avoid memory corruption. */ error (_("Too many array elements")); memcpy (value_contents_raw (array) + (index - low_bound) * element_size, @@ -1005,7 +1009,7 @@ evaluate_subexp_standard (struct type *expect_type, struct type *check_type = element_type; LONGEST low_bound, high_bound; - /* get targettype of elementtype */ + /* Get targettype of elementtype. */ while (TYPE_CODE (check_type) == TYPE_CODE_RANGE || TYPE_CODE (check_type) == TYPE_CODE_TYPEDEF) check_type = TYPE_TARGET_TYPE (check_type); @@ -1035,9 +1039,9 @@ evaluate_subexp_standard (struct type *expect_type, range_low_type = range_high_type = value_type (elem_val); range_low = range_high = value_as_long (elem_val); } - /* check types of elements to avoid mixture of elements from + /* Check types of elements to avoid mixture of elements from different types. Also check if type of element is "compatible" - with element type of powerset */ + with element type of powerset. */ if (TYPE_CODE (range_low_type) == TYPE_CODE_RANGE) range_low_type = TYPE_TARGET_TYPE (range_low_type); if (TYPE_CODE (range_high_type) == TYPE_CODE_RANGE) @@ -1045,7 +1049,7 @@ evaluate_subexp_standard (struct type *expect_type, if ((TYPE_CODE (range_low_type) != TYPE_CODE (range_high_type)) || (TYPE_CODE (range_low_type) == TYPE_CODE_ENUM && (range_low_type != range_high_type))) - /* different element modes */ + /* different element modes. */ error (_("POWERSET tuple elements of different mode")); if ((TYPE_CODE (check_type) != TYPE_CODE (range_low_type)) || (TYPE_CODE (check_type) == TYPE_CODE_ENUM @@ -1076,7 +1080,8 @@ evaluate_subexp_standard (struct type *expect_type, argvec = (struct value **) alloca (sizeof (struct value *) * nargs); for (tem = 0; tem < nargs; tem++) { - /* Ensure that array expressions are coerced into pointer objects. */ + /* Ensure that array expressions are coerced into pointer + objects. */ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); } if (noside == EVAL_SKIP) @@ -1193,7 +1198,7 @@ evaluate_subexp_standard (struct type *expect_type, to lookup the symbol information for the method. If we can't find any symbol information, then we'll use these to call the method, otherwise we can call the method - directly. The msg_send_stret function is used in the special + directly. The msg_send_stret function is used in the special case of a method that returns a structure (Apple runtime only). */ if (gnu_runtime) @@ -1216,15 +1221,15 @@ evaluate_subexp_standard (struct type *expect_type, else { msg_send = find_function_in_inferior ("objc_msgSend", NULL); - /* Special dispatcher for methods returning structs */ + /* Special dispatcher for methods returning structs. */ msg_send_stret = find_function_in_inferior ("objc_msgSend_stret", NULL); } - /* Verify the target object responds to this method. The + /* Verify the target object responds to this method. The standard top-level 'Object' class uses a different name for the verification method than the non-standard, but more - often used, 'NSObject' class. Make sure we check for both. */ + often used, 'NSObject' class. Make sure we check for both. */ responds_selector = lookup_child_selector (exp->gdbarch, "respondsToSelector:"); @@ -1245,7 +1250,7 @@ evaluate_subexp_standard (struct type *expect_type, error (_("no 'methodFor:' or 'methodForSelector:' method")); /* Call the verification method, to make sure that the target - class implements the desired method. */ + class implements the desired method. */ argvec[0] = msg_send; argvec[1] = target; @@ -1267,7 +1272,7 @@ evaluate_subexp_standard (struct type *expect_type, function method that implements this selector for this class. If we can find a symbol at that address, then we know the return type, parameter types etc. (that's a good - thing). */ + thing). */ argvec[0] = msg_send; argvec[1] = target; @@ -1305,13 +1310,12 @@ evaluate_subexp_standard (struct type *expect_type, if (method) { - struct block *b; CORE_ADDR funaddr; struct type *val_type; funaddr = find_function_addr (method, &val_type); - b = block_for_pc (funaddr); + block_for_pc (funaddr); CHECK_TYPEDEF (val_type); @@ -1323,7 +1327,8 @@ evaluate_subexp_standard (struct type *expect_type, } struct_return = using_struct_return (exp->gdbarch, - value_type (method), val_type); + value_type (method), + val_type); } else if (expect_type != NULL) { @@ -1347,12 +1352,14 @@ evaluate_subexp_standard (struct type *expect_type, if (method) { if (TYPE_CODE (value_type (method)) != TYPE_CODE_FUNC) - error (_("method address has symbol information with non-function type; skipping")); - - /* Create a function pointer of the appropriate type, and replace - its value with the value of msg_send or msg_send_stret. We must - use a pointer here, as msg_send and msg_send_stret are of pointer - type, and the representation may be different on systems that use + error (_("method address has symbol information " + "with non-function type; skipping")); + + /* Create a function pointer of the appropriate type, and + replace its value with the value of msg_send or + msg_send_stret. We must use a pointer here, as + msg_send and msg_send_stret are of pointer type, and + the representation may be different on systems that use function descriptors. */ if (struct_return) called_method @@ -1378,11 +1385,11 @@ evaluate_subexp_standard (struct type *expect_type, { /* If the return type doesn't look like a function type, call an error. This can happen if somebody tries to - turn a variable into a function call. This is here + turn a variable into a function call. This is here because people often want to call, eg, strcmp, which gdb doesn't know is a function. If gdb isn't asked for it's opinion (ie. through "whatis"), it won't offer - it. */ + it. */ struct type *type = value_type (called_method); @@ -1398,7 +1405,8 @@ evaluate_subexp_standard (struct type *expect_type, return allocate_value (type); } else - error (_("Expression of type other than \"method returning ...\" used as a method")); + error (_("Expression of type other than " + "\"method returning ...\" used as a method")); } /* Now depending on whether we found a symbol for the method, @@ -1418,7 +1426,8 @@ evaluate_subexp_standard (struct type *expect_type, /* Function objc_msg_lookup returns a pointer. */ deprecated_set_value_type (argvec[0], lookup_pointer_type (lookup_function_type (value_type (argvec[0])))); - argvec[0] = call_function_by_hand (argvec[0], nargs + 2, argvec + 1); + argvec[0] + = call_function_by_hand (argvec[0], nargs + 2, argvec + 1); } ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1); @@ -1431,12 +1440,13 @@ evaluate_subexp_standard (struct type *expect_type, op = exp->elts[*pos].opcode; nargs = longest_to_int (exp->elts[pc + 1].longconst); /* Allocate arg vector, including space for the function to be - called in argvec[0] and a terminating NULL */ - argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3)); + called in argvec[0] and a terminating NULL. */ + argvec = (struct value **) + alloca (sizeof (struct value *) * (nargs + 3)); if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { nargs++; - /* First, evaluate the structure into arg2 */ + /* First, evaluate the structure into arg2. */ pc2 = (*pos)++; if (noside == EVAL_SKIP) @@ -1473,16 +1483,16 @@ evaluate_subexp_standard (struct type *expect_type, else arg1 = cplus_method_ptr_to_value (&arg2, arg1); - /* Now, say which argument to start evaluating from */ + /* Now, say which argument to start evaluating from. */ tem = 2; } else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) { - /* Hair for method invocations */ + /* Hair for method invocations. */ int tem2; nargs++; - /* First, evaluate the structure into arg2 */ + /* First, evaluate the structure into arg2. */ pc2 = (*pos)++; tem2 = longest_to_int (exp->elts[pc2 + 1].longconst); *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1); @@ -1510,8 +1520,31 @@ evaluate_subexp_standard (struct type *expect_type, else { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + /* Check to see if the operator '->' has been + overloaded. If the operator has been overloaded + replace arg2 with the value returned by the custom + operator and continue evaluation. */ + while (unop_user_defined_p (op, arg2)) + { + volatile struct gdb_exception except; + struct value *value = NULL; + TRY_CATCH (except, RETURN_MASK_ERROR) + { + value = value_x_unop (arg2, op, noside); + } + + if (except.reason < 0) + { + if (except.error == NOT_FOUND_ERROR) + break; + else + throw_exception (except); + } + arg2 = value; + } } - /* Now, say which argument to start evaluating from */ + /* Now, say which argument to start evaluating from. */ tem = 2; } else if (op == OP_SCOPE @@ -1568,33 +1601,45 @@ evaluate_subexp_standard (struct type *expect_type, } else { - /* Non-method function call */ + /* Non-method function call. */ save_pos1 = *pos; - argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside); tem = 1; - type = value_type (argvec[0]); - if (type && TYPE_CODE (type) == TYPE_CODE_PTR) - type = TYPE_TARGET_TYPE (type); - if (type && TYPE_CODE (type) == TYPE_CODE_FUNC) + + /* If this is a C++ function wait until overload resolution. */ + if (op == OP_VAR_VALUE + && overload_resolution + && (exp->language_defn->la_language == language_cplus)) { - for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++) + (*pos) += 4; /* Skip the evaluation of the symbol. */ + argvec[0] = NULL; + } + else + { + argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside); + type = value_type (argvec[0]); + if (type && TYPE_CODE (type) == TYPE_CODE_PTR) + type = TYPE_TARGET_TYPE (type); + if (type && TYPE_CODE (type) == TYPE_CODE_FUNC) { - /* pai: FIXME This seems to be coercing arguments before - * overload resolution has been done! */ - argvec[tem] = evaluate_subexp (TYPE_FIELD_TYPE (type, tem - 1), - exp, pos, noside); + for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++) + { + argvec[tem] = evaluate_subexp (TYPE_FIELD_TYPE (type, + tem - 1), + exp, pos, noside); + } } } } - /* Evaluate arguments */ + /* Evaluate arguments. */ for (; tem <= nargs; tem++) { - /* Ensure that array expressions are coerced into pointer objects. */ + /* Ensure that array expressions are coerced into pointer + objects. */ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); } - /* signal end of arglist */ + /* Signal end of arglist. */ argvec[tem] = 0; if (op == OP_ADL_FUNC) { @@ -1608,14 +1653,17 @@ evaluate_subexp_standard (struct type *expect_type, func_name = (char *) alloca (name_len + 1); strcpy (func_name, &exp->elts[string_pc + 1].string); - /* Prepare list of argument types for overload resolution */ - arg_types = (struct type **) alloca (nargs * (sizeof (struct type *))); + /* Prepare list of argument types for overload resolution. */ + arg_types = (struct type **) + alloca (nargs * (sizeof (struct type *))); for (ix = 1; ix <= nargs; ix++) arg_types[ix - 1] = value_type (argvec[ix]); find_overload_match (arg_types, nargs, func_name, - NON_METHOD /* not method */ , 0 /* strict match */ , - NULL, NULL /* pass NULL symbol since symbol is unknown */ , + NON_METHOD, /* not method */ + 0, /* strict match */ + NULL, NULL, /* pass NULL symbol since + symbol is unknown */ NULL, &symp, NULL, 0); /* Now fix the expression being evaluated. */ @@ -1629,31 +1677,36 @@ evaluate_subexp_standard (struct type *expect_type, int static_memfuncp; char *tstr; - /* Method invocation : stuff "this" as first parameter */ + /* Method invocation : stuff "this" as first parameter. */ argvec[1] = arg2; if (op != OP_SCOPE) { - /* Name of method from expression */ + /* Name of method from expression. */ tstr = &exp->elts[pc2 + 2].string; } else tstr = function_name; - if (overload_resolution && (exp->language_defn->la_language == language_cplus)) + if (overload_resolution && (exp->language_defn->la_language + == language_cplus)) { - /* Language is C++, do some overload resolution before evaluation */ + /* Language is C++, do some overload resolution before + evaluation. */ struct value *valp = NULL; - /* Prepare list of argument types for overload resolution */ - arg_types = (struct type **) alloca (nargs * (sizeof (struct type *))); + /* Prepare list of argument types for overload resolution. */ + arg_types = (struct type **) + alloca (nargs * (sizeof (struct type *))); for (ix = 1; ix <= nargs; ix++) arg_types[ix - 1] = value_type (argvec[ix]); (void) find_overload_match (arg_types, nargs, tstr, - METHOD /* method */ , 0 /* strict match */ , - &arg2 /* the object */ , NULL, - &valp, NULL, &static_memfuncp, 0); + METHOD, /* method */ + 0, /* strict match */ + &arg2, /* the object */ + NULL, &valp, NULL, + &static_memfuncp, 0); if (op == OP_SCOPE && !static_memfuncp) { @@ -1663,10 +1716,11 @@ evaluate_subexp_standard (struct type *expect_type, function_name); } argvec[1] = arg2; /* the ``this'' pointer */ - argvec[0] = valp; /* use the method found after overload resolution */ + argvec[0] = valp; /* Use the method found after overload + resolution. */ } else - /* Non-C++ case -- or no overload resolution */ + /* Non-C++ case -- or no overload resolution. */ { struct value *temp = arg2; @@ -1677,9 +1731,10 @@ evaluate_subexp_standard (struct type *expect_type, /* value_struct_elt updates temp with the correct value of the ``this'' pointer if necessary, so modify argvec[1] to reflect any ``this'' changes. */ - arg2 = value_from_longest (lookup_pointer_type(value_type (temp)), - value_address (temp) - + value_embedded_offset (temp)); + arg2 + = value_from_longest (lookup_pointer_type(value_type (temp)), + value_address (temp) + + value_embedded_offset (temp)); argvec[1] = arg2; /* the ``this'' pointer */ } @@ -1697,14 +1752,16 @@ evaluate_subexp_standard (struct type *expect_type, } else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL)) { - /* Non-member function being called */ + /* Non-member function being called. */ /* fn: This can only be done for C++ functions. A C-style function in a C++ program, for instance, does not have the fields that - are expected here */ + are expected here. */ - if (overload_resolution && (exp->language_defn->la_language == language_cplus)) + if (overload_resolution && (exp->language_defn->la_language + == language_cplus)) { - /* Language is C++, do some overload resolution before evaluation */ + /* Language is C++, do some overload resolution before + evaluation. */ struct symbol *symp; int no_adl = 0; @@ -1715,19 +1772,22 @@ evaluate_subexp_standard (struct type *expect_type, if (op == OP_VAR_VALUE) function = exp->elts[save_pos1+2].symbol; - /* Prepare list of argument types for overload resolution */ - arg_types = (struct type **) alloca (nargs * (sizeof (struct type *))); + /* Prepare list of argument types for overload resolution. */ + arg_types = (struct type **) + alloca (nargs * (sizeof (struct type *))); for (ix = 1; ix <= nargs; ix++) arg_types[ix - 1] = value_type (argvec[ix]); - (void) find_overload_match (arg_types, nargs, NULL /* no need for name */ , - NON_METHOD /* not method */ , 0 /* strict match */ , - NULL, function /* the function */ , + (void) find_overload_match (arg_types, nargs, + NULL, /* no need for name */ + NON_METHOD, /* not method */ + 0, /* strict match */ + NULL, function, /* the function */ NULL, &symp, NULL, no_adl); if (op == OP_VAR_VALUE) { - /* Now fix the expression being evaluated */ + /* Now fix the expression being evaluated. */ exp->elts[save_pos1+2].symbol = symp; argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside); @@ -1737,14 +1797,14 @@ evaluate_subexp_standard (struct type *expect_type, } else { - /* Not C++, or no overload resolution allowed */ - /* nothing to be done; argvec already correctly set up */ + /* Not C++, or no overload resolution allowed. */ + /* Nothing to be done; argvec already correctly set up. */ } } else { - /* It is probably a C-style function */ - /* nothing to be done; argvec already correctly set up */ + /* It is probably a C-style function. */ + /* Nothing to be done; argvec already correctly set up. */ } do_call_it: @@ -1757,10 +1817,10 @@ evaluate_subexp_standard (struct type *expect_type, { /* If the return type doesn't look like a function type, call an error. This can happen if somebody tries to turn a variable into - a function call. This is here because people often want to + a function call. This is here because people often want to call, eg, strcmp, which gdb doesn't know is a function. If gdb isn't asked for it's opinion (ie. through "whatis"), - it won't offer it. */ + it won't offer it. */ struct type *ftype = value_type (argvec[0]); @@ -1772,17 +1832,21 @@ evaluate_subexp_standard (struct type *expect_type, return value_zero (builtin_type (exp->gdbarch)->builtin_int, not_lval); } + else if (TYPE_GNU_IFUNC (ftype)) + return allocate_value (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype))); else if (TYPE_TARGET_TYPE (ftype)) return allocate_value (TYPE_TARGET_TYPE (ftype)); else - error (_("Expression of type other than \"Function returning ...\" used as function")); + error (_("Expression of type other than " + "\"Function returning ...\" used as function")); } if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION) return call_internal_function (exp->gdbarch, exp->language_defn, argvec[0], nargs, argvec + 1); return call_function_by_hand (argvec[0], nargs, argvec + 1); - /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve */ + /* pai: FIXME save value from call_function_by_hand, then adjust + pc by adjust_fn_pc if +ve. */ case OP_F77_UNDETERMINED_ARGLIST: @@ -1790,8 +1854,8 @@ evaluate_subexp_standard (struct type *expect_type, array subscript operations cannot be disambiguated at parse time. We have made all array subscript operations, substring operations as well as function calls come here - and we now have to discover what the heck this thing actually was. - If it is a function, we process just as if we got an OP_FUNCALL. */ + and we now have to discover what the heck this thing actually was. + If it is a function, we process just as if we got an OP_FUNCALL. */ nargs = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 2; @@ -1838,10 +1902,11 @@ evaluate_subexp_standard (struct type *expect_type, case TYPE_CODE_PTR: case TYPE_CODE_FUNC: - /* It's a function call. */ + /* It's a function call. */ /* Allocate arg vector, including space for the function to be - called in argvec[0] and a terminating NULL */ - argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 2)); + called in argvec[0] and a terminating NULL. */ + argvec = (struct value **) + alloca (sizeof (struct value *) * (nargs + 2)); argvec[0] = arg1; tem = 1; for (; tem <= nargs; tem++) @@ -1855,7 +1920,7 @@ evaluate_subexp_standard (struct type *expect_type, case OP_COMPLEX: /* We have a complex number, There should be 2 floating - point numbers that compose it */ + point numbers that compose it. */ (*pos) += 2; arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); @@ -1888,9 +1953,30 @@ evaluate_subexp_standard (struct type *expect_type, if (noside == EVAL_SKIP) goto nosideret; + /* Check to see if operator '->' has been overloaded. If so replace + arg1 with the value returned by evaluating operator->(). */ + while (unop_user_defined_p (op, arg1)) + { + volatile struct gdb_exception except; + struct value *value = NULL; + TRY_CATCH (except, RETURN_MASK_ERROR) + { + value = value_x_unop (arg1, op, noside); + } + + if (except.reason < 0) + { + if (except.error == NOT_FOUND_ERROR) + break; + else + throw_exception (except); + } + arg1 = value; + } + /* JYG: if print object is on we need to replace the base type with rtti type in order to continue on with successful - lookup of member / method only available in the rtti type. */ + lookup of member / method only available in the rtti type. */ { struct type *type = value_type (arg1); struct type *real_type; @@ -1964,7 +2050,8 @@ evaluate_subexp_standard (struct type *expect_type, return value_ind (arg3); default: - error (_("non-pointer-to-member value used in pointer-to-member construct")); + error (_("non-pointer-to-member value used " + "in pointer-to-member construct")); } case TYPE_INSTANCE: @@ -2131,8 +2218,8 @@ evaluate_subexp_standard (struct type *expect_type, } case BINOP_RANGE: - arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + evaluate_subexp (NULL_TYPE, exp, pos, noside); + evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; error (_("':' operator used in invalid context")); @@ -2148,7 +2235,7 @@ evaluate_subexp_standard (struct type *expect_type, { /* If the user attempts to subscript something that is not an array or pointer type (like a plain int variable for example), - then report this as an error. */ + then report this as an error. */ arg1 = coerce_ref (arg1); type = check_typedef (value_type (arg1)); @@ -2183,7 +2270,7 @@ evaluate_subexp_standard (struct type *expect_type, while (nargs-- > 0) { arg2 = evaluate_subexp_with_coercion (exp, pos, noside); - /* FIXME: EVAL_SKIP handling may not be correct. */ + /* FIXME: EVAL_SKIP handling may not be correct. */ if (noside == EVAL_SKIP) { if (nargs > 0) @@ -2195,12 +2282,12 @@ evaluate_subexp_standard (struct type *expect_type, goto nosideret; } } - /* FIXME: EVAL_AVOID_SIDE_EFFECTS handling may not be correct. */ + /* FIXME: EVAL_AVOID_SIDE_EFFECTS handling may not be correct. */ if (noside == EVAL_AVOID_SIDE_EFFECTS) { /* If the user attempts to subscript something that has no target type (like a plain int variable for example), then report this - as an error. */ + as an error. */ type = TYPE_TARGET_TYPE (check_typedef (value_type (arg1))); if (type != NULL) @@ -2252,16 +2339,13 @@ evaluate_subexp_standard (struct type *expect_type, multi_f77_subscript: { - int subscript_array[MAX_FORTRAN_DIMS]; - int array_size_array[MAX_FORTRAN_DIMS]; + LONGEST subscript_array[MAX_FORTRAN_DIMS]; int ndimensions = 1, i; - struct type *tmp_type; - int offset_item; /* The array offset where the item lives */ + struct value *array = arg1; if (nargs > MAX_FORTRAN_DIMS) error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS); - tmp_type = check_typedef (value_type (arg1)); ndimensions = calc_f77_array_dims (type); if (nargs != ndimensions) @@ -2270,68 +2354,37 @@ evaluate_subexp_standard (struct type *expect_type, gdb_assert (nargs > 0); /* Now that we know we have a legal array subscript expression - let us actually find out where this element exists in the array. */ + let us actually find out where this element exists in the array. */ - offset_item = 0; - /* Take array indices left to right */ + /* Take array indices left to right. */ for (i = 0; i < nargs; i++) { - /* Evaluate each subscript, It must be a legal integer in F77 */ + /* Evaluate each subscript; it must be a legal integer in F77. */ arg2 = evaluate_subexp_with_coercion (exp, pos, noside); - /* Fill in the subscript and array size arrays */ + /* Fill in the subscript array. */ subscript_array[i] = value_as_long (arg2); } - /* Internal type of array is arranged right to left */ - for (i = 0; i < nargs; i++) + /* Internal type of array is arranged right to left. */ + for (i = nargs; i > 0; i--) { - upper = f77_get_upperbound (tmp_type); - lower = f77_get_lowerbound (tmp_type); - - array_size_array[nargs - i - 1] = upper - lower + 1; - - /* Zero-normalize subscripts so that offsetting will work. */ + struct type *array_type = check_typedef (value_type (array)); + LONGEST index = subscript_array[i - 1]; - subscript_array[nargs - i - 1] -= lower; - - /* If we are at the bottom of a multidimensional - array type then keep a ptr to the last ARRAY - type around for use when calling value_subscript() - below. This is done because we pretend to value_subscript - that we actually have a one-dimensional array - of base element type that we apply a simple - offset to. */ - - if (i < nargs - 1) - tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type)); + lower = f77_get_lowerbound (array_type); + array = value_subscripted_rvalue (array, index, lower); } - /* Now let us calculate the offset for this item */ - - offset_item = subscript_array[ndimensions - 1]; - - for (i = ndimensions - 1; i > 0; --i) - offset_item = - array_size_array[i - 1] * offset_item + subscript_array[i - 1]; - - /* Let us now play a dirty trick: we will take arg1 - which is a value node pointing to the topmost level - of the multidimensional array-set and pretend - that it is actually a array of the final element - type, this will ensure that value_subscript() - returns the correct type value */ - - deprecated_set_value_type (arg1, tmp_type); - return value_subscripted_rvalue (arg1, offset_item, 0); + return array; } case BINOP_LOGICAL_AND: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) { - arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + evaluate_subexp (NULL_TYPE, exp, pos, noside); goto nosideret; } @@ -2358,7 +2411,7 @@ evaluate_subexp_standard (struct type *expect_type, arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) { - arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + evaluate_subexp (NULL_TYPE, exp, pos, noside); goto nosideret; } @@ -2561,7 +2614,8 @@ evaluate_subexp_standard (struct type *expect_type, type = check_typedef (value_type (arg1)); if (TYPE_CODE (type) == TYPE_CODE_METHODPTR || TYPE_CODE (type) == TYPE_CODE_MEMBERPTR) - error (_("Attempt to dereference pointer to member without an object")); + error (_("Attempt to dereference pointer " + "to member without an object")); if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) @@ -2605,7 +2659,8 @@ evaluate_subexp_standard (struct type *expect_type, } else { - struct value *retvalp = evaluate_subexp_for_address (exp, pos, noside); + struct value *retvalp = evaluate_subexp_for_address (exp, pos, + noside); return retvalp; } @@ -2729,6 +2784,8 @@ evaluate_subexp_standard (struct type *expect_type, } else { + arg3 = value_non_lval (arg1); + if (ptrmath_type_p (exp->language_defn, value_type (arg1))) arg2 = value_ptradd (arg1, 1); else @@ -2741,7 +2798,7 @@ evaluate_subexp_standard (struct type *expect_type, } value_assign (arg1, arg2); - return arg1; + return arg3; } case UNOP_POSTDECREMENT: @@ -2754,6 +2811,8 @@ evaluate_subexp_standard (struct type *expect_type, } else { + arg3 = value_non_lval (arg1); + if (ptrmath_type_p (exp->language_defn, value_type (arg1))) arg2 = value_ptradd (arg1, -1); else @@ -2766,7 +2825,7 @@ evaluate_subexp_standard (struct type *expect_type, } value_assign (arg1, arg2); - return arg1; + return arg3; } case OP_THIS: @@ -2809,8 +2868,8 @@ evaluate_subexp_standard (struct type *expect_type, then they should be separate cases, with more descriptive error messages. */ - error (_("\ -GDB does not (yet) know how to evaluate that kind of expression")); + error (_("GDB does not (yet) know how to " + "evaluate that kind of expression")); } nosideret: @@ -2861,7 +2920,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, var = exp->elts[pc + 2].symbol; /* C++: The "address" of a reference should yield the address - * of the object pointed to. Let value_addr() deal with it. */ + * of the object pointed to. Let value_addr() deal with it. */ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF) goto default_case; @@ -2908,7 +2967,8 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)), not_lval); else - error (_("Attempt to take address of value not located in memory.")); + error (_("Attempt to take address of " + "value not located in memory.")); } return value_addr (x); } @@ -2923,9 +2983,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, Note that we currently only do the coercion for C expressions, where arrays are zero based and the coercion is correct. For other languages, with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION - to decide if coercion is appropriate. - - */ + to decide if coercion is appropriate. */ struct value * evaluate_subexp_with_coercion (struct expression *exp, @@ -2946,6 +3004,7 @@ evaluate_subexp_with_coercion (struct expression *exp, var = exp->elts[pc + 2].symbol; type = check_typedef (SYMBOL_TYPE (var)); if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && !TYPE_VECTOR (type) && CAST_IS_CONVERSION (exp->language_defn)) { (*pos) += 4; @@ -3012,7 +3071,7 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) } } -/* Parse a type expression in the string [P..P+LENGTH). */ +/* Parse a type expression in the string [P..P+LENGTH). */ struct type * parse_and_eval_type (char *p, int length) diff --git a/contrib/gdb-7/gdb/event-loop.c b/contrib/gdb-7/gdb/event-loop.c index e8cba5d0ac..617835feb0 100644 --- a/contrib/gdb-7/gdb/event-loop.c +++ b/contrib/gdb-7/gdb/event-loop.c @@ -1,6 +1,6 @@ /* Event loop machinery for GDB, the GNU debugger. - Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. This file is part of GDB. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ #include "defs.h" #include "event-loop.h" @@ -38,8 +38,8 @@ #include "gdb_assert.h" #include "gdb_select.h" -/* Tell create_file_handler what events we are interested in. - This is used by the select version of the event loop. */ +/* Tell create_file_handler what events we are interested in. + This is used by the select version of the event loop. */ #define GDB_READABLE (1<<1) #define GDB_WRITABLE (1<<2) @@ -56,12 +56,12 @@ typedef struct gdb_event gdb_event; typedef void (event_handler_func) (event_data); /* Event for the GDB event system. Events are queued by calling - async_queue_event and serviced later on by gdb_do_one_event. An + async_queue_event and serviced later on by gdb_do_one_event. An event can be, for instance, a file descriptor becoming ready to be read. Servicing an event simply means that the procedure PROC will be called. We have 2 queues, one for file handlers that we listen to in the event loop, and one for the file handlers+events that are - ready. The procedure PROC associated with each event is dependant + ready. The procedure PROC associated with each event is dependant of the event source. In the case of monitored file descriptors, it is always the same (handle_file_event). Its duty is to invoke the handler associated with the file descriptor whose state change @@ -82,36 +82,39 @@ struct gdb_event }; /* Information about each file descriptor we register with the event - loop. */ + loop. */ typedef struct file_handler { - int fd; /* File descriptor. */ - int mask; /* Events we want to monitor: POLLIN, etc. */ + int fd; /* File descriptor. */ + int mask; /* Events we want to monitor: POLLIN, etc. */ int ready_mask; /* Events that have been seen since - the last time. */ - handler_func *proc; /* Procedure to call when fd is ready. */ - gdb_client_data client_data; /* Argument to pass to proc. */ - int error; /* Was an error detected on this fd? */ - struct file_handler *next_file; /* Next registered file descriptor. */ + the last time. */ + handler_func *proc; /* Procedure to call when fd is ready. */ + gdb_client_data client_data; /* Argument to pass to proc. */ + int error; /* Was an error detected on this fd? */ + struct file_handler *next_file; /* Next registered file descriptor. */ } file_handler; -/* PROC is a function to be invoked when the READY flag is set. This +/* PROC is a function to be invoked when the READY flag is set. This happens when there has been a signal and the corresponding signal - handler has 'triggered' this async_signal_handler for - execution. The actual work to be done in response to a signal will - be carried out by PROC at a later time, within process_event. This - provides a deferred execution of signal handlers. + handler has 'triggered' this async_signal_handler for execution. + The actual work to be done in response to a signal will be carried + out by PROC at a later time, within process_event. This provides a + deferred execution of signal handlers. + Async_init_signals takes care of setting up such an - async_signal_handler for each interesting signal. */ + async_signal_handler for each interesting signal. */ + typedef struct async_signal_handler { - int ready; /* If ready, call this handler from the main event loop, - using invoke_async_handler. */ - struct async_signal_handler *next_handler; /* Ptr to next handler */ - sig_handler_func *proc; /* Function to call to do the work */ - gdb_client_data client_data; /* Argument to async_handler_func */ + int ready; /* If ready, call this handler + from the main event loop, using + invoke_async_handler. */ + struct async_signal_handler *next_handler; /* Ptr to next handler. */ + sig_handler_func *proc; /* Function to call to do the work. */ + gdb_client_data client_data; /* Argument to async_handler_func. */ } async_signal_handler; @@ -140,7 +143,7 @@ async_event_handler; /* Event queue: - - the first event in the queue is the head of the queue. + - the first event in the queue is the head of the queue. It will be the next to be serviced. - the last event in the queue @@ -150,25 +153,25 @@ async_event_handler; the queue will be processed in a last in first out fashion, while those inserted at the tail of the queue will be processed in a first in first out manner. All the fields are NULL if the queue is - empty. */ + empty. */ static struct { - gdb_event *first_event; /* First pending event */ - gdb_event *last_event; /* Last pending event */ + gdb_event *first_event; /* First pending event. */ + gdb_event *last_event; /* Last pending event. */ } event_queue; /* Gdb_notifier is just a list of file descriptors gdb is interested in. These are the input file descriptor, and the target file - descriptor. We have two flavors of the notifier, one for platforms + descriptor. We have two flavors of the notifier, one for platforms that have the POLL function, the other for those that don't, and - only support SELECT. Each of the elements in the gdb_notifier list is + only support SELECT. Each of the elements in the gdb_notifier list is basically a description of what kind of events gdb is interested - in, for each fd. */ + in, for each fd. */ /* As of 1999-04-30 only the input file descriptor is registered with the - event loop. */ + event loop. */ /* Do we use poll or select ? */ #ifdef HAVE_POLL @@ -186,79 +189,79 @@ static unsigned char use_poll = USE_POLL; static struct { - /* Ptr to head of file handler list. */ + /* Ptr to head of file handler list. */ file_handler *first_file_handler; #ifdef HAVE_POLL - /* Ptr to array of pollfd structures. */ + /* Ptr to array of pollfd structures. */ struct pollfd *poll_fds; - /* Timeout in milliseconds for calls to poll(). */ + /* Timeout in milliseconds for calls to poll(). */ int poll_timeout; #endif /* Masks to be used in the next call to select. - Bits are set in response to calls to create_file_handler. */ + Bits are set in response to calls to create_file_handler. */ fd_set check_masks[3]; - /* What file descriptors were found ready by select. */ + /* What file descriptors were found ready by select. */ fd_set ready_masks[3]; - /* Number of file descriptors to monitor. (for poll) */ - /* Number of valid bits (highest fd value + 1). (for select) */ + /* Number of file descriptors to monitor (for poll). */ + /* Number of valid bits (highest fd value + 1) (for select). */ int num_fds; - /* Time structure for calls to select(). */ + /* Time structure for calls to select(). */ struct timeval select_timeout; - /* Flag to tell whether the timeout should be used. */ + /* Flag to tell whether the timeout should be used. */ int timeout_valid; } gdb_notifier; -/* Structure associated with a timer. PROC will be executed at the - first occasion after WHEN. */ +/* Structure associated with a timer. PROC will be executed at the + first occasion after WHEN. */ struct gdb_timer { struct timeval when; int timer_id; struct gdb_timer *next; - timer_handler_func *proc; /* Function to call to do the work */ - gdb_client_data client_data; /* Argument to async_handler_func */ + timer_handler_func *proc; /* Function to call to do the work. */ + gdb_client_data client_data; /* Argument to async_handler_func. */ }; -/* List of currently active timers. It is sorted in order of - increasing timers. */ +/* List of currently active timers. It is sorted in order of + increasing timers. */ static struct { - /* Pointer to first in timer list. */ + /* Pointer to first in timer list. */ struct gdb_timer *first_timer; - /* Id of the last timer created. */ + /* Id of the last timer created. */ int num_timers; } timer_list; /* All the async_signal_handlers gdb is interested in are kept onto - this list. */ + this list. */ static struct { - /* Pointer to first in handler list. */ + /* Pointer to first in handler list. */ async_signal_handler *first_handler; - /* Pointer to last in handler list. */ + /* Pointer to last in handler list. */ async_signal_handler *last_handler; } sighandler_list; /* All the async_event_handlers gdb is interested in are kept onto - this list. */ + this list. */ static struct { - /* Pointer to first in handler list. */ + /* Pointer to first in handler list. */ async_event_handler *first_handler; - /* Pointer to last in handler list. */ + /* Pointer to last in handler list. */ async_event_handler *last_handler; } async_event_handler_list; @@ -276,18 +279,18 @@ static void poll_timers (void); the specified position. POSITION can be head or tail, with values TAIL, HEAD. EVENT_PTR points to the event to be inserted into the queue. - The caller must allocate memory for the event. It is freed + The caller must allocate memory for the event. It is freed after the event has ben handled. Events in the queue will be processed head to tail, therefore, events inserted at the head of the queue will be processed - as last in first out. Event appended at the tail of the queue - will be processed first in first out. */ + as last in first out. Event appended at the tail of the queue + will be processed first in first out. */ static void async_queue_event (gdb_event * event_ptr, queue_position position) { if (position == TAIL) { - /* The event will become the new last_event. */ + /* The event will become the new last_event. */ event_ptr->next_event = NULL; if (event_queue.first_event == NULL) @@ -298,7 +301,7 @@ async_queue_event (gdb_event * event_ptr, queue_position position) } else if (position == HEAD) { - /* The event becomes the new first_event. */ + /* The event becomes the new first_event. */ event_ptr->next_event = event_queue.first_event; if (event_queue.first_event == NULL) @@ -324,9 +327,9 @@ create_event (event_handler_func proc, event_data data) } /* Create a file event, to be enqueued in the event queue for - processing. The procedure associated to this event is always + processing. The procedure associated to this event is always handle_file_event, which will in turn invoke the one that was - associated to FD when it was registered with the event loop. */ + associated to FD when it was registered with the event loop. */ static gdb_event * create_file_event (int fd) { @@ -344,7 +347,7 @@ create_file_event (int fd) 0 is returned. Scan the queue from head to tail, processing therefore the high priority events first, by invoking the associated event handler - procedure. */ + procedure. */ static int process_event (void) { @@ -353,19 +356,19 @@ process_event (void) event_data data; /* First let's see if there are any asynchronous event handlers that - are ready. These would be the result of invoking any of the - signal handlers. */ + are ready. These would be the result of invoking any of the + signal handlers. */ if (invoke_async_signal_handlers ()) return 1; /* Look in the event queue to find an event that is ready - to be processed. */ + to be processed. */ for (event_ptr = event_queue.first_event; event_ptr != NULL; event_ptr = event_ptr->next_event) { - /* Call the handler for the event. */ + /* Call the handler for the event. */ proc = event_ptr->proc; data = event_ptr->data; @@ -373,9 +376,9 @@ process_event (void) /* Let's get rid of the event from the event queue. We need to do this now because while processing the event, the proc function could end up calling 'error' and therefore jump out - to the caller of this function, gdb_do_one_event. In that + to the caller of this function, gdb_do_one_event. In that case, we would have on the event queue an event wich has been - processed, but not deleted. */ + processed, but not deleted. */ if (event_queue.first_event == event_ptr) { @@ -395,12 +398,12 @@ process_event (void) } xfree (event_ptr); - /* Now call the procedure associated with the event. */ + /* Now call the procedure associated with the event. */ (*proc) (data); return 1; } - /* this is the case if there are no event on the event queue. */ + /* This is the case if there are no event on the event queue. */ return 0; } @@ -408,7 +411,7 @@ process_event (void) wait for something to happen (via gdb_wait_for_event), then process it. Returns >0 if something was done otherwise returns <0 (this can happen if there are no event sources to wait for). If an error - occurs catch_errors() which calls this function returns zero. */ + occurs catch_errors() which calls this function returns zero. */ int gdb_do_one_event (void *data) @@ -429,7 +432,7 @@ gdb_do_one_event (void *data) { case 0: /* Are any timers that are ready? If so, put an event on the - queue. */ + queue. */ poll_timers (); break; case 1: @@ -469,18 +472,18 @@ gdb_do_one_event (void *data) return 1; } -/* Start up the event loop. This is the entry point to the event loop - from the command loop. */ +/* Start up the event loop. This is the entry point to the event loop + from the command loop. */ void start_event_loop (void) { - /* Loop until there is nothing to do. This is the entry point to the - event loop engine. gdb_do_one_event, called via catch_errors() + /* Loop until there is nothing to do. This is the entry point to the + event loop engine. gdb_do_one_event, called via catch_errors() will process one event for each invocation. It blocks waits for an event and then processes it. >0 when an event is processed, 0 when catch_errors() caught an error and <0 when there are no - longer any event sources registered. */ + longer any event sources registered. */ while (1) { int gdb_result; @@ -491,7 +494,7 @@ start_event_loop (void) /* If we long-jumped out of do_one_event, we probably didn't get around to resetting the prompt, which leaves - readline in a messed-up state. Reset it here. */ + readline in a messed-up state. Reset it here. */ if (gdb_result == 0) { @@ -501,7 +504,7 @@ start_event_loop (void) async_enable_stdin (); /* FIXME: this should really be a call to a hook that is interface specific, because interfaces can display the - prompt in their own way. */ + prompt in their own way. */ display_gdb_prompt (0); /* This call looks bizarre, but it is required. If the user entered a command that caused an error, @@ -512,19 +515,19 @@ start_event_loop (void) if (after_char_processing_hook) (*after_char_processing_hook) (); /* Maybe better to set a flag to be checked somewhere as to - whether display the prompt or not. */ + whether display the prompt or not. */ } } - /* We are done with the event loop. There are no more event sources - to listen to. So we exit GDB. */ + /* We are done with the event loop. There are no more event sources + to listen to. So we exit GDB. */ return; } /* Wrapper function for create_file_handler, so that the caller doesn't have to know implementation details about the use of poll - vs. select. */ + vs. select. */ void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) { @@ -535,11 +538,11 @@ add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) if (use_poll) { #ifdef HAVE_POLL - /* Check to see if poll () is usable. If not, we'll switch to - use select. This can happen on systems like + /* Check to see if poll () is usable. If not, we'll switch to + use select. This can happen on systems like m68k-motorola-sys, `poll' cannot be used to wait for `stdin'. On m68k-motorola-sysv, tty's are not stream-based and not - `poll'able. */ + `poll'able. */ fds.fd = fd; fds.events = POLLIN; if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL)) @@ -559,26 +562,32 @@ add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) #endif } else - create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); + create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, + proc, client_data); } /* Add a file handler/descriptor to the list of descriptors we are - interested in. - FD is the file descriptor for the file/stream to be listened to. - For the poll case, MASK is a combination (OR) of - POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, - POLLWRBAND: these are the events we are interested in. If any of them - occurs, proc should be called. - For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION. - PROC is the procedure that will be called when an event occurs for - FD. CLIENT_DATA is the argument to pass to PROC. */ + interested in. + + FD is the file descriptor for the file/stream to be listened to. + + For the poll case, MASK is a combination (OR) of POLLIN, + POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND: + these are the events we are interested in. If any of them occurs, + proc should be called. + + For the select case, MASK is a combination of READABLE, WRITABLE, + EXCEPTION. PROC is the procedure that will be called when an event + occurs for FD. CLIENT_DATA is the argument to pass to PROC. */ + static void -create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data) +create_file_handler (int fd, int mask, handler_func * proc, + gdb_client_data client_data) { file_handler *file_ptr; - /* Do we already have a file handler for this file? (We may be - changing its associated procedure). */ + /* Do we already have a file handler for this file? (We may be + changing its associated procedure). */ for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; file_ptr = file_ptr->next_file) { @@ -586,8 +595,8 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie break; } - /* It is a new file descriptor. Add it to the list. Otherwise, just - change the data associated with it. */ + /* It is a new file descriptor. Add it to the list. Otherwise, just + change the data associated with it. */ if (file_ptr == NULL) { file_ptr = (file_handler *) xmalloc (sizeof (file_handler)); @@ -644,7 +653,7 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie } /* Remove the file descriptor FD from the list of monitored fd's: - i.e. we don't care anymore about events on the FD. */ + i.e. we don't care anymore about events on the FD. */ void delete_file_handler (int fd) { @@ -655,7 +664,7 @@ delete_file_handler (int fd) struct pollfd *new_poll_fds; #endif - /* Find the entry for the given file. */ + /* Find the entry for the given file. */ for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; file_ptr = file_ptr->next_file) @@ -670,11 +679,11 @@ delete_file_handler (int fd) if (use_poll) { #ifdef HAVE_POLL - /* Create a new poll_fds array by copying every fd's information but the - one we want to get rid of. */ + /* Create a new poll_fds array by copying every fd's information + but the one we want to get rid of. */ - new_poll_fds = - (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); + new_poll_fds = (struct pollfd *) + xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) { @@ -682,7 +691,8 @@ delete_file_handler (int fd) { (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd; (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events; - (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents; + (new_poll_fds + j)->revents + = (gdb_notifier.poll_fds + i)->revents; j++; } } @@ -703,7 +713,7 @@ delete_file_handler (int fd) if (file_ptr->mask & GDB_EXCEPTION) FD_CLR (fd, &gdb_notifier.check_masks[2]); - /* Find current max fd. */ + /* Find current max fd. */ if ((fd + 1) == gdb_notifier.num_fds) { @@ -720,11 +730,11 @@ delete_file_handler (int fd) } /* Deactivate the file descriptor, by clearing its mask, - so that it will not fire again. */ + so that it will not fire again. */ file_ptr->mask = 0; - /* Get rid of the file handler in the file handler list. */ + /* Get rid of the file handler in the file handler list. */ if (file_ptr == gdb_notifier.first_file_handler) gdb_notifier.first_file_handler = file_ptr->next_file; else @@ -741,7 +751,7 @@ delete_file_handler (int fd) /* Handle the given event by calling the procedure associated to the corresponding file handler. Called by process_event indirectly, through event_ptr->proc. EVENT_FILE_DESC is file descriptor of the - event in the front of the event queue. */ + event in the front of the event queue. */ static void handle_file_event (event_data data) { @@ -754,21 +764,21 @@ handle_file_event (event_data data) int event_file_desc = data.integer; /* Search the file handler list to find one that matches the fd in - the event. */ + the event. */ for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; file_ptr = file_ptr->next_file) { if (file_ptr->fd == event_file_desc) { /* With poll, the ready_mask could have any of three events - set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot - be used in the requested event mask (events), but they - can be returned in the return mask (revents). We need to - check for those event too, and add them to the mask which - will be passed to the handler. */ + set to 1: POLLHUP, POLLERR, POLLNVAL. These events + cannot be used in the requested event mask (events), but + they can be returned in the return mask (revents). We + need to check for those event too, and add them to the + mask which will be passed to the handler. */ /* See if the desired events (mask) match the received - events (ready_mask). */ + events (ready_mask). */ if (use_poll) { @@ -780,14 +790,17 @@ handle_file_event (event_data data) if (error_mask_returned != 0) { - /* Work in progress. We may need to tell somebody what - kind of error we had. */ + /* Work in progress. We may need to tell somebody + what kind of error we had. */ if (error_mask_returned & POLLHUP) - printf_unfiltered (_("Hangup detected on fd %d\n"), file_ptr->fd); + printf_unfiltered (_("Hangup detected on fd %d\n"), + file_ptr->fd); if (error_mask_returned & POLLERR) - printf_unfiltered (_("Error detected on fd %d\n"), file_ptr->fd); + printf_unfiltered (_("Error detected on fd %d\n"), + file_ptr->fd); if (error_mask_returned & POLLNVAL) - printf_unfiltered (_("Invalid or non-`poll'able fd %d\n"), file_ptr->fd); + printf_unfiltered (_("Invalid or non-`poll'able fd %d\n"), + file_ptr->fd); file_ptr->error = 1; } else @@ -801,7 +814,8 @@ handle_file_event (event_data data) { if (file_ptr->ready_mask & GDB_EXCEPTION) { - printf_unfiltered (_("Exception condition detected on fd %d\n"), file_ptr->fd); + printf_unfiltered (_("Exception condition detected " + "on fd %d\n"), file_ptr->fd); file_ptr->error = 1; } else @@ -809,10 +823,10 @@ handle_file_event (event_data data) mask = file_ptr->ready_mask & file_ptr->mask; } - /* Clear the received events for next time around. */ + /* Clear the received events for next time around. */ file_ptr->ready_mask = 0; - /* If there was a match, then call the handler. */ + /* If there was a match, then call the handler. */ if (mask != 0) (*file_ptr->proc) (file_ptr->error, file_ptr->client_data); break; @@ -823,8 +837,8 @@ handle_file_event (event_data data) /* Called by gdb_do_one_event to wait for new events on the monitored file descriptors. Queue file events as they are detected by the poll. If BLOCK and if there are no events, this function will - block in the call to poll. Return -1 if there are no files - descriptors to monitor, otherwise return 0. */ + block in the call to poll. Return -1 if there are no file + descriptors to monitor, otherwise return 0. */ static int gdb_wait_for_event (int block) { @@ -833,7 +847,7 @@ gdb_wait_for_event (int block) int num_found = 0; int i; - /* Make sure all output is done before getting another event. */ + /* Make sure all output is done before getting another event. */ gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); @@ -885,7 +899,7 @@ gdb_wait_for_event (int block) &gdb_notifier.ready_masks[2], timeout_p); - /* Clear the masks after an error from select. */ + /* Clear the masks after an error from select. */ if (num_found == -1) { FD_ZERO (&gdb_notifier.ready_masks[0]); @@ -899,7 +913,7 @@ gdb_wait_for_event (int block) } } - /* Enqueue all detected file events. */ + /* Enqueue all detected file events. */ if (use_poll) { @@ -922,7 +936,7 @@ gdb_wait_for_event (int block) if (file_ptr) { /* Enqueue an event only if this is still a new event for - this fd. */ + this fd. */ if (file_ptr->ready_mask == 0) { file_event_ptr = create_file_event (file_ptr->fd); @@ -957,7 +971,7 @@ gdb_wait_for_event (int block) num_found--; /* Enqueue an event only if this is still a new event for - this fd. */ + this fd. */ if (file_ptr->ready_mask == 0) { @@ -971,14 +985,15 @@ gdb_wait_for_event (int block) } -/* Create an asynchronous handler, allocating memory for it. +/* Create an asynchronous handler, allocating memory for it. Return a pointer to the newly created handler. This pointer will be used to invoke the handler by invoke_async_signal_handler. PROC is the function to call with CLIENT_DATA argument - whenever the handler is invoked. */ + whenever the handler is invoked. */ async_signal_handler * -create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data) +create_async_signal_handler (sig_handler_func * proc, + gdb_client_data client_data) { async_signal_handler *async_handler_ptr; @@ -1005,10 +1020,10 @@ call_async_signal_handler (struct async_signal_handler *handler) (*handler->proc) (handler->client_data); } -/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information will - be used when the handlers are invoked, after we have waited for - some event. The caller of this function is the interrupt handler - associated with a signal. */ +/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information + will be used when the handlers are invoked, after we have waited + for some event. The caller of this function is the interrupt + handler associated with a signal. */ void mark_async_signal_handler (async_signal_handler * async_handler_ptr) { @@ -1044,7 +1059,7 @@ invoke_async_signal_handlers (void) return any_ready; } -/* Delete an asynchronous handler (ASYNC_HANDLER_PTR). +/* Delete an asynchronous handler (ASYNC_HANDLER_PTR). Free the space allocated for it. */ void delete_async_signal_handler (async_signal_handler ** async_handler_ptr) @@ -1062,6 +1077,7 @@ delete_async_signal_handler (async_signal_handler ** async_handler_ptr) prev_ptr = sighandler_list.first_handler; while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr)) prev_ptr = prev_ptr->next_handler; + gdb_assert (prev_ptr); prev_ptr->next_handler = (*async_handler_ptr)->next_handler; if (sighandler_list.last_handler == (*async_handler_ptr)) sighandler_list.last_handler = prev_ptr; @@ -1160,7 +1176,8 @@ delete_async_event_handler (async_event_handler **async_handler_ptr) if (async_event_handler_list.first_handler == *async_handler_ptr) { - async_event_handler_list.first_handler = (*async_handler_ptr)->next_handler; + async_event_handler_list.first_handler + = (*async_handler_ptr)->next_handler; if (async_event_handler_list.first_handler == NULL) async_event_handler_list.last_handler = NULL; } @@ -1169,6 +1186,7 @@ delete_async_event_handler (async_event_handler **async_handler_ptr) prev_ptr = async_event_handler_list.first_handler; while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr) prev_ptr = prev_ptr->next_handler; + gdb_assert (prev_ptr); prev_ptr->next_handler = (*async_handler_ptr)->next_handler; if (async_event_handler_list.last_handler == (*async_handler_ptr)) async_event_handler_list.last_handler = prev_ptr; @@ -1177,19 +1195,20 @@ delete_async_event_handler (async_event_handler **async_handler_ptr) *async_handler_ptr = NULL; } -/* Create a timer that will expire in MILLISECONDS from now. When the - timer is ready, PROC will be executed. At creation, the timer is +/* Create a timer that will expire in MILLISECONDS from now. When the + timer is ready, PROC will be executed. At creation, the timer is aded to the timers queue. This queue is kept sorted in order of - increasing timers. Return a handle to the timer struct. */ + increasing timers. Return a handle to the timer struct. */ int -create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data) +create_timer (int milliseconds, timer_handler_func * proc, + gdb_client_data client_data) { struct gdb_timer *timer_ptr, *timer_index, *prev_timer; struct timeval time_now, delta; - /* compute seconds */ + /* Compute seconds. */ delta.tv_sec = milliseconds / 1000; - /* compute microseconds */ + /* Compute microseconds. */ delta.tv_usec = (milliseconds % 1000) * 1000; gettimeofday (&time_now, NULL); @@ -1197,7 +1216,7 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien timer_ptr = (struct gdb_timer *) xmalloc (sizeof (*timer_ptr)); timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec; timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec; - /* carry? */ + /* Carry? */ if (timer_ptr->when.tv_usec >= 1000000) { timer_ptr->when.tv_sec += 1; @@ -1209,14 +1228,14 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien timer_ptr->timer_id = timer_list.num_timers; /* Now add the timer to the timer queue, making sure it is sorted in - increasing order of expiration. */ + increasing order of expiration. */ for (timer_index = timer_list.first_timer; timer_index != NULL; timer_index = timer_index->next) { /* If the seconds field is greater or if it is the same, but the - microsecond field is greater. */ + microsecond field is greater. */ if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec) || ((timer_index->when.tv_sec == timer_ptr->when.tv_sec) && (timer_index->when.tv_usec > timer_ptr->when.tv_usec))) @@ -1245,13 +1264,13 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien } /* There is a chance that the creator of the timer wants to get rid of - it before it expires. */ + it before it expires. */ void delete_timer (int id) { struct gdb_timer *timer_ptr, *prev_timer = NULL; - /* Find the entry for the given timer. */ + /* Find the entry for the given timer. */ for (timer_ptr = timer_list.first_timer; timer_ptr != NULL; timer_ptr = timer_ptr->next) @@ -1262,7 +1281,7 @@ delete_timer (int id) if (timer_ptr == NULL) return; - /* Get rid of the timer in the timer list. */ + /* Get rid of the timer in the timer list. */ if (timer_ptr == timer_list.first_timer) timer_list.first_timer = timer_ptr->next; else @@ -1298,11 +1317,11 @@ handle_timer_event (event_data dummy) && (timer_ptr->when.tv_usec > time_now.tv_usec))) break; - /* Get rid of the timer from the beginning of the list. */ + /* Get rid of the timer from the beginning of the list. */ timer_list.first_timer = timer_ptr->next; saved_timer = timer_ptr; timer_ptr = timer_ptr->next; - /* Call the procedure associated with that timer. */ + /* Call the procedure associated with that timer. */ (*saved_timer->proc) (saved_timer->client_data); xfree (saved_timer); } @@ -1310,12 +1329,12 @@ handle_timer_event (event_data dummy) gdb_notifier.timeout_valid = 0; } -/* Check whether any timers in the timers queue are ready. If at least +/* Check whether any timers in the timers queue are ready. If at least one timer is ready, stick an event onto the event queue. Even in case more than one timer is ready, one event is enough, because the handle_timer_event() will go through the timers list and call the - procedures associated with all that have expired. Update the - timeout for the select() or poll() as well. */ + procedures associated with all that have expired.l Update the + timeout for the select() or poll() as well. */ static void poll_timers (void) { @@ -1327,15 +1346,15 @@ poll_timers (void) gettimeofday (&time_now, NULL); delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec; delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec; - /* borrow? */ + /* Borrow? */ if (delta.tv_usec < 0) { delta.tv_sec -= 1; delta.tv_usec += 1000000; } - /* Oops it expired already. Tell select / poll to return - immediately. (Cannot simply test if delta.tv_sec is negative + /* Oops it expired already. Tell select / poll to return + immediately. (Cannot simply test if delta.tv_sec is negative because time_t might be unsigned.) */ if (timer_list.first_timer->when.tv_sec < time_now.tv_sec || (timer_list.first_timer->when.tv_sec == time_now.tv_sec @@ -1353,8 +1372,8 @@ poll_timers (void) async_queue_event (event_ptr, TAIL); } - /* Now we need to update the timeout for select/ poll, because we - don't want to sit there while this timer is expiring. */ + /* Now we need to update the timeout for select/ poll, because + we don't want to sit there while this timer is expiring. */ if (use_poll) { #ifdef HAVE_POLL diff --git a/contrib/gdb-7/gdb/event-loop.h b/contrib/gdb-7/gdb/event-loop.h index 9a61d91cdc..54d83c469e 100644 --- a/contrib/gdb-7/gdb/event-loop.h +++ b/contrib/gdb-7/gdb/event-loop.h @@ -1,5 +1,5 @@ /* Definitions used by the GDB event loop. - Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. @@ -18,18 +18,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* An event loop listens for events from multiple event sources. When +/* An event loop listens for events from multiple event sources. When an event arrives, it is queued and processed by calling the - appropriate event handler. The event loop then continues to listen - for more events. An event loop completes when there are no event + appropriate event handler. The event loop then continues to listen + for more events. An event loop completes when there are no event sources to listen on. External event sources can be plugged into the loop. There are 4 main components: - - a list of file descriptors to be monitored, GDB_NOTIFIER. + - a list of file descriptors to be monitored, GDB_NOTIFIER. - a list of asynchronous event sources to be monitored, ASYNC_EVENT_HANDLER_LIST. - - a list of events that have occurred, EVENT_QUEUE. + - a list of events that have occurred, EVENT_QUEUE. - a list of signal handling functions, SIGHANDLER_LIST. GDB_NOTIFIER keeps track of the file descriptor based event @@ -64,9 +64,9 @@ functions that are invoked through traditional signal handlers. The actions to be taken is response to such events will be executed when the SIGHANDLER_LIST is scanned, the next time through the - infinite loop. + infinite loop. - Corollary tasks are the creation and deletion of event sources. */ + Corollary tasks are the creation and deletion of event sources. */ typedef void *gdb_client_data; struct async_signal_handler; @@ -76,14 +76,14 @@ typedef void (sig_handler_func) (gdb_client_data); typedef void (async_event_handler_func) (gdb_client_data); typedef void (timer_handler_func) (gdb_client_data); -/* Where to add an event onto the event queue, by queue_event. */ +/* Where to add an event onto the event queue, by queue_event. */ typedef enum { - /* Add at tail of queue. It will be processed in first in first - out order. */ + /* Add at tail of queue. It will be processed in first in first + out order. */ TAIL, - /* Add at head of queue. It will be processed in last in first out - order. */ + /* Add at head of queue. It will be processed in last in first + out order. */ HEAD } queue_position; @@ -93,11 +93,15 @@ queue_position; extern void start_event_loop (void); extern int gdb_do_one_event (void *data); extern void delete_file_handler (int fd); -extern void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data); +extern void add_file_handler (int fd, handler_func *proc, + gdb_client_data client_data); extern struct async_signal_handler * - create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data); -extern void delete_async_signal_handler (struct async_signal_handler **async_handler_ptr); -extern int create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data); + create_async_signal_handler (sig_handler_func *proc, + gdb_client_data client_data); +extern void delete_async_signal_handler (struct async_signal_handler **); +extern int create_timer (int milliseconds, + timer_handler_func *proc, + gdb_client_data client_data); extern void delete_timer (int id); /* Call the handler from HANDLER immediately. This function diff --git a/contrib/gdb-7/gdb/event-top.c b/contrib/gdb-7/gdb/event-top.c index 0fc7f899a0..660f137b08 100644 --- a/contrib/gdb-7/gdb/event-top.c +++ b/contrib/gdb-7/gdb/event-top.c @@ -1,7 +1,7 @@ /* Top level stuff for GDB, the GNU debugger. - Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. @@ -18,7 +18,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ #include "defs.h" #include "top.h" @@ -34,10 +34,9 @@ #include "main.h" #include "gdbthread.h" -/* For dont_repeat() */ -#include "gdbcmd.h" +#include "gdbcmd.h" /* for dont_repeat() */ -/* readline include files */ +/* readline include files. */ #include "readline/readline.h" #include "readline/history.h" @@ -50,7 +49,7 @@ static void change_line_handler (void); static void change_annotation_level (void); static void command_handler (char *command); -/* Signal handlers. */ +/* Signal handlers. */ #ifdef SIGQUIT static void handle_sigquit (int sig); #endif @@ -63,7 +62,7 @@ static void handle_sigwinch (int sig); #endif /* Functions to be invoked by the event loop in response to - signals. */ + signals. */ #if defined (SIGQUIT) || defined (SIGHUP) static void async_do_nothing (gdb_client_data); #endif @@ -76,65 +75,65 @@ static void async_stop_sig (gdb_client_data); #endif /* Readline offers an alternate interface, via callback - functions. These are all included in the file callback.c in the + functions. These are all included in the file callback.c in the readline distribution. This file provides (mainly) a function, which the event loop uses as callback (i.e. event handler) whenever an event is detected on the standard input file descriptor. readline_callback_read_char is called (by the GDB event loop) whenever - there is a new character ready on the input stream. This function + there is a new character ready on the input stream. This function incrementally builds a buffer internal to readline where it accumulates the line read up to the point of invocation. In the special case in which the character read is newline, the function invokes a GDB supplied callback routine, which does the processing of a full command line. This latter routine is the asynchronous analog - of the old command_line_input in gdb. Instead of invoking (and waiting + of the old command_line_input in gdb. Instead of invoking (and waiting for) readline to read the command line and pass it back to command_loop for processing, the new command_line_handler function has the command line already available as its parameter. INPUT_HANDLER is to be set to the function that readline will invoke when a complete line of input is ready. CALL_READLINE is to be set to the function - that readline offers as callback to the event_loop. */ + that readline offers as callback to the event_loop. */ void (*input_handler) (char *); void (*call_readline) (gdb_client_data); -/* Important variables for the event loop. */ +/* Important variables for the event loop. */ /* This is used to determine if GDB is using the readline library or - its own simplified form of readline. It is used by the asynchronous + its own simplified form of readline. It is used by the asynchronous form of the set editing command. ezannoni: as of 1999-04-29 I expect that this variable will not be used after gdb is changed to use the event - loop as default engine, and event-top.c is merged into top.c. */ + loop as default engine, and event-top.c is merged into top.c. */ int async_command_editing_p; /* This variable contains the new prompt that the user sets with the - set prompt command. */ + set prompt command. */ char *new_async_prompt; /* This is the annotation suffix that will be used when the - annotation_level is 2. */ + annotation_level is 2. */ char *async_annotation_suffix; /* This is used to display the notification of the completion of an - asynchronous execution command. */ + asynchronous execution command. */ int exec_done_display_p = 0; /* This is the file descriptor for the input stream that GDB uses to - read commands from. */ + read commands from. */ int input_fd; -/* This is the prompt stack. Prompts will be pushed on the stack as +/* This is the prompt stack. Prompts will be pushed on the stack as needed by the different 'kinds' of user inputs GDB is asking - for. See event-loop.h. */ + for. See event-loop.h. */ struct prompts the_prompts; -/* signal handling variables */ +/* Signal handling variables. */ /* Each of these is a pointer to a function that the event loop will - invoke if the corresponding signal has received. The real signal + invoke if the corresponding signal has received. The real signal handlers mark these functions as ready to be executed and the event - loop, in a later iteration, calls them. See the function - invoke_async_signal_handler. */ + loop, in a later iteration, calls them. See the function + invoke_async_signal_handler. */ void *sigint_token; #ifdef SIGHUP void *sighup_token; @@ -151,10 +150,10 @@ void *sigtstp_token; #endif /* Structure to save a partially entered command. This is used when - the user types '\' at the end of a command line. This is necessary + the user types '\' at the end of a command line. This is necessary because each line of input is handled by a different call to command_line_handler, and normally there is no state retained - between different calls. */ + between different calls. */ int more_to_come = 0; struct readline_input_state @@ -166,12 +165,12 @@ readline_input_state; /* This hook is called by rl_callback_read_char_wrapper after each character is processed. */ -void (*after_char_processing_hook) (); +void (*after_char_processing_hook) (void); -/* Wrapper function for calling into the readline library. The event - loop expects the callback function to have a paramter, while readline - expects none. */ +/* Wrapper function for calling into the readline library. The event + loop expects the callback function to have a paramter, while + readline expects none. */ static void rl_callback_read_char_wrapper (gdb_client_data client_data) { @@ -181,21 +180,21 @@ rl_callback_read_char_wrapper (gdb_client_data client_data) } /* Initialize all the necessary variables, start the event loop, - register readline, and stdin, start the loop. */ + register readline, and stdin, start the loop. */ void cli_command_loop (void) { /* If we are using readline, set things up and display the first - prompt, otherwise just print the prompt. */ + prompt, otherwise just print the prompt. */ if (async_command_editing_p) { int length; char *a_prompt; char *gdb_prompt = get_prompt (); - /* Tell readline what the prompt to display is and what function it - will need to call after a whole line is read. This also displays - the first prompt. */ + /* Tell readline what the prompt to display is and what function + it will need to call after a whole line is read. This also + displays the first prompt. */ length = strlen (PREFIX (0)) + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1; a_prompt = (char *) alloca (length); @@ -207,54 +206,54 @@ cli_command_loop (void) else display_gdb_prompt (0); - /* Now it's time to start the event loop. */ + /* Now it's time to start the event loop. */ start_event_loop (); } /* Change the function to be invoked every time there is a character - ready on stdin. This is used when the user sets the editing off, + ready on stdin. This is used when the user sets the editing off, therefore bypassing readline, and letting gdb handle the input - itself, via gdb_readline2. Also it is used in the opposite case in + itself, via gdb_readline2. Also it is used in the opposite case in which the user sets editing on again, by restoring readline - handling of the input. */ + handling of the input. */ static void change_line_handler (void) { - /* NOTE: this operates on input_fd, not instream. If we are reading - commands from a file, instream will point to the file. However in + /* NOTE: this operates on input_fd, not instream. If we are reading + commands from a file, instream will point to the file. However in async mode, we always read commands from a file with editing - off. This means that the 'set editing on/off' will have effect - only on the interactive session. */ + off. This means that the 'set editing on/off' will have effect + only on the interactive session. */ if (async_command_editing_p) { - /* Turn on editing by using readline. */ + /* Turn on editing by using readline. */ call_readline = rl_callback_read_char_wrapper; input_handler = command_line_handler; } else { - /* Turn off editing by using gdb_readline2. */ + /* Turn off editing by using gdb_readline2. */ rl_callback_handler_remove (); call_readline = gdb_readline2; /* Set up the command handler as well, in case we are called as - first thing from .gdbinit. */ + first thing from .gdbinit. */ input_handler = command_line_handler; } } /* Displays the prompt. The prompt that is displayed is the current top of the prompt stack, if the argument NEW_PROMPT is - 0. Otherwise, it displays whatever NEW_PROMPT is. This is used + 0. Otherwise, it displays whatever NEW_PROMPT is. This is used after each gdb command has completed, and in the following cases: - 1. when the user enters a command line which is ended by '\' + 1. When the user enters a command line which is ended by '\' indicating that the command will continue on the next line. In that case the prompt that is displayed is the empty string. 2. When the user is entering 'commands' for a breakpoint, or - actions for a tracepoint. In this case the prompt will be '>' + actions for a tracepoint. In this case the prompt will be '>' 3. Other???? - FIXME: 2. & 3. not implemented yet for async. */ + FIXME: 2. & 3. not implemented yet for async. */ void display_gdb_prompt (char *new_prompt) { @@ -276,15 +275,15 @@ display_gdb_prompt (char *new_prompt) function, readline still tries to do its own display if we don't call rl_callback_handler_install and rl_callback_handler_remove (which readline detects because a - global variable is not set). If readline did that, it could + global variable is not set). If readline did that, it could mess up gdb signal handlers for SIGINT. Readline assumes that between calls to rl_set_signals and rl_clear_signals gdb - doesn't do anything with the signal handlers. Well, that's + doesn't do anything with the signal handlers. Well, that's not the case, because when the target executes we change the - SIGINT signal handler. If we allowed readline to display the + SIGINT signal handler. If we allowed readline to display the prompt, the signal handler change would happen exactly between the calls to the above two functions. - Calling rl_callback_handler_remove(), does the job. */ + Calling rl_callback_handler_remove(), does the job. */ rl_callback_handler_remove (); return; @@ -292,18 +291,18 @@ display_gdb_prompt (char *new_prompt) if (!new_prompt) { - /* Just use the top of the prompt stack. */ + /* Just use the top of the prompt stack. */ prompt_length = strlen (PREFIX (0)) + strlen (SUFFIX (0)) + strlen (gdb_prompt) + 1; new_prompt = (char *) alloca (prompt_length); - /* Prefix needs to have new line at end. */ + /* Prefix needs to have new line at end. */ strcpy (new_prompt, PREFIX (0)); strcat (new_prompt, gdb_prompt); /* Suffix needs to have a new line at end and \032 \032 at - beginning. */ + beginning. */ strcat (new_prompt, SUFFIX (0)); } @@ -312,8 +311,9 @@ display_gdb_prompt (char *new_prompt) rl_callback_handler_remove (); rl_callback_handler_install (new_prompt, input_handler); } - /* new_prompt at this point can be the top of the stack or the one passed in */ - else if (new_prompt) + /* new_prompt at this point can be the top of the stack or the one + passed in. It can't be NULL. */ + else { /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from @@ -324,10 +324,10 @@ display_gdb_prompt (char *new_prompt) } /* Used when the user requests a different annotation level, with - 'set annotate'. It pushes a new prompt (with prefix and suffix) on top + 'set annotate'. It pushes a new prompt (with prefix and suffix) on top of the prompt stack, if the annotation level desired is 2, otherwise it pops the top of the prompt stack when we want the annotation level - to be the normal ones (1 or 0). */ + to be the normal ones (1 or 0). */ static void change_annotation_level (void) { @@ -336,7 +336,7 @@ change_annotation_level (void) if (!PREFIX (0) || !PROMPT (0) || !SUFFIX (0)) { /* The prompt stack has not been initialized to "", we are - using gdb w/o the --async switch */ + using gdb w/o the --async switch. */ warning (_("Command has same effect as set annotate")); return; } @@ -345,7 +345,7 @@ change_annotation_level (void) { if (!strcmp (PREFIX (0), "") && !strcmp (SUFFIX (0), "")) { - /* Push a new prompt if the previous annotation_level was not >1. */ + /* Push a new prompt if the previous annotation_level was not >1. */ prefix = (char *) alloca (strlen (async_annotation_suffix) + 10); strcpy (prefix, "\n\032\032pre-"); strcat (prefix, async_annotation_suffix); @@ -363,16 +363,16 @@ change_annotation_level (void) { if (strcmp (PREFIX (0), "") && strcmp (SUFFIX (0), "")) { - /* Pop the top of the stack, we are going back to annotation < 1. */ + /* Pop the top of the stack, we are going back to annotation < 1. */ pop_prompt (); } } } -/* Pushes a new prompt on the prompt stack. Each prompt has three - parts: prefix, prompt, suffix. Usually prefix and suffix are empty - strings, except when the annotation level is 2. Memory is allocated - within xstrdup for the new prompt. */ +/* Pushes a new prompt on the prompt stack. Each prompt has three + parts: prefix, prompt, suffix. Usually prefix and suffix are empty + strings, except when the annotation level is 2. Memory is allocated + within xstrdup for the new prompt. */ void push_prompt (char *prefix, char *prompt, char *suffix) { @@ -380,8 +380,8 @@ push_prompt (char *prefix, char *prompt, char *suffix) PREFIX (0) = xstrdup (prefix); /* Note that this function is used by the set annotate 2 - command. This is why we take care of saving the old prompt - in case a new one is not specified. */ + command. This is why we take care of saving the old prompt + in case a new one is not specified. */ if (prompt) PROMPT (0) = xstrdup (prompt); else @@ -390,17 +390,18 @@ push_prompt (char *prefix, char *prompt, char *suffix) SUFFIX (0) = xstrdup (suffix); } -/* Pops the top of the prompt stack, and frees the memory allocated for it. */ +/* Pops the top of the prompt stack, and frees the memory allocated + for it. */ void pop_prompt (void) { /* If we are not during a 'synchronous' execution command, in which - case, the top prompt would be empty. */ + case, the top prompt would be empty. */ if (strcmp (PROMPT (0), "")) /* This is for the case in which the prompt is set while the - annotation level is 2. The top prompt will be changed, but when + annotation level is 2. The top prompt will be changed, but when we return to annotation level < 2, we want that new prompt to be - in effect, until the user does another 'set prompt'. */ + in effect, until the user does another 'set prompt'. */ if (strcmp (PROMPT (0), PROMPT (-1))) { xfree (PROMPT (-1)); @@ -416,7 +417,7 @@ pop_prompt (void) /* When there is an event ready on the stdin file desriptor, instead of calling readline directly throught the callback function, or instead of calling gdb_readline2, give gdb a chance to detect - errors and do something. */ + errors and do something. */ void stdin_event_handler (int error, gdb_client_data client_data) { @@ -426,7 +427,7 @@ stdin_event_handler (int error, gdb_client_data client_data) delete_file_handler (input_fd); discard_all_continuations (); discard_all_intermediate_continuations (); - /* If stdin died, we may as well kill gdb. */ + /* If stdin died, we may as well kill gdb. */ quit_command ((char *) 0, stdin == instream); } else @@ -435,17 +436,17 @@ stdin_event_handler (int error, gdb_client_data client_data) /* Re-enable stdin after the end of an execution command in synchronous mode, or after an error from the target, and we aborted - the exec operation. */ + the exec operation. */ void async_enable_stdin (void) { if (sync_execution) { - /* See NOTE in async_disable_stdin() */ + /* See NOTE in async_disable_stdin(). */ /* FIXME: cagney/1999-09-27: Call this before clearing sync_execution. Current target_terminal_ours() implementations - check for sync_execution before switching the terminal. */ + check for sync_execution before switching the terminal. */ target_terminal_ours (); pop_prompt (); sync_execution = 0; @@ -453,7 +454,7 @@ async_enable_stdin (void) } /* Disable reads from stdin (the console) marking the command as - synchronous. */ + synchronous. */ void async_disable_stdin (void) @@ -466,12 +467,12 @@ async_disable_stdin (void) } -/* Handles a gdb command. This function is called by +/* Handles a gdb command. This function is called by command_line_handler, which has processed one or more input lines - into COMMAND. */ + into COMMAND. */ /* NOTE: 1999-04-30 This is the asynchronous version of the command_loop function. The command_loop function will be obsolete when we - switch to use the event loop at every execution of gdb. */ + switch to use the event loop at every execution of gdb. */ static void command_handler (char *command) { @@ -482,11 +483,11 @@ command_handler (char *command) if (instream == stdin && stdin_is_tty) reinitialize_more_filter (); - /* If readline returned a NULL command, it means that the - connection with the terminal is gone. This happens at the - end of a testsuite run, after Expect has hung up - but GDB is still alive. In such a case, we just quit gdb - killing the inferior program too. */ + /* If readline returned a NULL command, it means that the connection + with the terminal is gone. This happens at the end of a + testsuite run, after Expect has hung up but GDB is still alive. + In such a case, we just quit gdb killing the inferior program + too. */ if (command == 0) { printf_unfiltered ("quit\n"); @@ -503,14 +504,15 @@ command_handler (char *command) do_cleanups (stat_chain); } -/* Handle a complete line of input. This is called by the callback - mechanism within the readline library. Deal with incomplete commands - as well, by saving the partial input in a global buffer. */ +/* Handle a complete line of input. This is called by the callback + mechanism within the readline library. Deal with incomplete + commands as well, by saving the partial input in a global + buffer. */ /* NOTE: 1999-04-30 This is the asynchronous version of the - command_line_input function. command_line_input will become + command_line_input function; command_line_input will become obsolete once we use the event loop as the default mechanism in - GDB. */ + GDB. */ static void command_line_handler (char *rl) { @@ -555,7 +557,8 @@ command_line_handler (char *rl) #endif /* Make sure that all output has been output. Some machines may let - you get away with leaving out some of the gdb_flush, but not all. */ + you get away with leaving out some of the gdb_flush, but not + all. */ wrap_here (""); gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); @@ -564,12 +567,12 @@ command_line_handler (char *rl) ++source_line_number; /* If we are in this case, then command_handler will call quit - and exit from gdb. */ + and exit from gdb. */ if (!rl || rl == (char *) EOF) { got_eof = 1; command_handler (0); - return; /* Lint. */ + return; /* Lint. */ } if (strlen (rl) + 1 + (p - linebuffer) > linelength) { @@ -580,7 +583,7 @@ command_line_handler (char *rl) } p1 = rl; /* Copy line. Don't copy null at end. (Leaves line alone - if this was just a newline) */ + if this was just a newline). */ while (*p1) *p++ = *p1++; @@ -595,8 +598,8 @@ command_line_handler (char *rl) readline_input_state.linebuffer_ptr = p; /* We will not invoke a execute_command if there is more - input expected to complete the command. So, we need to - print an empty prompt here. */ + input expected to complete the command. So, we need to + print an empty prompt here. */ more_to_come = 1; push_prompt ("", "", ""); display_gdb_prompt (0); @@ -654,9 +657,8 @@ command_line_handler (char *rl) xfree (history_value); } - /* If we just got an empty line, and that is supposed - to repeat the previous command, return the value in the - global buffer. */ + /* If we just got an empty line, and that is supposed to repeat the + previous command, return the value in the global buffer. */ if (repeat && p == linebuffer && *p != '\\') { command_handler (line); @@ -686,7 +688,7 @@ command_line_handler (char *rl) and remove the '#'. The kill ring is probably better, but some people are in the habit of commenting things out. */ if (*p1 == '#') - *p1 = '\0'; /* Found a comment. */ + *p1 = '\0'; /* Found a comment. */ /* Save into global buffer if appropriate. */ if (repeat) @@ -711,11 +713,11 @@ command_line_handler (char *rl) } /* Does reading of input from terminal w/o the editing features - provided by the readline library. */ + provided by the readline library. */ -/* NOTE: 1999-04-30 Asynchronous version of gdb_readline. gdb_readline +/* NOTE: 1999-04-30 Asynchronous version of gdb_readline; gdb_readline will become obsolete when the event loop is made the default - execution for gdb. */ + execution for gdb. */ void gdb_readline2 (gdb_client_data client_data) { @@ -726,11 +728,11 @@ gdb_readline2 (gdb_client_data client_data) static int done_once = 0; /* Unbuffer the input stream, so that, later on, the calls to fgetc - fetch only one char at the time from the stream. The fgetc's will + fetch only one char at the time from the stream. The fgetc's will get up to the first newline, but there may be more chars in the - stream after '\n'. If we buffer the input and fgetc drains the + stream after '\n'. If we buffer the input and fgetc drains the stream, getting stuff beyond the newline as well, a select, done - afterwards will not trigger. */ + afterwards will not trigger. */ if (!done_once && !ISATTY (instream)) { setbuf (instream, NULL); @@ -742,9 +744,9 @@ gdb_readline2 (gdb_client_data client_data) /* We still need the while loop here, even though it would seem obvious to invoke gdb_readline2 at every character entered. If not using the readline library, the terminal is in cooked mode, - which sends the characters all at once. Poll will notice that the - input fd has changed state only after enter is pressed. At this - point we still need to fetch all the chars entered. */ + which sends the characters all at once. Poll will notice that the + input fd has changed state only after enter is pressed. At this + point we still need to fetch all the chars entered. */ while (1) { @@ -755,9 +757,9 @@ gdb_readline2 (gdb_client_data client_data) if (c == EOF) { if (input_index > 0) - /* The last line does not end with a newline. Return it, and - if we are called again fgetc will still return EOF and - we'll return NULL then. */ + /* The last line does not end with a newline. Return it, + and if we are called again fgetc will still return EOF + and we'll return NULL then. */ break; xfree (result); (*input_handler) (0); @@ -785,17 +787,17 @@ gdb_readline2 (gdb_client_data client_data) /* Initialization of signal handlers and tokens. There is a function - handle_sig* for each of the signals GDB cares about. Specifically: + handle_sig* for each of the signals GDB cares about. Specifically: SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These functions are the actual signal handlers associated to the signals via calls to signal(). The only job for these functions is to enqueue the appropriate event/procedure with the event loop. Such - procedures are the old signal handlers. The event loop will take + procedures are the old signal handlers. The event loop will take care of invoking the queued procedures to perform the usual tasks - associated with the reception of the signal. */ + associated with the reception of the signal. */ /* NOTE: 1999-04-30 This is the asynchronous version of init_signals. init_signals will become obsolete as we move to have to event loop - as the default for gdb. */ + as the default for gdb. */ void async_init_signals (void) { @@ -853,8 +855,8 @@ mark_async_signal_handler_wrapper (void *token) mark_async_signal_handler ((struct async_signal_handler *) token); } -/* Tell the event loop what to do if SIGINT is received. - See event-signal.c. */ +/* Tell the event loop what to do if SIGINT is received. + See event-signal.c. */ void handle_sigint (int sig) { @@ -862,19 +864,19 @@ handle_sigint (int sig) /* We could be running in a loop reading in symfiles or something so it may be quite a while before we get back to the event loop. So - set quit_flag to 1 here. Then if QUIT is called before we get to + set quit_flag to 1 here. Then if QUIT is called before we get to the event loop, we will unwind as expected. */ quit_flag = 1; /* If immediate_quit is set, we go ahead and process the SIGINT right - away, even if we usually would defer this to the event loop. The + away, even if we usually would defer this to the event loop. The assumption here is that it is safe to process ^C immediately if - immediate_quit is set. If we didn't, SIGINT would be really + immediate_quit is set. If we didn't, SIGINT would be really processed only the next time through the event loop. To get to that point, though, the command that we want to interrupt needs to finish first, which is unacceptable. If immediate quit is not set, - we process SIGINT the next time through the loop, which is fine. */ + we process SIGINT the next time through the loop, which is fine. */ gdb_call_async_signal_handler (sigint_token, immediate_quit); } @@ -887,7 +889,7 @@ handle_sigterm (int sig) quit_force ((char *) 0, stdin == instream); } -/* Do the quit. All the checks have been done by the caller. */ +/* Do the quit. All the checks have been done by the caller. */ void async_request_quit (gdb_client_data arg) { @@ -895,15 +897,15 @@ async_request_quit (gdb_client_data arg) back here, that means that an exception was thrown to unwind the current command before we got back to the event loop. So there is no reason to call quit again here, unless immediate_quit is - set.*/ + set. */ if (quit_flag || immediate_quit) quit (); } #ifdef SIGQUIT -/* Tell the event loop what to do if SIGQUIT is received. - See event-signal.c. */ +/* Tell the event loop what to do if SIGQUIT is received. + See event-signal.c. */ static void handle_sigquit (int sig) { @@ -918,13 +920,13 @@ handle_sigquit (int sig) static void async_do_nothing (gdb_client_data arg) { - /* Empty function body. */ + /* Empty function body. */ } #endif #ifdef SIGHUP -/* Tell the event loop what to do if SIGHUP is received. - See event-signal.c. */ +/* Tell the event loop what to do if SIGHUP is received. + See event-signal.c. */ static void handle_sighup (int sig) { @@ -932,14 +934,14 @@ handle_sighup (int sig) signal (sig, handle_sighup); } -/* Called by the event loop to process a SIGHUP */ +/* Called by the event loop to process a SIGHUP. */ static void async_disconnect (gdb_client_data arg) { catch_errors (quit_cover, NULL, "Could not kill the program being debugged", RETURN_MASK_ALL); - signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */ + signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */ raise (SIGHUP); } #endif @@ -977,13 +979,14 @@ async_stop_sig (gdb_client_data arg) printf_unfiltered ("%s", prompt); gdb_flush (gdb_stdout); - /* Forget about any previous command -- null line now will do nothing. */ + /* Forget about any previous command -- null line now will do + nothing. */ dont_repeat (); } #endif /* STOP_SIGNAL */ -/* Tell the event loop what to do if SIGFPE is received. - See event-signal.c. */ +/* Tell the event loop what to do if SIGFPE is received. + See event-signal.c. */ static void handle_sigfpe (int sig) { @@ -991,17 +994,17 @@ handle_sigfpe (int sig) signal (sig, handle_sigfpe); } -/* Event loop will call this functin to process a SIGFPE. */ +/* Event loop will call this functin to process a SIGFPE. */ static void async_float_handler (gdb_client_data arg) { - /* This message is based on ANSI C, section 4.7. Note that integer - divide by zero causes this, so "float" is a misnomer. */ + /* This message is based on ANSI C, section 4.7. Note that integer + divide by zero causes this, so "float" is a misnomer. */ error (_("Erroneous arithmetic operation.")); } -/* Tell the event loop what to do if SIGWINCH is received. - See event-signal.c. */ +/* Tell the event loop what to do if SIGWINCH is received. + See event-signal.c. */ #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) static void handle_sigwinch (int sig) @@ -1014,14 +1017,16 @@ handle_sigwinch (int sig) /* Called by do_setshow_command. */ void -set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c) +set_async_editing_command (char *args, int from_tty, + struct cmd_list_element *c) { change_line_handler (); } /* Called by do_setshow_command. */ void -set_async_annotation_level (char *args, int from_tty, struct cmd_list_element *c) +set_async_annotation_level (char *args, int from_tty, + struct cmd_list_element *c) { change_annotation_level (); } @@ -1035,7 +1040,7 @@ set_async_prompt (char *args, int from_tty, struct cmd_list_element *c) /* Set things up for readline to be invoked via the alternate interface, i.e. via a callback function (rl_callback_read_char), - and hook up instream to the event loop. */ + and hook up instream to the event loop. */ void gdb_setup_readline (void) { @@ -1048,12 +1053,13 @@ gdb_setup_readline (void) gdb_stderr = stdio_fileopen (stderr); gdb_stdlog = gdb_stderr; /* for moment */ gdb_stdtarg = gdb_stderr; /* for moment */ + gdb_stdtargerr = gdb_stderr; /* for moment */ /* If the input stream is connected to a terminal, turn on editing. */ if (ISATTY (instream)) { - /* Tell gdb that we will be using the readline library. This + /* Tell gdb that we will be using the readline library. This could be overwritten by a command in .gdbinit like 'set editing on' or 'off'. */ async_command_editing_p = 1; @@ -1069,11 +1075,11 @@ gdb_setup_readline (void) } /* When readline has read an end-of-line character, it passes the - complete line to gdb for processing. command_line_handler is the + complete line to gdb for processing; command_line_handler is the function that does this. */ input_handler = command_line_handler; - /* Tell readline to use the same input stream that gdb uses. */ + /* Tell readline to use the same input stream that gdb uses. */ rl_instream = instream; /* Get a file descriptor for the input stream, so that we can @@ -1083,7 +1089,7 @@ gdb_setup_readline (void) /* Now we need to create the event sources for the input file descriptor. */ /* At this point in time, this is the only event source that we - register with the even loop. Another source is going to be the + register with the even loop. Another source is going to be the target program (inferior), but that must be registered only when it actually exists (I.e. after we say 'run' or after we connect to a remote target. */ @@ -1106,6 +1112,7 @@ gdb_disable_readline (void) ui_file_delete (gdb_stderr); gdb_stdlog = NULL; gdb_stdtarg = NULL; + gdb_stdtargerr = NULL; #endif rl_callback_handler_remove (); diff --git a/contrib/gdb-7/gdb/event-top.h b/contrib/gdb-7/gdb/event-top.h index 725eae2997..8550164423 100644 --- a/contrib/gdb-7/gdb/event-top.h +++ b/contrib/gdb-7/gdb/event-top.h @@ -1,6 +1,6 @@ /* Definitions used by event-top.c, for GDB, the GNU debugger. - Copyright (C) 1999, 2001, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2001, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. @@ -73,7 +73,7 @@ struct prompts #define PREFIX(X) the_prompts.prompt_stack[the_prompts.top + X].prefix #define SUFFIX(X) the_prompts.prompt_stack[the_prompts.top + X].suffix -/* Exported functions from event-top.c. +/* Exported functions from event-top.c. FIXME: these should really go into top.h. */ extern void display_gdb_prompt (char *new_prompt); diff --git a/contrib/gdb-7/gdb/exceptions.c b/contrib/gdb-7/gdb/exceptions.c index ec9b9be62e..099ef0d2b1 100644 --- a/contrib/gdb-7/gdb/exceptions.c +++ b/contrib/gdb-7/gdb/exceptions.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -89,7 +89,7 @@ exceptions_state_mc_init (struct ui_out *func_uiout, uiout = func_uiout; /* Prevent error/quit during FUNC from calling cleanups established - prior to here. */ + prior to here. */ new_catcher->saved_cleanup_chain = save_cleanups (); /* Push this new catcher on the top. */ @@ -108,7 +108,7 @@ catcher_pop (void) current_catcher = old_catcher->prev; /* Restore the cleanup chain, the error/quit messages, and the uiout - builder, to their original states. */ + builder, to their original states. */ restore_cleanups (old_catcher->saved_cleanup_chain); @@ -186,7 +186,7 @@ exceptions_state_mc (enum catcher_action action) } /* The caller didn't request that the event be caught, relay the event to the next containing - catch_errors(). */ + catch_errors(). */ catcher_pop (); throw_exception (exception); } @@ -226,14 +226,17 @@ throw_exception (struct gdb_exception exception) /* Perhaps it would be cleaner to do this via the cleanup chain (not sure I can think of a reason why that is vital, though). */ if (tp != NULL) - bpstat_clear_actions (tp->stop_bpstat); /* Clear queued breakpoint commands */ + { + /* Clear queued breakpoint commands. */ + bpstat_clear_actions (tp->control.stop_bpstat); + } disable_current_display (); do_cleanups (ALL_CLEANUPS); /* Jump to the containing catch_errors() call, communicating REASON to that call via setjmp's return value. Note that REASON can't - be zero, by definition in defs.h. */ + be zero, by definition in defs.h. */ exceptions_state_mc (CATCH_THROWING); *current_catcher->exception = exception; EXCEPTIONS_SIGLONGJMP (current_catcher->buf, exception.reason); @@ -367,7 +370,7 @@ print_any_exception (struct ui_file *file, const char *prefix, if (e.reason < 0 && e.message != NULL) { target_terminal_ours (); - wrap_here (""); /* Force out any buffered output */ + wrap_here (""); /* Force out any buffered output. */ gdb_flush (gdb_stdout); annotate_error_begin (); @@ -439,12 +442,12 @@ throw_error (enum errors error, const char *fmt, ...) be replaced by judicious use of QUIT. */ /* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with - error() et.al. could maintain a set of flags that indicate the the + error() et al. could maintain a set of flags that indicate the the current state of each of the longjmp buffers. This would give the longjmp code the chance to detect a longjmp botch (before it gets to longjmperror()). Prior to 1999-11-05 this wasn't possible as code also randomly used a SET_TOP_LEVEL macro that directly - initialize the longjmp buffers. */ + initialized the longjmp buffers. */ int catch_exceptions (struct ui_out *uiout, diff --git a/contrib/gdb-7/gdb/exceptions.h b/contrib/gdb-7/gdb/exceptions.h index 7d68a36a21..b1c45878c1 100644 --- a/contrib/gdb-7/gdb/exceptions.h +++ b/contrib/gdb-7/gdb/exceptions.h @@ -2,7 +2,7 @@ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -49,9 +49,12 @@ typedef int return_mask; enum errors { GDB_NO_ERROR, + /* Any generic error, the corresponding text is in exception.message. */ GENERIC_ERROR, + + /* Something requested was not found. */ NOT_FOUND_ERROR, /* Thread library lacks support necessary for finding thread local @@ -78,6 +81,10 @@ enum errors { /* Feature is not supported in this copy of GDB. */ UNSUPPORTED_ERROR, + /* Value not available. E.g., a register was not collected in a + traceframe. */ + NOT_AVAILABLE_ERROR, + /* Add more errors here. */ NR_ERRORS }; @@ -108,8 +115,8 @@ extern const struct gdb_exception exception_none; /* Functions to drive the exceptions state m/c (internal to exceptions). */ EXCEPTIONS_SIGJMP_BUF *exceptions_state_mc_init (struct ui_out *func_uiout, - volatile struct gdb_exception * - exception, + volatile struct + gdb_exception *exception, return_mask mask); int exceptions_state_mc_action_iter (void); int exceptions_state_mc_action_iter_1 (void); @@ -149,7 +156,7 @@ int exceptions_state_mc_action_iter_1 (void); /* If E is an exception, print it's error message on the specified - stream. for _fprintf, prefix the message with PREFIX... */ + stream. For _fprintf, prefix the message with PREFIX... */ extern void exception_print (struct ui_file *file, struct gdb_exception e); extern void exception_fprintf (struct ui_file *file, struct gdb_exception e, const char *prefix, @@ -166,7 +173,8 @@ extern void exception_fprintf (struct ui_file *file, struct gdb_exception e, be a good thing or a dangerous thing.'' -- the Existential Wombat. */ -extern void throw_exception (struct gdb_exception exception) ATTRIBUTE_NORETURN; +extern void throw_exception (struct gdb_exception exception) + ATTRIBUTE_NORETURN; extern void throw_verror (enum errors, const char *fmt, va_list ap) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0); extern void throw_vfatal (const char *fmt, va_list ap) @@ -235,9 +243,9 @@ extern struct gdb_exception catch_exception (struct ui_out *uiout, return_mask mask); /* If CATCH_ERRORS_FTYPE throws an error, catch_errors() returns zero - otherwize the result from CATCH_ERRORS_FTYPE is returned. It is + otherwize the result from CATCH_ERRORS_FTYPE is returned. It is probably useful for CATCH_ERRORS_FTYPE to always return a non-zero - value. It's unfortunate that, catch_errors() does not return an + value. It's unfortunate that, catch_errors() does not return an indication of the exact exception that it caught - quit_flag might help. @@ -247,9 +255,10 @@ typedef int (catch_errors_ftype) (void *); extern int catch_errors (catch_errors_ftype *, void *, char *, return_mask); /* Template to catch_errors() that wraps calls to command - functions. */ + functions. */ typedef void (catch_command_errors_ftype) (char *, int); -extern int catch_command_errors (catch_command_errors_ftype *func, char *command, int from_tty, return_mask); +extern int catch_command_errors (catch_command_errors_ftype *func, + char *command, int from_tty, return_mask); #endif diff --git a/contrib/gdb-7/gdb/exec.c b/contrib/gdb-7/gdb/exec.c index f9977a8ed6..a2da9d5297 100644 --- a/contrib/gdb-7/gdb/exec.c +++ b/contrib/gdb-7/gdb/exec.c @@ -1,7 +1,7 @@ /* Work with executable files, for GDB. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -25,6 +25,7 @@ #include "target.h" #include "gdbcmd.h" #include "language.h" +#include "filenames.h" #include "symfile.h" #include "objfiles.h" #include "completer.h" @@ -130,7 +131,7 @@ exec_close_1 (int quitting) nxt = vp->nxt; /* if there is an objfile associated with this bfd, - free_objfile() will do proper cleanup of objfile *and* bfd. */ + free_objfile() will do proper cleanup of objfile *and* bfd. */ if (vp->objfile) { @@ -247,7 +248,7 @@ exec_file_attach (char *filename, int from_tty) /* At this point, scratch_pathname and exec_bfd->name both point to the same malloc'd string. However exec_close() will attempt to free it via the exec_bfd->name pointer, so we need to make another copy and - leave exec_bfd as the new owner of the original copy. */ + leave exec_bfd as the new owner of the original copy. */ scratch_pathname = xstrdup (scratch_pathname); cleanups = make_cleanup (xfree, scratch_pathname); @@ -264,7 +265,7 @@ exec_file_attach (char *filename, int from_tty) /* FIXME - This should only be run for RS6000, but the ifdef is a poor way to accomplish. */ #ifdef DEPRECATED_IBM6000_TARGET - /* Setup initial vmap. */ + /* Setup initial vmap. */ map_vmap (exec_bfd, 0); if (vmap == NULL) @@ -314,7 +315,7 @@ exec_file_attach (char *filename, int from_tty) be called from file_command(), which also calls symbol_file_command() which can take multiple args. - If ARGS is NULL, we just want to close the exec file. */ + If ARGS is NULL, we just want to close the exec file. */ static void exec_file_command (char *args, int from_tty) @@ -353,7 +354,7 @@ exec_file_command (char *args, int from_tty) exec_file_attach (NULL, from_tty); } -/* Set both the exec file and the symbol file, in one command. +/* Set both the exec file and the symbol file, in one command. What a novelty. Why did GDB go through four major releases before this command was added? */ @@ -369,7 +370,7 @@ file_command (char *arg, int from_tty) } -/* Locate all mappable sections of a BFD file. +/* Locate all mappable sections of a BFD file. table_pp_char is a char * to get it through bfd_map_over_sections; we cast it back to its proper type. */ @@ -439,7 +440,8 @@ build_section_table (struct bfd *some_bfd, struct target_section **start, *end = *start; bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end); if (*end > *start + count) - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); /* We could realloc the table, but it probably loses for most files. */ return 0; } @@ -539,7 +541,7 @@ bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3) vp->dend = vp->dstart + bfd_section_size (abfd, sect); vp->dvma = bfd_section_vma (abfd, sect); } - /* Silently ignore other types of sections. (FIXME?) */ + /* Silently ignore other types of sections. (FIXME?) */ } /* Make a vmap for ABFD which might be a member of the archive ARCH. @@ -562,7 +564,7 @@ map_vmap (bfd *abfd, bfd *arch) vmap_bfd.pvmap = vp; bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd); - /* Find the end of the list and append. */ + /* Find the end of the list and append. */ for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt) ; *vpp = vp; @@ -571,6 +573,42 @@ map_vmap (bfd *abfd, bfd *arch) } +VEC(mem_range_s) * +section_table_available_memory (VEC(mem_range_s) *memory, + CORE_ADDR memaddr, ULONGEST len, + struct target_section *sections, + struct target_section *sections_end) +{ + struct target_section *p; + + for (p = sections; p < sections_end; p++) + { + if ((bfd_get_section_flags (p->bfd, p->the_bfd_section) + & SEC_READONLY) == 0) + continue; + + /* Copy the meta-data, adjusted. */ + if (mem_ranges_overlap (p->addr, p->endaddr - p->addr, memaddr, len)) + { + ULONGEST lo1, hi1, lo2, hi2; + struct mem_range *r; + + lo1 = memaddr; + hi1 = memaddr + len; + + lo2 = p->addr; + hi2 = p->endaddr; + + r = VEC_safe_push (mem_range_s, memory, NULL); + + r->start = max (lo1, lo2); + r->length = min (hi1, hi2) - r->start; + } + } + + return memory; +} + int section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len, @@ -584,12 +622,13 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST memend = memaddr + len; if (len <= 0) - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); for (p = sections; p < sections_end; p++) { if (section_name && strcmp (section_name, p->the_bfd_section->name) != 0) - continue; /* not the section we need */ + continue; /* not the section we need. */ if (memaddr >= p->addr) { if (memend <= p->endaddr) @@ -627,7 +666,7 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, } } - return 0; /* We can't help */ + return 0; /* We can't help. */ } struct target_section_table * @@ -668,7 +707,8 @@ print_section_info (struct target_section_table *t, bfd *abfd) printf_filtered (_("file type %s.\n"), bfd_get_target (abfd)); if (abfd == exec_bfd) { - /* gcc-3.4 does not like the initialization in

sections_end>. */ + /* gcc-3.4 does not like the initialization in +

sections_end>. */ bfd_vma displacement = 0; bfd_vma entry_point; @@ -689,7 +729,7 @@ print_section_info (struct target_section_table *t, bfd *abfd) } } if (p == t->sections_end) - warning (_("Cannot find section for the entry point of %s.\n"), + warning (_("Cannot find section for the entry point of %s."), bfd_get_filename (abfd)); entry_point = gdbarch_addr_bits_remove (gdbarch, @@ -712,7 +752,8 @@ print_section_info (struct target_section_table *t, bfd *abfd) if (info_verbose) printf_filtered (" @ %s", hex_string_custom (p->the_bfd_section->filepos, 8)); - printf_filtered (" is %s", bfd_section_name (p->bfd, p->the_bfd_section)); + printf_filtered (" is %s", bfd_section_name (p->bfd, + p->the_bfd_section)); if (p->bfd != abfd) printf_filtered (" in %s", bfd_get_filename (p->bfd)); printf_filtered ("\n"); @@ -764,17 +805,18 @@ set_section_command (char *args, int from_tty) if (args == 0) error (_("Must specify section name and its virtual address")); - /* Parse out section name */ + /* Parse out section name. */ for (secname = args; !isspace (*args); args++); seclen = args - secname; - /* Parse out new virtual address */ + /* Parse out new virtual address. */ secaddr = parse_and_eval_address (args); table = current_target_sections; for (p = table->sections; p < table->sections_end; p++) { - if (!strncmp (secname, bfd_section_name (exec_bfd, p->the_bfd_section), seclen) + if (!strncmp (secname, bfd_section_name (exec_bfd, + p->the_bfd_section), seclen) && bfd_section_name (exec_bfd, p->the_bfd_section)[seclen] == '\0') { offset = secaddr - p->addr; @@ -804,7 +846,7 @@ exec_set_section_address (const char *filename, int index, CORE_ADDR address) table = current_target_sections; for (p = table->sections; p < table->sections_end; p++) { - if (strcmp (filename, p->bfd->filename) == 0 + if (filename_cmp (filename, p->bfd->filename) == 0 && index == p->the_bfd_section->index) { p->endaddr += address - p->addr; @@ -832,14 +874,10 @@ exec_has_memory (struct target_ops *ops) != current_target_sections->sections_end); } -/* Find mapped memory. */ +/* Find mapped memory. */ extern void -exec_set_find_memory_regions (int (*func) (int (*) (CORE_ADDR, - unsigned long, - int, int, int, - void *), - void *)) +exec_set_find_memory_regions (int (*func) (find_memory_region_ftype, void *)) { exec_ops.to_find_memory_regions = func; } diff --git a/contrib/gdb-7/gdb/exec.h b/contrib/gdb-7/gdb/exec.h index 89d14d556c..89fd1565f7 100644 --- a/contrib/gdb-7/gdb/exec.h +++ b/contrib/gdb-7/gdb/exec.h @@ -1,6 +1,7 @@ /* Work with executable files, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +23,7 @@ #include "target.h" #include "progspace.h" +#include "memrange.h" struct target_section; struct target_ops; @@ -43,6 +45,17 @@ extern int build_section_table (struct bfd *, struct target_section **, extern int resize_section_table (struct target_section_table *, int); +/* Appends all read-only memory ranges found in the target section + table defined by SECTIONS and SECTIONS_END, starting at (and + intersected with) MEMADDR for LEN bytes. Returns the augmented + VEC. */ + +extern VEC(mem_range_s) * + section_table_available_memory (VEC(mem_range_s) *ranges, + CORE_ADDR memaddr, ULONGEST len, + struct target_section *sections, + struct target_section *sections_end); + /* Read or write from mappable sections of BFD executable files. Request to transfer up to LEN 8-bit bytes of the target sections diff --git a/contrib/gdb-7/gdb/expprint.c b/contrib/gdb-7/gdb/expprint.c index ee9b4f9a99..a52dee3a91 100644 --- a/contrib/gdb-7/gdb/expprint.c +++ b/contrib/gdb-7/gdb/expprint.c @@ -1,7 +1,7 @@ /* Print in infix form a struct expression. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2003, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -205,7 +205,8 @@ print_subexp_standard (struct expression *exp, int *pos, fprintf_unfiltered (stream, "B''"); return; - case OP_OBJC_NSSTRING: /* Objective-C Foundation Class NSString constant. */ + case OP_OBJC_NSSTRING: /* Objective-C Foundation Class + NSString constant. */ { struct value_print_options opts; @@ -254,7 +255,7 @@ print_subexp_standard (struct expression *exp, int *pos, fprintf_unfiltered (stream, " %s", selector); } fprintf_unfiltered (stream, "]"); - /* "selector" was malloc'd by target_read_string. Free it. */ + /* "selector" was malloc'd by target_read_string. Free it. */ xfree (selector); return; } @@ -276,7 +277,7 @@ print_subexp_standard (struct expression *exp, int *pos, does not match our expection of what we should find for a simple string, revert back to array printing. Note that the last expression element is an explicit null terminator - byte, which doesn't get printed. */ + byte, which doesn't get printed. */ tempstr = alloca (nargs); pc += 4; while (tem < nargs) @@ -285,7 +286,8 @@ print_subexp_standard (struct expression *exp, int *pos, || exp->elts[pc + 1].type != builtin_type (exp->gdbarch)->builtin_char) { - /* Not a simple array of char, use regular array printing. */ + /* Not a simple array of char, use regular array + printing. */ tem = 0; break; } @@ -370,7 +372,7 @@ print_subexp_standard (struct expression *exp, int *pos, fputs_filtered (&exp->elts[pc + 2].string, stream); return; - /* Will not occur for Modula-2 */ + /* Will not occur for Modula-2. */ case STRUCTOP_PTR: tem = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); @@ -532,6 +534,27 @@ print_subexp_standard (struct expression *exp, int *pos, fprintf_unfiltered (stream, ")"); return; + case TYPE_INSTANCE: + { + LONGEST count = exp->elts[pc + 1].longconst; + + /* The COUNT. */ + (*pos)++; + fputs_unfiltered ("TypesInstance(", stream); + while (count-- > 0) + { + type_print (exp->elts[(*pos)++].type, "", stream, 0); + if (count > 0) + fputs_unfiltered (",", stream); + } + fputs_unfiltered (",", stream); + /* Ending COUNT and ending TYPE_INSTANCE. */ + (*pos) += 2; + print_subexp (exp, pos, stream, PREC_PREFIX); + fputs_unfiltered (")", stream); + return; + } + /* Default ops */ default: @@ -551,7 +574,7 @@ print_subexp_standard (struct expression *exp, int *pos, error (_("Invalid expression")); } - /* Note that PREC_BUILTIN will always emit parentheses. */ + /* Note that PREC_BUILTIN will always emit parentheses. */ if ((int) myprec < (int) prec) fputs_filtered ("(", stream); if ((int) opcode > (int) BINOP_END) @@ -621,7 +644,7 @@ op_string (enum exp_opcode op) static char *op_name (struct expression *, enum exp_opcode); static int dump_subexp_body (struct expression *exp, struct ui_file *, int); -/* Name for OPCODE, when it appears in expression EXP. */ +/* Name for OPCODE, when it appears in expression EXP. */ static char * op_name (struct expression *exp, enum exp_opcode opcode) @@ -644,176 +667,11 @@ op_name_standard (enum exp_opcode opcode) sprintf (buf, "", opcode); return buf; } - case OP_NULL: - return "OP_NULL"; - case BINOP_ADD: - return "BINOP_ADD"; - case BINOP_SUB: - return "BINOP_SUB"; - case BINOP_MUL: - return "BINOP_MUL"; - case BINOP_DIV: - return "BINOP_DIV"; - case BINOP_REM: - return "BINOP_REM"; - case BINOP_MOD: - return "BINOP_MOD"; - case BINOP_LSH: - return "BINOP_LSH"; - case BINOP_RSH: - return "BINOP_RSH"; - case BINOP_LOGICAL_AND: - return "BINOP_LOGICAL_AND"; - case BINOP_LOGICAL_OR: - return "BINOP_LOGICAL_OR"; - case BINOP_BITWISE_AND: - return "BINOP_BITWISE_AND"; - case BINOP_BITWISE_IOR: - return "BINOP_BITWISE_IOR"; - case BINOP_BITWISE_XOR: - return "BINOP_BITWISE_XOR"; - case BINOP_EQUAL: - return "BINOP_EQUAL"; - case BINOP_NOTEQUAL: - return "BINOP_NOTEQUAL"; - case BINOP_LESS: - return "BINOP_LESS"; - case BINOP_GTR: - return "BINOP_GTR"; - case BINOP_LEQ: - return "BINOP_LEQ"; - case BINOP_GEQ: - return "BINOP_GEQ"; - case BINOP_REPEAT: - return "BINOP_REPEAT"; - case BINOP_ASSIGN: - return "BINOP_ASSIGN"; - case BINOP_COMMA: - return "BINOP_COMMA"; - case BINOP_SUBSCRIPT: - return "BINOP_SUBSCRIPT"; - case MULTI_SUBSCRIPT: - return "MULTI_SUBSCRIPT"; - case BINOP_EXP: - return "BINOP_EXP"; - case BINOP_MIN: - return "BINOP_MIN"; - case BINOP_MAX: - return "BINOP_MAX"; - case STRUCTOP_MEMBER: - return "STRUCTOP_MEMBER"; - case STRUCTOP_MPTR: - return "STRUCTOP_MPTR"; - case BINOP_INTDIV: - return "BINOP_INTDIV"; - case BINOP_ASSIGN_MODIFY: - return "BINOP_ASSIGN_MODIFY"; - case BINOP_VAL: - return "BINOP_VAL"; - case BINOP_CONCAT: - return "BINOP_CONCAT"; - case BINOP_RANGE: - return "BINOP_RANGE"; - case BINOP_END: - return "BINOP_END"; - case TERNOP_COND: - return "TERNOP_COND"; - case TERNOP_SLICE: - return "TERNOP_SLICE"; - case TERNOP_SLICE_COUNT: - return "TERNOP_SLICE_COUNT"; - case OP_LONG: - return "OP_LONG"; - case OP_DOUBLE: - return "OP_DOUBLE"; - case OP_VAR_VALUE: - return "OP_VAR_VALUE"; - case OP_LAST: - return "OP_LAST"; - case OP_REGISTER: - return "OP_REGISTER"; - case OP_INTERNALVAR: - return "OP_INTERNALVAR"; - case OP_FUNCALL: - return "OP_FUNCALL"; - case OP_STRING: - return "OP_STRING"; - case OP_BITSTRING: - return "OP_BITSTRING"; - case OP_ARRAY: - return "OP_ARRAY"; - case UNOP_CAST: - return "UNOP_CAST"; - case UNOP_DYNAMIC_CAST: - return "UNOP_DYNAMIC_CAST"; - case UNOP_REINTERPRET_CAST: - return "UNOP_REINTERPRET_CAST"; - case UNOP_MEMVAL: - return "UNOP_MEMVAL"; - case UNOP_MEMVAL_TLS: - return "UNOP_MEMVAL_TLS"; - case UNOP_NEG: - return "UNOP_NEG"; - case UNOP_LOGICAL_NOT: - return "UNOP_LOGICAL_NOT"; - case UNOP_COMPLEMENT: - return "UNOP_COMPLEMENT"; - case UNOP_IND: - return "UNOP_IND"; - case UNOP_ADDR: - return "UNOP_ADDR"; - case UNOP_PREINCREMENT: - return "UNOP_PREINCREMENT"; - case UNOP_POSTINCREMENT: - return "UNOP_POSTINCREMENT"; - case UNOP_PREDECREMENT: - return "UNOP_PREDECREMENT"; - case UNOP_POSTDECREMENT: - return "UNOP_POSTDECREMENT"; - case UNOP_SIZEOF: - return "UNOP_SIZEOF"; - case UNOP_PLUS: - return "UNOP_PLUS"; - case UNOP_CAP: - return "UNOP_CAP"; - case UNOP_CHR: - return "UNOP_CHR"; - case UNOP_ORD: - return "UNOP_ORD"; - case UNOP_ABS: - return "UNOP_ABS"; - case UNOP_FLOAT: - return "UNOP_FLOAT"; - case UNOP_HIGH: - return "UNOP_HIGH"; - case UNOP_MAX: - return "UNOP_MAX"; - case UNOP_MIN: - return "UNOP_MIN"; - case UNOP_ODD: - return "UNOP_ODD"; - case UNOP_TRUNC: - return "UNOP_TRUNC"; - case OP_BOOL: - return "OP_BOOL"; - case OP_M2_STRING: - return "OP_M2_STRING"; - case STRUCTOP_STRUCT: - return "STRUCTOP_STRUCT"; - case STRUCTOP_PTR: - return "STRUCTOP_PTR"; - case OP_THIS: - return "OP_THIS"; - case OP_OBJC_SELF: - return "OP_OBJC_SELF"; - case OP_SCOPE: - return "OP_SCOPE"; - case OP_TYPE: - return "OP_TYPE"; - case OP_LABELED: - return "OP_LABELED"; - case OP_ADL_FUNC: - return "OP_ADL_FUNC"; +#define OP(name) \ + case name: \ + return #name ; +#include "std-operator.def" +#undef OP } } @@ -909,6 +767,7 @@ dump_subexp_body_standard (struct expression *exp, case TERNOP_SLICE: case TERNOP_SLICE_COUNT: elt = dump_subexp (exp, stream, elt); + /* FALL THROUGH */ case BINOP_ADD: case BINOP_SUB: case BINOP_MUL: @@ -945,6 +804,7 @@ dump_subexp_body_standard (struct expression *exp, case STRUCTOP_MEMBER: case STRUCTOP_MPTR: elt = dump_subexp (exp, stream, elt); + /* FALL THROUGH */ case UNOP_NEG: case UNOP_LOGICAL_NOT: case UNOP_COMPLEMENT: @@ -1100,6 +960,29 @@ dump_subexp_body_standard (struct expression *exp, elt += 4 + BYTES_TO_EXP_ELEM (len + 1); } break; + case TYPE_INSTANCE: + { + char *elem_name; + LONGEST len; + + len = exp->elts[elt++].longconst; + fprintf_filtered (stream, "%s TypeInstance: ", plongest (len)); + while (len-- > 0) + { + fprintf_filtered (stream, "Type @"); + gdb_print_host_address (exp->elts[elt].type, stream); + fprintf_filtered (stream, " ("); + type_print (exp->elts[elt].type, NULL, stream, 0); + fprintf_filtered (stream, ")"); + elt++; + if (len > 0) + fputs_filtered (", ", stream); + } + /* Ending LEN and ending TYPE_INSTANCE. */ + elt += 2; + elt = dump_subexp (exp, stream, elt); + } + break; default: case OP_NULL: case MULTI_SUBSCRIPT: diff --git a/contrib/gdb-7/gdb/expression.h b/contrib/gdb-7/gdb/expression.h index a6f966a8ee..45f336e2b2 100644 --- a/contrib/gdb-7/gdb/expression.h +++ b/contrib/gdb-7/gdb/expression.h @@ -1,7 +1,7 @@ /* Definitions for expressions stored in reversed prefix form, for GDB. Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -22,7 +22,7 @@ #define EXPRESSION_H 1 -#include "symtab.h" /* Needed for "struct block" type. */ +#include "symtab.h" /* Needed for "struct block" type. */ #include "doublest.h" /* Needed for DOUBLEST. */ @@ -43,328 +43,19 @@ enum exp_opcode { - /* Used when it's necessary to pass an opcode which will be ignored, - or to catch uninitialized values. */ - OP_NULL, - -/* BINOP_... operate on two values computed by following subexpressions, - replacing them by one result value. They take no immediate arguments. */ - - BINOP_ADD, /* + */ - BINOP_SUB, /* - */ - BINOP_MUL, /* * */ - BINOP_DIV, /* / */ - BINOP_REM, /* % */ - BINOP_MOD, /* mod (Knuth 1.2.4) */ - BINOP_LSH, /* << */ - BINOP_RSH, /* >> */ - BINOP_LOGICAL_AND, /* && */ - BINOP_LOGICAL_OR, /* || */ - BINOP_BITWISE_AND, /* & */ - BINOP_BITWISE_IOR, /* | */ - BINOP_BITWISE_XOR, /* ^ */ - BINOP_EQUAL, /* == */ - BINOP_NOTEQUAL, /* != */ - BINOP_LESS, /* < */ - BINOP_GTR, /* > */ - BINOP_LEQ, /* <= */ - BINOP_GEQ, /* >= */ - BINOP_REPEAT, /* @ */ - BINOP_ASSIGN, /* = */ - BINOP_COMMA, /* , */ - BINOP_SUBSCRIPT, /* x[y] */ - BINOP_EXP, /* Exponentiation */ - - /* C++. */ - - BINOP_MIN, /* ? */ - - /* STRUCTOP_MEMBER is used for pointer-to-member constructs. - X . * Y translates into X STRUCTOP_MEMBER Y. */ - STRUCTOP_MEMBER, - - /* STRUCTOP_MPTR is used for pointer-to-member constructs - when X is a pointer instead of an aggregate. */ - STRUCTOP_MPTR, - - /* TYPE_INSTANCE is used when the user specifies a specific - type instantiation for overloaded methods/functions. - - The format is: - TYPE_INSTANCE num_types type0 ... typeN num_types TYPE_INSTANCE */ - TYPE_INSTANCE, - - /* end of C++. */ - - /* For Modula-2 integer division DIV */ - BINOP_INTDIV, - - BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on. - The following exp_element is another opcode, - a BINOP_, saying how to modify. - Then comes another BINOP_ASSIGN_MODIFY, - making three exp_elements in total. */ - - /* Modula-2 standard (binary) procedures */ - BINOP_VAL, - - /* Concatenate two operands, such as character strings or bitstrings. - If the first operand is a integer expression, then it means concatenate - the second operand with itself that many times. */ - BINOP_CONCAT, - - /* For (the deleted) Chill and Pascal. */ - BINOP_IN, /* Returns 1 iff ARG1 IN ARG2. */ - - /* This is the "colon operator" used various places in (the - deleted) Chill. */ - BINOP_RANGE, - - /* This must be the highest BINOP_ value, for expprint.c. */ - BINOP_END, - - /* Operates on three values computed by following subexpressions. */ - TERNOP_COND, /* ?: */ - - /* A sub-string/sub-array. (the deleted) Chill syntax: - OP1(OP2:OP3). Return elements OP2 through OP3 of OP1. */ - TERNOP_SLICE, - - /* A sub-string/sub-array. (The deleted) Chill syntax: OP1(OP2 UP - OP3). Return OP3 elements of OP1, starting with element - OP2. */ - TERNOP_SLICE_COUNT, - - /* Multidimensional subscript operator, such as Modula-2 x[a,b,...]. - The dimensionality is encoded in the operator, like the number of - function arguments in OP_FUNCALL, I.E. . - The value of the first following subexpression is subscripted - by each of the next following subexpressions, one per dimension. */ - MULTI_SUBSCRIPT, - - /* The OP_... series take immediate following arguments. - After the arguments come another OP_... (the same one) - so that the grouping can be recognized from the end. */ - - /* OP_LONG is followed by a type pointer in the next exp_element - and the long constant value in the following exp_element. - Then comes another OP_LONG. - Thus, the operation occupies four exp_elements. */ - OP_LONG, - - /* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a long. */ - OP_DOUBLE, - - /* OP_VAR_VALUE takes one struct block * in the following element, - and one struct symbol * in the following exp_element, followed by - another OP_VAR_VALUE, making four exp_elements. If the block is - non-NULL, evaluate the symbol relative to the innermost frame - executing in that block; if the block is NULL use the selected frame. */ - OP_VAR_VALUE, - - /* OP_LAST is followed by an integer in the next exp_element. - The integer is zero for the last value printed, - or it is the absolute number of a history element. - With another OP_LAST at the end, this makes three exp_elements. */ - OP_LAST, - - /* OP_REGISTER is followed by a string in the next exp_element. - This is the name of a register to fetch. */ - OP_REGISTER, - - /* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element. - With another OP_INTERNALVAR at the end, this makes three exp_elements. */ - OP_INTERNALVAR, - - /* OP_FUNCALL is followed by an integer in the next exp_element. - The integer is the number of args to the function call. - That many plus one values from following subexpressions - are used, the first one being the function. - The integer is followed by a repeat of OP_FUNCALL, - making three exp_elements. */ - OP_FUNCALL, - - /* OP_OBJC_MSGCALL is followed by a string in the next exp_element and then an - integer. The string is the selector string. The integer is the number - of arguments to the message call. That many plus one values are used, - the first one being the object pointer. This is an Objective C message */ - OP_OBJC_MSGCALL, - - /* This is EXACTLY like OP_FUNCALL but is semantically different. - In F77, array subscript expressions, substring expressions - and function calls are all exactly the same syntactically. They may - only be disambiguated at runtime. Thus this operator, which - indicates that we have found something of the form ( ) */ - OP_F77_UNDETERMINED_ARGLIST, - - /* OP_COMPLEX takes a type in the following element, followed by another - OP_COMPLEX, making three exp_elements. It is followed by two double - args, and converts them into a complex number of the given type. */ - OP_COMPLEX, - - /* OP_STRING represents a string constant. - Its format is the same as that of a STRUCTOP, but the string - data is just made into a string constant when the operation - is executed. */ - OP_STRING, - - /* OP_BITSTRING represents a packed bitstring constant. - Its format is the same as that of a STRUCTOP, but the bitstring - data is just made into a bitstring constant when the operation - is executed. */ - OP_BITSTRING, - - /* OP_ARRAY creates an array constant out of the following subexpressions. - It is followed by two exp_elements, the first containing an integer - that is the lower bound of the array and the second containing another - integer that is the upper bound of the array. The second integer is - followed by a repeat of OP_ARRAY, making four exp_elements total. - The bounds are used to compute the number of following subexpressions - to consume, as well as setting the bounds in the created array constant. - The type of the elements is taken from the type of the first subexp, - and they must all match. */ - OP_ARRAY, - - /* UNOP_CAST is followed by a type pointer in the next exp_element. - With another UNOP_CAST at the end, this makes three exp_elements. - It casts the value of the following subexpression. */ - UNOP_CAST, - - /* The C++ dynamic_cast operator. */ - UNOP_DYNAMIC_CAST, - - /* The C++ reinterpret_cast operator. */ - UNOP_REINTERPRET_CAST, - - /* UNOP_MEMVAL is followed by a type pointer in the next exp_element - With another UNOP_MEMVAL at the end, this makes three exp_elements. - It casts the contents of the word addressed by the value of the - following subexpression. */ - UNOP_MEMVAL, - - /* UNOP_MEMVAL_TLS is followed by a `struct objfile' pointer in the next - exp_element and a type pointer in the following exp_element. - With another UNOP_MEMVAL_TLS at the end, this makes four exp_elements. - It casts the contents of the word offsetted by the value of the - following subexpression from the TLS specified by `struct objfile'. */ - UNOP_MEMVAL_TLS, - - /* UNOP_... operate on one value from a following subexpression - and replace it with a result. They take no immediate arguments. */ - - UNOP_NEG, /* Unary - */ - UNOP_LOGICAL_NOT, /* Unary ! */ - UNOP_COMPLEMENT, /* Unary ~ */ - UNOP_IND, /* Unary * */ - UNOP_ADDR, /* Unary & */ - UNOP_PREINCREMENT, /* ++ before an expression */ - UNOP_POSTINCREMENT, /* ++ after an expression */ - UNOP_PREDECREMENT, /* -- before an expression */ - UNOP_POSTDECREMENT, /* -- after an expression */ - UNOP_SIZEOF, /* Unary sizeof (followed by expression) */ - - UNOP_PLUS, /* Unary plus */ - - UNOP_CAP, /* Modula-2 standard (unary) procedures */ - UNOP_CHR, - UNOP_ORD, - UNOP_ABS, - UNOP_FLOAT, - UNOP_HIGH, - UNOP_MAX, - UNOP_MIN, - UNOP_ODD, - UNOP_TRUNC, - - OP_BOOL, /* Modula-2 builtin BOOLEAN type */ - OP_M2_STRING, /* Modula-2 string constants */ - - /* STRUCTOP_... operate on a value from a following subexpression - by extracting a structure component specified by a string - that appears in the following exp_elements (as many as needed). - STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->". - They differ only in the error message given in case the value is - not suitable or the structure component specified is not found. - - The length of the string follows the opcode, followed by - BYTES_TO_EXP_ELEM(length) elements containing the data of the - string, followed by the length again and the opcode again. */ - - STRUCTOP_STRUCT, - STRUCTOP_PTR, - - /* C++: OP_THIS is just a placeholder for the class instance variable. - It just comes in a tight (OP_THIS, OP_THIS) pair. */ - OP_THIS, - - /* Objective-C: OP_OBJC_SELF is just a placeholder for the class instance - variable. It just comes in a tight (OP_OBJC_SELF, OP_OBJC_SELF) pair. */ - OP_OBJC_SELF, - - /* Objective C: "@selector" pseudo-operator */ - OP_OBJC_SELECTOR, - - /* OP_SCOPE surrounds a type name and a field name. The type - name is encoded as one element, but the field name stays as - a string, which, of course, is variable length. */ - OP_SCOPE, - - /* Used to represent named structure field values in brace - initializers (or tuples as they are called in (the deleted) - Chill). - - The gcc C syntax is NAME:VALUE or .NAME=VALUE, the (the - deleted) Chill syntax is .NAME:VALUE. Multiple labels (as in - the (the deleted) Chill syntax .NAME1,.NAME2:VALUE) is - represented as if it were .NAME1:(.NAME2:VALUE) (though that is - not valid (the deleted) Chill syntax). - - The NAME is represented as for STRUCTOP_STRUCT; VALUE follows. */ - OP_LABELED, - - /* OP_TYPE is for parsing types, and used with the "ptype" command - so we can look up types that are qualified by scope, either with - the GDB "::" operator, or the Modula-2 '.' operator. */ - OP_TYPE, - - /* An un-looked-up identifier. */ - OP_NAME, - - /* An Objective C Foundation Class NSString constant */ - OP_OBJC_NSSTRING, - - /* A F90 array range operator (for "exp:exp", "exp:", ":exp" and ":"). */ - OP_F90_RANGE, - - /* OP_DECFLOAT is followed by a type pointer in the next exp_element - and a dec long constant value in the following exp_element. - Then comes another OP_DECFLOAT. */ - OP_DECFLOAT, - - /* OP_ADL_FUNC specifies that the function is to be looked up in an - Argument Dependent manner (Koenig lookup). */ - OP_ADL_FUNC, - - /* First extension operator. Individual language modules define - extra operators in *.inc include files below always starting with - numbering at OP_EXTENDED0: - BINOP_MOGRIFY = OP_EXTENDED0, - BINOP_FROB, - ... */ - OP_EXTENDED0, - - /* Last possible extension operator. Defined to provide an - explicit and finite number of extended operators. */ - OP_EXTENDED_LAST = 0xff, - /* NOTE: Eventually, we expect to convert to an object-oriented - formulation for expression operators that does away with the - need for these extension operators, and indeed for this - entire enumeration type. Therefore, consider the OP_EXTENDED - definitions to be a temporary measure. */ - - /* Each language specific set of operators starts at OP_EXTENDED0. */ -#include "ada-operator.inc" +#define OP(name) name , + +#include "std-operator.def" + + /* First extension operator. Individual language modules define extra + operators in *.def include files below with numbers higher than + OP_EXTENDED0. */ + OP (OP_EXTENDED0) + +/* Language specific operators. */ +#include "ada-operator.def" + +#undef OP /* Existing only to swallow the last comma (',') from last .inc file. */ OP_UNUSED_LAST @@ -388,14 +79,15 @@ union exp_element struct expression { - const struct language_defn *language_defn; /* language it was entered in */ - struct gdbarch *gdbarch; /* architecture it was parsed in */ + const struct language_defn *language_defn; /* language it was + entered in. */ + struct gdbarch *gdbarch; /* architecture it was parsed in. */ int nelts; union exp_element elts[1]; }; /* Macros for converting between number of expression elements and bytes - to store that many expression elements. */ + to store that many expression elements. */ #define EXP_ELEM_TO_BYTES(elements) \ ((elements) * sizeof (union exp_element)) @@ -447,7 +139,8 @@ extern void print_expression (struct expression *, struct ui_file *); extern char *op_string (enum exp_opcode); -extern void dump_raw_expression (struct expression *, struct ui_file *, char *); +extern void dump_raw_expression (struct expression *, + struct ui_file *, char *); extern void dump_prefix_expression (struct expression *, struct ui_file *); #endif /* !defined (EXPRESSION_H) */ diff --git a/contrib/gdb-7/gdb/f-exp.y b/contrib/gdb-7/gdb/f-exp.y index 415819a0fc..d9cf3cfcb9 100644 --- a/contrib/gdb-7/gdb/f-exp.y +++ b/contrib/gdb-7/gdb/f-exp.y @@ -1,6 +1,6 @@ /* YACC parser for Fortran expressions, for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1995, 1996, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt @@ -64,7 +64,7 @@ yacc generated parsers in gdb. Note that these are only the variables produced by yacc. If other parser generators (bison, byacc, etc) produce additional global names that conflict at link time, then those parser - generators need to be fixed instead of adding those names to this list. */ + generators need to be fixed instead of adding those names to this list. */ #define yymaxdepth f_maxdepth #define yyparse f_parse @@ -517,9 +517,9 @@ variable: name_not_typename if (msymbol != NULL) write_exp_msymbol (msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + error (_("No symbol table is loaded. Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name ($1.stoken)); } } @@ -758,7 +758,7 @@ parse_number (p, len, parsed_float, putithere) if (RANGE_CHECK && n != 0) { if ((unsigned_p && (unsigned)prevn >= (unsigned)n)) - range_error("Overflow on numeric constant."); + range_error (_("Overflow on numeric constant.")); } prevn = n; } @@ -794,7 +794,7 @@ parse_number (p, len, parsed_float, putithere) putithere->typed_val.val = n; /* If the high bit of the worked out type is set then this number - has to be unsigned. */ + has to be unsigned. */ if (unsigned_p || (n & high_bit)) putithere->typed_val.type = unsigned_type; @@ -875,7 +875,7 @@ static const struct token f77_keywords[] = /* Implementation of a dynamically expandable buffer for processing input characters acquired through lexptr and building a value to return in - yylval. Ripped off from ch-exp.y */ + yylval. Ripped off from ch-exp.y */ static char *tempbuf; /* Current buffer contents */ static int tempbufsize; /* Size of allocated buffer */ @@ -892,8 +892,8 @@ static int tempbufindex; /* Current index into buffer */ } while (0); -/* Grow the static temp buffer if necessary, including allocating the first one - on demand. */ +/* Grow the static temp buffer if necessary, including allocating the + first one on demand. */ static void growbuf_by_size (count) @@ -910,7 +910,7 @@ growbuf_by_size (count) } /* Blatantly ripped off from ch-exp.y. This routine recognizes F77 - string-literals. + string-literals. Recognize a string literal. A string literal is a nonzero sequence of characters enclosed in matching single quotes, except that @@ -919,7 +919,7 @@ growbuf_by_size (count) a string, it is simply doubled (I.E. 'this''is''one''string') */ static int -match_string_literal () +match_string_literal (void) { char *tokptr = lexptr; @@ -951,7 +951,7 @@ match_string_literal () /* Read one token, getting characters through lexptr. */ static int -yylex () +yylex (void) { int c; int namelen; @@ -984,7 +984,8 @@ yylex () /* See if it is a special .foo. operator. */ for (i = 0; dot_ops[i].operator != NULL; i++) - if (strncmp (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)) == 0) + if (strncmp (tokstart, dot_ops[i].operator, + strlen (dot_ops[i].operator)) == 0) { lexptr += strlen (dot_ops[i].operator); yylval.opcode = dot_ops[i].opcode; @@ -1038,7 +1039,7 @@ yylex () case '.': /* Might be a floating point number. */ if (lexptr[1] < '0' || lexptr[1] > '9') - goto symbol; /* Nope, must be a symbol. */ + goto symbol; /* Nope, must be a symbol. */ /* FALL THRU into number case. */ case '0': @@ -1062,7 +1063,8 @@ yylex () p += 2; hex = 1; } - else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) + else if (c == '0' && (p[1]=='t' || p[1]=='T' + || p[1]=='d' || p[1]=='D')) { p += 2; hex = 0; @@ -1097,7 +1099,7 @@ yylex () memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - error ("Invalid number \"%s\".", err_copy); + error (_("Invalid number \"%s\"."), err_copy); } lexptr = p; return toktype; @@ -1131,7 +1133,7 @@ yylex () if (!(c == '_' || c == '$' || c ==':' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error (_("Invalid character '%c' in expression."), c); namelen = 0; for (c = tokstart[namelen]; @@ -1150,8 +1152,8 @@ yylex () /* Catch specific keywords. */ for (i = 0; f77_keywords[i].operator != NULL; i++) - if (strncmp (tokstart, f77_keywords[i].operator, - strlen(f77_keywords[i].operator)) == 0) + if (strlen (f77_keywords[i].operator) == namelen + && strncmp (tokstart, f77_keywords[i].operator, namelen) == 0) { /* lexptr += strlen(f77_keywords[i].operator); */ yylval.opcode = f77_keywords[i].opcode; @@ -1222,5 +1224,5 @@ yyerror (msg) if (prev_lexptr) lexptr = prev_lexptr; - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); } diff --git a/contrib/gdb-7/gdb/f-lang.c b/contrib/gdb-7/gdb/f-lang.c index cad8cfbbf7..61513c121e 100644 --- a/contrib/gdb-7/gdb/f-lang.c +++ b/contrib/gdb-7/gdb/f-lang.c @@ -1,7 +1,7 @@ /* Fortran language support routines for GDB, the GNU debugger. Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -34,19 +34,20 @@ #include "cp-support.h" -/* Following is dubious stuff that had been in the xcoff reader. */ +/* Following is dubious stuff that had been in the xcoff reader. */ struct saved_fcn { - long line_offset; /* Line offset for function */ + long line_offset; /* Line offset for function. */ struct saved_fcn *next; }; struct saved_bf_symnum { - long symnum_fcn; /* Symnum of function (i.e. .function directive) */ - long symnum_bf; /* Symnum of .bf for this function */ + long symnum_fcn; /* Symnum of function (i.e. .function + directive). */ + long symnum_bf; /* Symnum of .bf for this function. */ struct saved_bf_symnum *next; }; @@ -84,7 +85,7 @@ static void f_emit_char (int c, struct type *type, static void f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - c &= 0xFF; /* Avoid sign bit follies */ + c &= 0xFF; /* Avoid sign bit follies. */ if (PRINT_LITERAL_FORM (c)) { @@ -125,7 +126,7 @@ f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) } /* FIXME: This is a copy of the same function from c-exp.y. It should - be replaced with a true F77version. */ + be replaced with a true F77version. */ static void f_printchar (int c, struct type *type, struct ui_file *stream) @@ -140,7 +141,7 @@ f_printchar (int c, struct type *type, struct ui_file *stream) are printed as appropriate. Print ellipses at the end if we had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. FIXME: This is a copy of the same function from c-exp.y. It should - be replaced with a true F77 version. */ + be replaced with a true F77 version. */ static void f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, @@ -333,7 +334,8 @@ f_word_break_characters (void) return retval; } -/* Consider the modules separator :: as a valid symbol name character class. */ +/* Consider the modules separator :: as a valid symbol name character + class. */ static char ** f_make_symbol_completion_list (char *text, char *word) @@ -342,7 +344,7 @@ f_make_symbol_completion_list (char *text, char *word) } /* This is declared in c-lang.h but it is silly to import that file for what - is already just a hack. */ + is already just a hack. */ extern int c_value_print (struct value *, struct ui_file *, const struct value_print_options *); @@ -371,7 +373,8 @@ const struct language_defn f_language_defn = cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ f_op_print_tab, /* expression operators for printing */ 0, /* arrays are first-class (not c-style) */ 1, /* String lower bound */ @@ -504,14 +507,14 @@ SAVED_F77_COMMON_PTR current_common = NULL; /* Ptr to current COMMON */ static SAVED_BF_PTR saved_bf_list = NULL; /* Ptr to (.bf,function) list */ static SAVED_BF_PTR saved_bf_list_end = NULL; /* Ptr to above list's end */ -static SAVED_BF_PTR current_head_bf_list = NULL; /* Current head of above list - */ +static SAVED_BF_PTR current_head_bf_list = NULL; /* Current head of + above list. */ static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use - in macros */ + in macros. */ /* The following function simply enters a given common block onto - the global common block chain */ + the global common block chain. */ static void add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) @@ -522,7 +525,7 @@ add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) /* If the COMMON block we are trying to add has a blank name (i.e. "#BLNK_COM") then we set it to __BLANK because the darn "#" character makes GDB's input - parser have fits. */ + parser have fits. */ if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 @@ -542,7 +545,7 @@ add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) tmp->name = xmalloc (strlen (name) + 1); /* local_copy_func_stab is a stabstring, let us first extract the - function name from the stab by NULLing out the ':' character. */ + function name from the stab by NULLing out the ':' character. */ c = NULL; @@ -579,7 +582,7 @@ add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) #endif /* The following function simply enters a given common entry onto - the "current_common" block that has been saved away. */ + the "current_common" block that has been saved away. */ #if 0 static void @@ -591,7 +594,7 @@ add_common_entry (struct symbol *entry_sym_ptr) /* The order of this list is important, since we expect the entries to appear in decl. - order when we later issue "info common" calls */ + order when we later issue "info common" calls. */ tmp = allocate_common_entry_node (); @@ -616,7 +619,7 @@ add_common_entry (struct symbol *entry_sym_ptr) } #endif -/* This routine finds the first encountred COMMON block named "name" */ +/* This routine finds the first encountred COMMON block named "name". */ #if 0 static SAVED_F77_COMMON_PTR @@ -639,7 +642,7 @@ find_first_common_named (char *name) #endif /* This routine finds the first encountred COMMON block named "name" - that belongs to function funcname */ + that belongs to function funcname. */ SAVED_F77_COMMON_PTR find_common_for_function (char *name, char *funcname) @@ -672,7 +675,7 @@ patch_common_entries (SAVED_F77_COMMON_PTR blk, CORE_ADDR offset, int secnum) { COMMON_ENTRY_PTR entry; - blk->offset = offset; /* Keep this around for future use. */ + blk->offset = offset; /* Keep this around for future use. */ entry = blk->entries; @@ -690,7 +693,7 @@ patch_common_entries (SAVED_F77_COMMON_PTR blk, CORE_ADDR offset, int secnum) blocks occur with relative infrequency, we simply do a linear scan on the name. Eventually, the best way to do this will be a hashed-lookup. Secnum is the section number for the .bss section - (which is where common data lives). */ + (which is where common data lives). */ static void patch_all_commons_by_name (char *name, CORE_ADDR offset, int secnum) @@ -728,7 +731,7 @@ patch_all_commons_by_name (char *name, CORE_ADDR offset, int secnum) #line pragmas sometimes cause line ranges to get messed up we simply create a linear list. This list can then be searched first by a queueing algorithm and upon failure fall back to - a linear scan. */ + a linear scan. */ #if 0 #define ADD_BF_SYMNUM(bf_sym,fcn_sym) \ @@ -757,7 +760,7 @@ else \ } #endif -/* This function frees the entire (.bf,function) list */ +/* This function frees the entire (.bf,function) list. */ #if 0 static void @@ -788,7 +791,7 @@ get_bf_for_fcn (long the_function) int nprobes = 0; /* First use a simple queuing algorithm (i.e. look and see if the - item at the head of the queue is the one you want) */ + item at the head of the queue is the one you want). */ if (saved_bf_list == NULL) internal_error (__FILE__, __LINE__, @@ -807,7 +810,7 @@ get_bf_for_fcn (long the_function) /* If the above did not work (probably because #line directives were used in the sourcefile and they messed up our internal tables) we now do - the ugly linear scan */ + the ugly linear scan. */ if (global_remote_debug) fprintf_unfiltered (gdb_stderr, "\ndefaulting to linear scan\n"); diff --git a/contrib/gdb-7/gdb/f-lang.h b/contrib/gdb-7/gdb/f-lang.h index f5bb82d7ed..8043577cf4 100644 --- a/contrib/gdb-7/gdb/f-lang.h +++ b/contrib/gdb-7/gdb/f-lang.h @@ -1,7 +1,7 @@ /* Fortran language support definitions for GDB, the GNU debugger. Copyright (C) 1992, 1993, 1994, 1995, 1998, 2000, 2005, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C definitions by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -87,13 +87,13 @@ extern SAVED_F77_COMMON_PTR find_common_for_function (char *, char *); /* When reasonable array bounds cannot be fetched, such as when you ask to 'mt print symbols' and there is no stack frame and therefore no way of knowing the bounds of stack-based arrays, - we have to assign default bounds, these are as good as any... */ + we have to assign default bounds, these are as good as any... */ #define DEFAULT_UPPER_BOUND 999999 #define DEFAULT_LOWER_BOUND -999999 -extern char *real_main_name; /* Name of main function */ -extern int real_main_c_value; /* C_value field of main function */ +extern char *real_main_name; /* Name of main function. */ +extern int real_main_c_value; /* C_value field of main function. */ extern int f77_get_upperbound (struct type *); diff --git a/contrib/gdb-7/gdb/f-typeprint.c b/contrib/gdb-7/gdb/f-typeprint.c index d35a255ae1..ad988d23dd 100644 --- a/contrib/gdb-7/gdb/f-typeprint.c +++ b/contrib/gdb-7/gdb/f-typeprint.c @@ -1,7 +1,7 @@ /* Support for printing Fortran types for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1998, 2000, - 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 + 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C version by Farooq Butt @@ -36,7 +36,7 @@ #include "gdb_string.h" #include -#if 0 /* Currently unused */ +#if 0 /* Currently unused. */ static void f_type_print_args (struct type *, struct ui_file *); #endif @@ -76,7 +76,7 @@ f_print_type (struct type *type, const char *varstring, struct ui_file *stream, fputs_filtered (varstring, stream); /* For demangled function names, we have the arglist as part of the name, - so don't print an additional pair of ()'s */ + so don't print an additional pair of ()'s. */ demangled_args = varstring[strlen (varstring) - 1] == ')'; f_type_print_varspec_suffix (type, stream, show, 0, demangled_args, 0); @@ -182,7 +182,7 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream, fprintf_filtered (stream, "%d:", lower_bound); /* Make sure that, if we have an assumed size array, we - print out a warning and print the upperbound as '*' */ + print out a warning and print the upperbound as '*'. */ if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) fprintf_filtered (stream, "*"); @@ -271,7 +271,7 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, } /* When SHOW is zero or less, and there is a valid type name, then always - just print the type name directly from the type. */ + just print the type name directly from the type. */ if ((show <= 0) && (TYPE_NAME (type) != NULL)) { @@ -316,12 +316,12 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_RANGE: - /* This should not occur */ + /* This should not occur. */ fprintfi_filtered (level, stream, ""); break; case TYPE_CODE_CHAR: - /* Override name "char" and make it "character" */ + /* Override name "char" and make it "character". */ fprintfi_filtered (level, stream, "character"); break; @@ -337,7 +337,7 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_STRING: - /* Strings may have dynamic upperbounds (lengths) like arrays. */ + /* Strings may have dynamic upperbounds (lengths) like arrays. */ if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) fprintfi_filtered (level, stream, "character*(*)"); @@ -379,7 +379,7 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, /* Handle types not explicitly handled by the other cases, such as fundamental types. For these, just print whatever the type name is, as recorded in the type itself. If there - is no type name, then complain. */ + is no type name, then complain. */ if (TYPE_NAME (type) != NULL) fprintfi_filtered (level, stream, "%s", TYPE_NAME (type)); else diff --git a/contrib/gdb-7/gdb/f-valprint.c b/contrib/gdb-7/gdb/f-valprint.c index 85f698d5da..3280ddcb5d 100644 --- a/contrib/gdb-7/gdb/f-valprint.c +++ b/contrib/gdb-7/gdb/f-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Fortran values for GDB, the GNU debugger. Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2003, 2005, 2006, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C definitions by Farooq Butt (fmbutt@engage.sps.mot.com), additionally worked over by Stan Shebs. @@ -49,14 +49,14 @@ static void f77_get_dynamic_length_of_aggregate (struct type *); int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2]; /* Array which holds offsets to be applied to get a row's elements - for a given array. Array also holds the size of each subarray. */ + for a given array. Array also holds the size of each subarray. */ /* The following macro gives us the size of the nth dimension, Where - n is 1 based. */ + n is 1 based. */ #define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1]) -/* The following gives us the offset for row n where n is 1-based. */ +/* The following gives us the offset for row n where n is 1-based. */ #define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0]) @@ -85,7 +85,7 @@ f77_get_upperbound (struct type *type) return TYPE_ARRAY_UPPER_BOUND_VALUE (type); } -/* Obtain F77 adjustable array dimensions */ +/* Obtain F77 adjustable array dimensions. */ static void f77_get_dynamic_length_of_aggregate (struct type *type) @@ -110,10 +110,11 @@ f77_get_dynamic_length_of_aggregate (struct type *type) lower_bound = f77_get_lowerbound (type); upper_bound = f77_get_upperbound (type); - /* Patch in a valid length value. */ + /* Patch in a valid length value. */ TYPE_LENGTH (type) = - (upper_bound - lower_bound + 1) * TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type))); + (upper_bound - lower_bound + 1) + * TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type))); } /* Function that sets up the array offset,size table for the array @@ -143,7 +144,7 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) /* Now we multiply eltlen by all the offsets, so that later we can print out array elements correctly. Up till now we know an offset to apply to get the item but we also - have to know how much to add to get to the next item */ + have to know how much to add to get to the next item. */ ndimen--; eltlen = TYPE_LENGTH (tmp_type); @@ -162,7 +163,8 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) static void f77_print_array_1 (int nss, int ndimensions, struct type *type, - const gdb_byte *valaddr, CORE_ADDR address, + const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, const struct value_print_options *options, @@ -172,12 +174,15 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, if (nss != ndimensions) { - for (i = 0; (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); i++) + for (i = 0; + (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); + i++) { fprintf_filtered (stream, "( "); f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type), - valaddr + i * F77_DIM_OFFSET (nss), - address + i * F77_DIM_OFFSET (nss), + valaddr, + embedded_offset + i * F77_DIM_OFFSET (nss), + address, stream, recurse, val, options, elts); fprintf_filtered (stream, ") "); } @@ -190,10 +195,10 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, i++, (*elts)++) { val_print (TYPE_TARGET_TYPE (type), - valaddr + i * F77_DIM_OFFSET (ndimensions), - 0, - address + i * F77_DIM_OFFSET (ndimensions), - stream, recurse, val, options, current_language); + valaddr, + embedded_offset + i * F77_DIM_OFFSET (ndimensions), + address, stream, recurse, + val, options, current_language); if (i != (F77_DIM_SIZE (nss) - 1)) fprintf_filtered (stream, ", "); @@ -206,10 +211,11 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, } /* This function gets called to print an F77 array, we set up some - stuff and then immediately call f77_print_array_1() */ + stuff and then immediately call f77_print_array_1(). */ static void f77_print_array (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, @@ -221,26 +227,24 @@ f77_print_array (struct type *type, const gdb_byte *valaddr, ndimensions = calc_f77_array_dims (type); if (ndimensions > MAX_FORTRAN_DIMS || ndimensions < 0) - error (_("Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)"), + error (_("\ +Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)"), ndimensions, MAX_FORTRAN_DIMS); /* Since F77 arrays are stored column-major, we set up an - offset table to get at the various row's elements. The - offset table contains entries for both offset and subarray size. */ + offset table to get at the various row's elements. The + offset table contains entries for both offset and subarray size. */ f77_create_arrayprint_offset_tbl (type, stream); - f77_print_array_1 (1, ndimensions, type, valaddr, address, stream, - recurse, val, options, &elts); + f77_print_array_1 (1, ndimensions, type, valaddr, embedded_offset, + address, stream, recurse, val, options, &elts); } -/* Print data of type TYPE located at VALADDR (within GDB), which came from - the inferior at address ADDRESS, onto stdio stream STREAM according to - OPTIONS. The data at VALADDR is in target byte order. - - If the data are a string pointer, returns the number of string characters - printed. */ +/* See val_print for a description of the various parameters of this + function; they are identical. The semantics of the return value is + also identical to val_print. */ int f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, @@ -250,7 +254,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { struct gdbarch *gdbarch = get_type_arch (type); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - unsigned int i = 0; /* Number of characters printed */ + unsigned int i = 0; /* Number of characters printed. */ struct type *elttype; LONGEST val; CORE_ADDR addr; @@ -262,24 +266,27 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_STRING: f77_get_dynamic_length_of_aggregate (type); LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char, - valaddr, TYPE_LENGTH (type), NULL, 0, options); + valaddr + embedded_offset, + TYPE_LENGTH (type), NULL, 0, options); break; case TYPE_CODE_ARRAY: fprintf_filtered (stream, "("); - f77_print_array (type, valaddr, address, stream, recurse, original_value, options); + f77_print_array (type, valaddr, embedded_offset, + address, stream, recurse, original_value, options); fprintf_filtered (stream, ")"); break; case TYPE_CODE_PTR: if (options->format && options->format != 's') { - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } else { - addr = unpack_pointer (type, valaddr); + addr = unpack_pointer (type, valaddr + embedded_offset); elttype = check_typedef (TYPE_TARGET_TYPE (type)); if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) @@ -299,8 +306,8 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, && TYPE_CODE (elttype) == TYPE_CODE_INT && (options->format == 0 || options->format == 's') && addr != 0) - i = val_print_string (TYPE_TARGET_TYPE (type), addr, -1, stream, - options); + i = val_print_string (TYPE_TARGET_TYPE (type), NULL, addr, -1, + stream, options); /* Return number of characters printed, including the terminating '\0' if we reached the end. val_print_string takes care including @@ -342,7 +349,8 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_FUNC: if (options->format) { - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } /* FIXME, we should consider, at least for ANSI C language, eliminating @@ -361,36 +369,41 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr, type, &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); } else { - val_print_type_code_int (type, valaddr, stream); + val_print_type_code_int (type, valaddr + embedded_offset, stream); /* C and C++ has no single byte int type, char is used instead. Since we don't know whether the value is really intended to be used as an integer or a character, print the character - equivalent as well. */ + equivalent as well. */ if (TYPE_LENGTH (type) == 1) { + LONGEST c; + fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), - type, stream); + c = unpack_long (type, valaddr + embedded_offset); + LA_PRINT_CHAR ((unsigned char) c, type, stream); } } break; case TYPE_CODE_FLAGS: if (options->format) - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else - val_print_type_code_flags (type, valaddr, stream); + val_print_type_code_flags (type, valaddr + embedded_offset, stream); break; case TYPE_CODE_FLT: if (options->format) - print_scalar_formatted (valaddr, type, options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else - print_floating (valaddr, type, stream); + print_floating (valaddr + embedded_offset, type, stream); break; case TYPE_CODE_VOID: @@ -413,11 +426,12 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr, type, &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { - val = extract_unsigned_integer (valaddr, + val = extract_unsigned_integer (valaddr + embedded_offset, TYPE_LENGTH (type), byte_order); if (val == 0) fprintf_filtered (stream, ".FALSE."); @@ -428,9 +442,10 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { /* Bash the type code temporarily. */ TYPE_CODE (type) = TYPE_CODE_INT; - val_print (type, valaddr, 0, address, stream, recurse, + val_print (type, valaddr, embedded_offset, + address, stream, recurse, original_value, options, current_language); - /* Restore the type code so later uses work as intended. */ + /* Restore the type code so later uses work as intended. */ TYPE_CODE (type) = TYPE_CODE_BOOL; } } @@ -439,9 +454,10 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_COMPLEX: type = TYPE_TARGET_TYPE (type); fputs_filtered ("(", stream); - print_floating (valaddr, type, stream); + print_floating (valaddr + embedded_offset, type, stream); fputs_filtered (",", stream); - print_floating (valaddr + TYPE_LENGTH (type), type, stream); + print_floating (valaddr + embedded_offset + TYPE_LENGTH (type), + type, stream); fputs_filtered (")", stream); break; @@ -461,8 +477,9 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { int offset = TYPE_FIELD_BITPOS (type, index) / 8; - val_print (TYPE_FIELD_TYPE (type, index), valaddr + offset, - embedded_offset, address, stream, recurse + 1, + val_print (TYPE_FIELD_TYPE (type, index), valaddr, + embedded_offset + offset, + address, stream, recurse + 1, original_value, options, current_language); if (index != TYPE_NFIELDS (type) - 1) fputs_filtered (", ", stream); @@ -496,8 +513,8 @@ list_all_visible_commons (char *funname) } /* This function is used to print out the values in a given COMMON - block. It will always use the most local common block of the - given name */ + block. It will always use the most local common block of the + given name. */ static void info_common_command (char *comname, int from_tty) @@ -511,12 +528,12 @@ info_common_command (char *comname, int from_tty) /* We have been told to display the contents of F77 COMMON block supposedly visible in this function. Let us first make sure that it is visible and if so, let - us display its contents */ + us display its contents. */ fi = get_selected_frame (_("No frame selected")); /* The following is generally ripped off from stack.c's routine - print_frame_info() */ + print_frame_info(). */ func = find_pc_function (get_frame_pc (fi)); if (func) @@ -533,7 +550,7 @@ info_common_command (char *comname, int from_tty) up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. - FIXME: (Not necessarily true. What about text labels) */ + FIXME: (Not necessarily true. What about text labels?) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); @@ -557,7 +574,7 @@ info_common_command (char *comname, int from_tty) } /* If comname is NULL, we assume the user wishes to see the - which COMMON blocks are visible here and then return */ + which COMMON blocks are visible here and then return. */ if (comname == 0) { @@ -589,7 +606,7 @@ info_common_command (char *comname, int from_tty) } /* This function is used to determine whether there is a - F77 common block visible at the current scope called 'comname'. */ + F77 common block visible at the current scope called 'comname'. */ #if 0 static int @@ -606,7 +623,7 @@ there_is_a_visible_common_named (char *comname) fi = get_selected_frame (_("No frame selected")); /* The following is generally ripped off from stack.c's routine - print_frame_info() */ + print_frame_info(). */ func = find_pc_function (fi->pc); if (func) @@ -623,7 +640,7 @@ there_is_a_visible_common_named (char *comname) up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. - FIXME: (Not necessarily true. What about text labels) */ + FIXME: (Not necessarily true. What about text labels?) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); diff --git a/contrib/gdb-7/gdb/fbsd-nat.c b/contrib/gdb-7/gdb/fbsd-nat.c index d499864904..406ac37233 100644 --- a/contrib/gdb-7/gdb/fbsd-nat.c +++ b/contrib/gdb-7/gdb/fbsd-nat.c @@ -1,6 +1,6 @@ /* Native-dependent code for FreeBSD. - Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -34,7 +34,7 @@ #include "elf-bfd.h" #include "fbsd-nat.h" -/* Return a the name of file that can be opened to get the symbols for +/* Return the name of a file that can be opened to get the symbols for the child process identified by PID. */ char * @@ -92,9 +92,7 @@ fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end, argument to FUNC. */ int -fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, - int, int, int, void *), - void *obfd) +fbsd_find_memory_regions (find_memory_region_ftype func, void *obfd) { pid_t pid = ptid_get_pid (inferior_ptid); char *mapfilename; @@ -134,7 +132,7 @@ fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, exec ? 'x' : '-'); } - /* Invoke the callback function to create the corefile segment. */ + /* Invoke the callback function to create the corefile segment. */ func (start, size, read, write, exec, obfd); } @@ -145,7 +143,7 @@ fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, static int find_signalled_thread (struct thread_info *info, void *data) { - if (info->stop_signal != TARGET_SIGNAL_0 + if (info->suspend.stop_signal != TARGET_SIGNAL_0 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) return 1; @@ -159,7 +157,7 @@ find_stop_signal (void) iterate_over_threads (find_signalled_thread, NULL); if (info) - return info->stop_signal; + return info->suspend.stop_signal; else return TARGET_SIGNAL_0; } @@ -204,7 +202,7 @@ fbsd_make_corefile_notes (bfd *obfd, int *note_size) if (get_exec_file (0)) { - char *fname = strrchr (get_exec_file (0), '/') + 1; + const char *fname = lbasename (get_exec_file (0)); char *psargs = xstrdup (fname); if (get_inferior_args ()) diff --git a/contrib/gdb-7/gdb/fbsd-nat.h b/contrib/gdb-7/gdb/fbsd-nat.h index b61162bc4e..c232a4fa2d 100644 --- a/contrib/gdb-7/gdb/fbsd-nat.h +++ b/contrib/gdb-7/gdb/fbsd-nat.h @@ -1,6 +1,7 @@ /* Native-dependent code for FreeBSD. - Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +21,7 @@ #ifndef FBSD_NAT_H #define FBSD_NAT_H -/* Return a the name of file that can be opened to get the symbols for +/* Return the name of a file that can be opened to get the symbols for the child process identified by PID. */ extern char *fbsd_pid_to_exec_file (int pid); diff --git a/contrib/gdb-7/gdb/features/feature_to_c.sh b/contrib/gdb-7/gdb/features/feature_to_c.sh index 9a68314541..dd9f225ab9 100644 --- a/contrib/gdb-7/gdb/features/feature_to_c.sh +++ b/contrib/gdb-7/gdb/features/feature_to_c.sh @@ -2,7 +2,7 @@ # Convert text files to compilable C arrays. # -# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # # This file is part of GDB. # diff --git a/contrib/gdb-7/gdb/features/gdb-target.dtd b/contrib/gdb-7/gdb/features/gdb-target.dtd index d5710caa77..fd7dac33fa 100644 --- a/contrib/gdb-7/gdb/features/gdb-target.dtd +++ b/contrib/gdb-7/gdb/features/gdb-target.dtd @@ -1,4 +1,4 @@ - + + + + + + + diff --git a/contrib/gdb-7/gdb/features/xinclude.dtd b/contrib/gdb-7/gdb/features/xinclude.dtd index 307b316758..df2df4175b 100644 --- a/contrib/gdb-7/gdb/features/xinclude.dtd +++ b/contrib/gdb-7/gdb/features/xinclude.dtd @@ -1,4 +1,4 @@ - jump to normal symbol processing. */ if (sym) - return symbol_found (funfirstline, canonical, copy, sym, NULL); + return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL); /* If symbol was not found, look in minimal symbol tables. */ msymbol = lookup_minimal_symbol (copy, NULL, NULL); @@ -1815,7 +2016,8 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, /* Not a user variable or function -- must be convenience variable. */ if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx)) - error (_("Convenience variables used in line specs must have integer values.")); + error (_("Convenience variables used in line " + "specs must have integer values.")); } init_sal (&val); @@ -1838,36 +2040,68 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, +/* A helper for decode_line_1 that tries to find a label. The label + is searched for in the current block. + FUNCTION_SYMBOL is the enclosing function; or NULL if none + specified. + COPY is the name of the label to find. + CANONICAL is the same as the "canonical" argument to decode_line_1. + RESULT is a pointer to a symtabs_and_lines structure which will be + filled in on success. + This function returns 1 if a label was found, 0 otherwise. */ + +static int +decode_label (struct symbol *function_symbol, char *copy, + struct linespec_result *canonical, + struct symtabs_and_lines *result) +{ + struct symbol *sym; + struct block *block; + + if (function_symbol) + block = SYMBOL_BLOCK_VALUE (function_symbol); + else + { + block = get_selected_block (0); + for (; + block && !BLOCK_FUNCTION (block); + block = BLOCK_SUPERBLOCK (block)) + ; + if (!block) + return 0; + function_symbol = BLOCK_FUNCTION (block); + } + + sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0); + + if (sym != NULL) + *result = symbol_found (0, canonical, copy, sym, NULL, function_symbol); + + return sym != NULL; +} + /* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL, - look in that symtab's static variables first. If NOT_FOUND_PTR is not NULL and - the function cannot be found, store boolean true in the location pointed to - and do not issue an error message. */ + look in that symtab's static variables first. */ static struct symtabs_and_lines -decode_variable (char *copy, int funfirstline, char ***canonical, - struct symtab *file_symtab, int *not_found_ptr) +decode_variable (char *copy, int funfirstline, + struct linespec_result *canonical, + struct symtab *file_symtab) { struct symbol *sym; struct minimal_symbol *msymbol; - sym = lookup_symbol (copy, - (file_symtab - ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), - STATIC_BLOCK) - : get_selected_block (0)), + sym = lookup_symbol (copy, get_search_block (file_symtab), VAR_DOMAIN, 0); if (sym != NULL) - return symbol_found (funfirstline, canonical, copy, sym, file_symtab); + return symbol_found (funfirstline, canonical, copy, sym, file_symtab, NULL); msymbol = lookup_minimal_symbol (copy, NULL, NULL); if (msymbol != NULL) return minsym_found (funfirstline, msymbol); - if (not_found_ptr) - *not_found_ptr = 1; - if (!have_full_symbols () && !have_partial_symbols () && !have_minimal_symbols ()) @@ -1886,14 +2120,15 @@ decode_variable (char *copy, int funfirstline, char ***canonical, corresponding struct symtabs_and_lines. */ static struct symtabs_and_lines -symbol_found (int funfirstline, char ***canonical, char *copy, - struct symbol *sym, struct symtab *file_symtab) +symbol_found (int funfirstline, struct linespec_result *canonical, char *copy, + struct symbol *sym, struct symtab *file_symtab, + struct symbol *function_symbol) { struct symtabs_and_lines values; if (SYMBOL_CLASS (sym) == LOC_BLOCK) { - /* Arg is the name of a function */ + /* Arg is the name of a function. */ values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); values.sals[0] = find_function_start_sal (sym, funfirstline); @@ -1917,8 +2152,38 @@ symbol_found (int funfirstline, char ***canonical, char *copy, } else { - if (funfirstline) - error (_("\"%s\" is not a function"), copy); + if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0) + { + /* We know its line number. */ + values.sals = (struct symtab_and_line *) + xmalloc (sizeof (struct symtab_and_line)); + values.nelts = 1; + init_sal (&values.sals[0]); + values.sals[0].symtab = SYMBOL_SYMTAB (sym); + values.sals[0].line = SYMBOL_LINE (sym); + values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym); + values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); + values.sals[0].explicit_pc = 1; + + if (canonical) + { + canonical->special_display = 1; + canonical->canonical = xmalloc (sizeof (char *)); + canonical->canonical[0] + = xstrprintf ("%s:%s", + SYMBOL_NATURAL_NAME (function_symbol), + SYMBOL_NATURAL_NAME (sym)); + } + + return values; + } + else if (funfirstline) + { + /* NOT_FOUND_ERROR is not correct but it ensures COPY will be + searched also as a minimal symbol. */ + + throw_error (NOT_FOUND_ERROR, _("\"%s\" is not a function"), copy); + } else if (SYMBOL_LINE (sym) != 0) { /* We know its line number. */ @@ -1928,6 +2193,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy, memset (&values.sals[0], 0, sizeof (values.sals[0])); values.sals[0].symtab = SYMBOL_SYMTAB (sym); values.sals[0].line = SYMBOL_LINE (sym); + values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); return values; } else @@ -1971,3 +2237,9 @@ minsym_found (int funfirstline, struct minimal_symbol *msymbol) values.nelts = 1; return values; } + +void +init_linespec_result (struct linespec_result *lr) +{ + memset (lr, 0, sizeof (*lr)); +} diff --git a/contrib/gdb-7/gdb/linespec.h b/contrib/gdb-7/gdb/linespec.h index 161f7d04dc..3c86af36cb 100644 --- a/contrib/gdb-7/gdb/linespec.h +++ b/contrib/gdb-7/gdb/linespec.h @@ -1,5 +1,6 @@ /* Header for GDB line completion. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,9 +20,32 @@ struct symtab; +/* An instance of this may be filled in by decode_line_1. The caller + must call init_linespec_result to initialize it. */ + +struct linespec_result +{ + /* If non-zero, the linespec should be displayed to the user. This + is used by "unusual" linespecs where the ordinary `info break' + display mechanism would do the wrong thing. */ + int special_display; + + /* If non-NULL, an array of canonical names for returned + symtab_and_line objects. The array has as many elements as the + `nelts' field in the symtabs_and_line returned by decode_line_1. + An element in the array may be NULL. The array and each non-NULL + element in it are allocated with xmalloc and must be freed by the + caller. */ + char **canonical; +}; + +/* Initialize a linespec_result. */ + +extern void init_linespec_result (struct linespec_result *); + extern struct symtabs_and_lines decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, int default_line, - char ***canonical, int *not_found_ptr); + struct linespec_result *canonical); #endif /* defined (LINESPEC_H) */ diff --git a/contrib/gdb-7/gdb/m2-exp.y b/contrib/gdb-7/gdb/m2-exp.y index 3baff791ee..1809af8ee5 100644 --- a/contrib/gdb-7/gdb/m2-exp.y +++ b/contrib/gdb-7/gdb/m2-exp.y @@ -1,6 +1,6 @@ /* YACC grammar for Modula-2 expressions, for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, - 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Generated from expread.y (now c-exp.y) and contributed by the Department of Computer Science at the State University of New York at Buffalo, 1991. @@ -34,7 +34,7 @@ generator. Doing this with #defines and trying to control the interaction with include files ( and for example) just became too messy, particularly when such includes can be inserted at random - times by the parser generator. */ + times by the parser generator. */ %{ @@ -58,7 +58,7 @@ yacc generated parsers in gdb. Note that these are only the variables produced by yacc. If other parser generators (bison, byacc, etc) produce additional global names that conflict at link time, then those parser - generators need to be fixed instead of adding those names to this list. */ + generators need to be fixed instead of adding those names to this list. */ #define yymaxdepth m2_maxdepth #define yyparse m2_parse @@ -119,7 +119,7 @@ static char *make_qualname (char *, char *); static int parse_number (int); -/* The sign of the number being parsed. */ +/* The sign of the number being parsed. */ static int number_sign = 1; /* The block that the module specified by the qualifer on an identifer is @@ -329,21 +329,21 @@ exp : set ; exp : exp IN set - { error("Sets are not implemented.");} + { error (_("Sets are not implemented."));} ; exp : INCL '(' exp ',' exp ')' - { error("Sets are not implemented.");} + { error (_("Sets are not implemented."));} ; exp : EXCL '(' exp ',' exp ')' - { error("Sets are not implemented.");} + { error (_("Sets are not implemented."));} ; set : '{' arglist '}' - { error("Sets are not implemented.");} + { error (_("Sets are not implemented."));} | type '{' arglist '}' - { error("Sets are not implemented.");} + { error (_("Sets are not implemented."));} ; @@ -543,7 +543,7 @@ exp : STRING write_exp_elt_opcode (OP_M2_STRING); } ; -/* This will be used for extensions later. Like adding modules. */ +/* This will be used for extensions later. Like adding modules. */ block : fblock { $$ = SYMBOL_BLOCK_VALUE($1); } ; @@ -562,7 +562,7 @@ fblock : block COLONCOLON BLOCKNAME = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, 0); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) - error ("No function \"%s\" in specified context.", + error (_("No function \"%s\" in specified context."), copy_name ($3)); $$ = tem; } @@ -586,7 +586,7 @@ variable: block COLONCOLON NAME sym = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, 0); if (sym == 0) - error ("No symbol \"%s\" in specified context.", + error (_("No symbol \"%s\" in specified context."), copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); @@ -596,7 +596,7 @@ variable: block COLONCOLON NAME write_exp_elt_opcode (OP_VAR_VALUE); } ; -/* Base case for variables. */ +/* Base case for variables. */ variable: NAME { struct symbol *sym; int is_a_field_of_this; @@ -633,9 +633,9 @@ variable: NAME if (msymbol != NULL) write_exp_msymbol (msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"symbol-file\" command."); + error (_("No symbol table is loaded. Use the \"symbol-file\" command.")); else - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name ($1)); } } @@ -692,9 +692,9 @@ parse_number (olen) return FLOAT; } if (p[c] == '.' && base != 10) - error("Floating point numbers must be base 10."); + error (_("Floating point numbers must be base 10.")); if (base == 10 && (p[c] < '0' || p[c] > '9')) - error("Invalid digit \'%c\' in number.",p[c]); + error (_("Invalid digit \'%c\' in number."),p[c]); } while (len-- > 0) @@ -702,7 +702,7 @@ parse_number (olen) c = *p++; n *= base; if( base == 8 && (c == '8' || c == '9')) - error("Invalid digit \'%c\' in octal number.",c); + error (_("Invalid digit \'%c\' in octal number."),c); if (c >= '0' && c <= '9') i = c - '0'; else @@ -718,12 +718,12 @@ parse_number (olen) if(!unsigned_p && number_sign == 1 && (prevn >= n)) unsigned_p=1; /* Try something unsigned */ /* Don't do the range check if n==i and i==0, since that special - case will give an overflow error. */ + case will give an overflow error. */ if(RANGE_CHECK && n!=i && i) { if((unsigned_p && (unsigned)prevn >= (unsigned)n) || ((!unsigned_p && number_sign==-1) && -prevn <= -n)) - range_error("Overflow on numeric constant."); + range_error (_("Overflow on numeric constant.")); } prevn=n; } @@ -743,7 +743,7 @@ parse_number (olen) return UINT; } else if((unsigned_p && (n<0))) { - range_error("Overflow on numeric constant -- number too large."); + range_error (_("Overflow on numeric constant -- number too large.")); /* But, this can return if range_check == range_warn. */ } yylval.lval = n; @@ -808,7 +808,7 @@ static struct keyword keytab[] = compatible */ static int -yylex () +yylex (void) { int c; int namelen; @@ -905,7 +905,7 @@ yylex () } } if(c != quote) - error("Unterminated string or character constant."); + error (_("Unterminated string or character constant.")); yylval.sval.ptr = tokstart + 1; yylval.sval.length = namelen - 1; lexptr += namelen + 1; @@ -952,7 +952,7 @@ yylex () memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - error ("Invalid number \"%s\".", err_copy); + error (_("Invalid number \"%s\"."), err_copy); } lexptr = p; return toktype; @@ -961,7 +961,7 @@ yylex () if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; @@ -1038,20 +1038,20 @@ yylex () return BLOCKNAME; case LOC_UNDEF: - error("internal: Undefined class in m2lex()"); + error (_("internal: Undefined class in m2lex()")); case LOC_LABEL: case LOC_UNRESOLVED: - error("internal: Unforseen case in m2lex()"); + error (_("internal: Unforseen case in m2lex()")); default: - error ("unhandled token in m2lex()"); + error (_("unhandled token in m2lex()")); break; } } else { - /* Built-in BOOLEAN type. This is sort of a hack. */ + /* Built-in BOOLEAN type. This is sort of a hack. */ if (strncmp (tokstart, "TRUE", 4) == 0) { yylval.ulval = 1; @@ -1064,7 +1064,7 @@ yylex () } } - /* Must be another type of name... */ + /* Must be another type of name... */ return NAME; } } @@ -1090,5 +1090,5 @@ yyerror (msg) if (prev_lexptr) lexptr = prev_lexptr; - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); } diff --git a/contrib/gdb-7/gdb/m2-lang.c b/contrib/gdb-7/gdb/m2-lang.c index ade52d9852..f83c622e21 100644 --- a/contrib/gdb-7/gdb/m2-lang.c +++ b/contrib/gdb-7/gdb/m2-lang.c @@ -1,7 +1,7 @@ /* Modula 2 language support routines for GDB, the GNU debugger. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2002, 2003, 2004, - 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -42,7 +42,7 @@ static void m2_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - c &= 0xFF; /* Avoid sign bit follies */ + c &= 0xFF; /* Avoid sign bit follies. */ if (PRINT_LITERAL_FORM (c)) { @@ -243,7 +243,8 @@ evaluate_subexp_modula2 (struct type *expect_type, struct expression *exp, type = TYPE_FIELD_TYPE (type, 0); if (type == NULL || (TYPE_CODE (type) != TYPE_CODE_PTR)) { - warning (_("internal error: unbounded array structure is unknown")); + warning (_("internal error: unbounded " + "array structure is unknown")); return evaluate_subexp_standard (expect_type, exp, pos, noside); } /* i18n: Do not translate the "_m2_contents" part! */ @@ -254,7 +255,7 @@ evaluate_subexp_modula2 (struct type *expect_type, struct expression *exp, if (value_type (arg1) != type) arg1 = value_cast (type, arg1); - type = check_typedef (value_type (arg1)); + check_typedef (value_type (arg1)); return value_ind (value_ptradd (arg1, value_as_long (arg2))); } else @@ -389,7 +390,8 @@ const struct language_defn m2_language_defn = basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ m2_op_print_tab, /* expression operators for printing */ 0, /* arrays are first-class (not c-style) */ 0, /* String lower bound */ diff --git a/contrib/gdb-7/gdb/m2-lang.h b/contrib/gdb-7/gdb/m2-lang.h index 87df81c3f0..88a085d9de 100644 --- a/contrib/gdb-7/gdb/m2-lang.h +++ b/contrib/gdb-7/gdb/m2-lang.h @@ -1,6 +1,6 @@ /* Modula 2 language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1998, 2000, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 1992, 1998, 2000, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/m2-typeprint.c b/contrib/gdb-7/gdb/m2-typeprint.c index 592df37827..0caf945d61 100644 --- a/contrib/gdb-7/gdb/m2-typeprint.c +++ b/contrib/gdb-7/gdb/m2-typeprint.c @@ -1,6 +1,6 @@ /* Support for printing Modula 2 types for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1995, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -67,7 +67,8 @@ int m2_is_unbounded_array (struct type *type); void -m2_print_type (struct type *type, const char *varstring, struct ui_file *stream, +m2_print_type (struct type *type, const char *varstring, + struct ui_file *stream, int show, int level) { enum type_code code; @@ -133,7 +134,7 @@ m2_print_type (struct type *type, const char *varstring, struct ui_file *stream, break; case TYPE_CODE_UNDEF: - /* i18n: Do not translate the "struct" part! */ + /* i18n: Do not translate the "struct" part! */ m2_unknown (_("undef"), type, stream, show, level); break; @@ -328,8 +329,8 @@ m2_short_set (struct type *type, struct ui_file *stream, int show, int level) int m2_is_long_set (struct type *type) { - LONGEST previous_high = 0; /* unnecessary initialization - keeps gcc -Wall happy */ + LONGEST previous_high = 0; /* Unnecessary initialization + keeps gcc -Wall happy. */ int len, i; struct type *range; @@ -467,7 +468,7 @@ m2_long_set (struct type *type, struct ui_file *stream, int show, int level) } } else - /* i18n: Do not translate the "SET OF" part! */ + /* i18n: Do not translate the "SET OF" part! */ fprintf_filtered(stream, _("SET OF ")); return 1; @@ -554,7 +555,7 @@ m2_record_fields (struct type *type, struct ui_file *stream, int show, if (TYPE_CODE (type) == TYPE_CODE_STRUCT) fprintf_filtered (stream, "RECORD\n"); else if (TYPE_CODE (type) == TYPE_CODE_UNION) - /* i18n: Do not translate "CASE" and "OF" */ + /* i18n: Do not translate "CASE" and "OF". */ fprintf_filtered (stream, _("CASE OF\n")); for (i = TYPE_N_BASECLASSES (type); i < len; i++) diff --git a/contrib/gdb-7/gdb/m2-valprint.c b/contrib/gdb-7/gdb/m2-valprint.c index e27ce8c1a2..ed997b16b6 100644 --- a/contrib/gdb-7/gdb/m2-valprint.c +++ b/contrib/gdb-7/gdb/m2-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Modula 2 values for GDB, the GNU debugger. Copyright (C) 1986, 1988, 1989, 1991, 1992, 1996, 1998, 2000, 2005, 2006, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -201,9 +201,10 @@ m2_print_unbounded_array (struct type *type, const gdb_byte *valaddr, len = unpack_field_as_long (type, valaddr + embedded_offset, 1); fprintf_filtered (stream, "{"); - m2_print_array_contents (value_type (val), value_contents(val), + m2_print_array_contents (value_type (val), + value_contents_for_printing (val), value_embedded_offset (val), addr, stream, - recurse, NULL, options, len); + recurse, val, options, len); fprintf_filtered (stream, ", HIGH = %d}", (int) len); } @@ -235,7 +236,7 @@ print_unpacked_pointer (struct type *type, && TYPE_CODE (elttype) == TYPE_CODE_INT && (options->format == 0 || options->format == 's') && addr != 0) - return val_print_string (TYPE_TARGET_TYPE (type), addr, -1, + return val_print_string (TYPE_TARGET_TYPE (type), NULL, addr, -1, stream, options); return 0; @@ -296,11 +297,11 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr, || ((current_language->la_language == language_m2) && (TYPE_CODE (type) == TYPE_CODE_CHAR))) && (options->format == 0 || options->format == 's')) - val_print_string (type, address, len+1, stream, options); + val_print_string (type, NULL, address, len+1, stream, options); else { fprintf_filtered (stream, "{"); - val_print_array_elements (type, valaddr + embedded_offset, + val_print_array_elements (type, valaddr, embedded_offset, address, stream, recurse, val, options, 0); fprintf_filtered (stream, "}"); @@ -309,12 +310,9 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr, } -/* Print data of type TYPE located at VALADDR (within GDB), which came from - the inferior at address ADDRESS, onto stdio stream STREAM according to - OPTIONS. The data at VALADDR is in target byte order. - - If the data are a string pointer, returns the number of string characters - printed. */ +/* See val_print for a description of the various parameters of this + function; they are identical. The semantics of the return value is + also identical to val_print. */ int m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, @@ -323,7 +321,7 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, const struct value_print_options *options) { struct gdbarch *gdbarch = get_type_arch (type); - unsigned int i = 0; /* Number of characters printed */ + unsigned int i = 0; /* Number of characters printed. */ unsigned len; struct type *elttype; unsigned eltlen; @@ -354,7 +352,7 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { unsigned int temp_len; - /* Look for a NULL char. */ + /* Look for a NULL char. */ for (temp_len = 0; (valaddr + embedded_offset)[temp_len] && temp_len < len && temp_len < options->print_max; @@ -370,8 +368,9 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, else { fprintf_filtered (stream, "{"); - val_print_array_elements (type, valaddr + embedded_offset, - address, stream, recurse, original_value, + val_print_array_elements (type, valaddr, embedded_offset, + address, stream, + recurse, original_value, options, 0); fprintf_filtered (stream, "}"); } @@ -386,8 +385,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, print_variable_at_address (type, valaddr + embedded_offset, stream, recurse, options); else if (options->format && options->format != 's') - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else { addr = unpack_pointer (type, valaddr + embedded_offset); @@ -448,8 +447,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_ENUM: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } len = TYPE_NFIELDS (type); @@ -475,8 +474,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_FUNC: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } /* FIXME, we should consider, at least for ANSI C language, eliminating @@ -495,8 +494,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -533,8 +532,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else val_print_type_code_int (type, valaddr + embedded_offset, stream); @@ -547,8 +546,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -564,8 +563,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, case TYPE_CODE_FLT: if (options->format) - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else print_floating (valaddr + embedded_offset, type, stream); break; diff --git a/contrib/gdb-7/gdb/macrocmd.c b/contrib/gdb-7/gdb/macrocmd.c index 74aa05221a..c77156a416 100644 --- a/contrib/gdb-7/gdb/macrocmd.c +++ b/contrib/gdb-7/gdb/macrocmd.c @@ -1,5 +1,6 @@ /* C preprocessor macro expansion commands for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -298,7 +299,7 @@ macro_define_command (char *exp, int from_tty) { alloced *= 2; argv = (char **) xrealloc (argv, alloced * sizeof (char *)); - /* Must update new_macro as well... */ + /* Must update new_macro as well... */ new_macro.argv = (const char * const *) argv; } argv[new_macro.argc] = extract_identifier (&exp, 1); diff --git a/contrib/gdb-7/gdb/macroexp.c b/contrib/gdb-7/gdb/macroexp.c index 73e68d76df..6080ee43ea 100644 --- a/contrib/gdb-7/gdb/macroexp.c +++ b/contrib/gdb-7/gdb/macroexp.c @@ -1,5 +1,6 @@ /* C preprocessor macro expansion for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -205,7 +206,7 @@ set_token (struct macro_buffer *tok, char *start, char *end) init_shared_buffer (tok, start, end - start); tok->last_token = 0; - /* Presumed; get_identifier may overwrite this. */ + /* Presumed; get_identifier may overwrite this. */ tok->is_identifier = 0; } @@ -334,7 +335,7 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end) else if (*p == 'L' || *p == 'u' || *p == 'U') p += 2; else - gdb_assert (0); + gdb_assert_not_reached ("unexpected character constant"); body_start = p; for (;;) @@ -389,7 +390,7 @@ get_string_literal (struct macro_buffer *tok, char *p, char *end) else if (*p == 'L' || *p == 'u' || *p == 'U') p += 2; else - gdb_assert (0); + gdb_assert_not_reached ("unexpected string literal"); for (;;) { @@ -703,7 +704,7 @@ struct macro_name_list { particular macro, and otherwise delegates the decision to another function/baton pair. But that makes the linked list of excluded macros chained through untyped baton pointers, which will make it - harder to debug. :( */ + harder to debug. :( */ static int currently_rescanning (struct macro_name_list *list, const char *name) { @@ -901,7 +902,8 @@ find_parameter (const struct macro_buffer *tok, return -1; for (i = 0; i < argc; ++i) - if (tok->len == strlen (argv[i]) && ! memcmp (tok->text, argv[i], tok->len)) + if (tok->len == strlen (argv[i]) + && !memcmp (tok->text, argv[i], tok->len)) return i; if (is_varargs && tok->len == va_arg_name->len @@ -1139,7 +1141,7 @@ substitute_args (struct macro_buffer *dest, its expansion to DEST. SRC is the input text following the ID token. We are currently rescanning the expansions of the macros named in NO_LOOP; don't re-expand them. Use LOOKUP_FUNC and - LOOKUP_BATON to find definitions for any nested macro references. + LOOKUP_BATON to find definitions for any nested macro references. Return 1 if we decided to expand it, zero otherwise. (If it's a function-like macro name that isn't followed by an argument list, @@ -1181,7 +1183,7 @@ expand (const char *id, struct macro_buffer *argv = NULL; struct macro_buffer substituted; struct macro_buffer substituted_src; - struct macro_buffer va_arg_name; + struct macro_buffer va_arg_name = {0}; int is_varargs = 0; if (def->argc >= 1) diff --git a/contrib/gdb-7/gdb/macroexp.h b/contrib/gdb-7/gdb/macroexp.h index fce77855fb..3b7c319547 100644 --- a/contrib/gdb-7/gdb/macroexp.h +++ b/contrib/gdb-7/gdb/macroexp.h @@ -1,5 +1,6 @@ /* Interface to C preprocessor macro expansion for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macroscope.c b/contrib/gdb-7/gdb/macroscope.c index 844e2e5b29..b529e68c1f 100644 --- a/contrib/gdb-7/gdb/macroscope.c +++ b/contrib/gdb-7/gdb/macroscope.c @@ -1,5 +1,6 @@ /* Functions for deciding which macros are currently in scope. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -101,12 +102,13 @@ default_macro_scope (void) struct symtab_and_line sal; struct macro_scope *ms; struct frame_info *frame; + CORE_ADDR pc; /* If there's a selected frame, use its PC. */ frame = deprecated_safe_get_selected_frame (); - if (frame) - sal = find_pc_line (get_frame_pc (frame), 0); - + if (frame && get_frame_pc_if_available (frame, &pc)) + sal = find_pc_line (pc, 0); + /* Fall back to the current listing position. */ else { diff --git a/contrib/gdb-7/gdb/macroscope.h b/contrib/gdb-7/gdb/macroscope.h index 55937897da..fbbecfa9b1 100644 --- a/contrib/gdb-7/gdb/macroscope.h +++ b/contrib/gdb-7/gdb/macroscope.h @@ -1,5 +1,6 @@ /* Interface to functions for deciding which macros are currently in scope. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macrotab.c b/contrib/gdb-7/gdb/macrotab.c index 93651ab39a..cba285dc9d 100644 --- a/contrib/gdb-7/gdb/macrotab.c +++ b/contrib/gdb-7/gdb/macrotab.c @@ -1,5 +1,6 @@ /* C preprocessor macro tables for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -20,6 +21,7 @@ #include "defs.h" #include "gdb_obstack.h" #include "splay-tree.h" +#include "filenames.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" @@ -159,7 +161,7 @@ struct macro_key struct macro_table *table; /* The name of the macro. This is in the table's bcache, if it has - one. */ + one. */ const char *name; /* The source file and line number where the definition's scope @@ -469,8 +471,8 @@ macro_include (struct macro_source_file *source, First, squawk. */ complaint (&symfile_complaints, - _("both `%s' and `%s' allegedly #included at %s:%d"), included, - (*link)->filename, source->filename, line); + _("both `%s' and `%s' allegedly #included at %s:%d"), + included, (*link)->filename, source->filename, line); /* Now, choose a new, unoccupied line number for this #inclusion, after the alleged #inclusion line. */ @@ -499,7 +501,7 @@ struct macro_source_file * macro_lookup_inclusion (struct macro_source_file *source, const char *name) { /* Is SOURCE itself named NAME? */ - if (strcmp (name, source->filename) == 0) + if (filename_cmp (name, source->filename) == 0) return source; /* The filename in the source structure is probably a full path, but @@ -509,11 +511,12 @@ macro_lookup_inclusion (struct macro_source_file *source, const char *name) int src_name_len = strlen (source->filename); /* We do mean < here, and not <=; if the lengths are the same, - then the strcmp above should have triggered, and we need to + then the filename_cmp above should have triggered, and we need to check for a slash here. */ if (name_len < src_name_len - && source->filename[src_name_len - name_len - 1] == '/' - && strcmp (name, source->filename + src_name_len - name_len) == 0) + && IS_DIR_SEPARATOR (source->filename[src_name_len - name_len - 1]) + && filename_cmp (name, + source->filename + src_name_len - name_len) == 0) return source; } @@ -728,7 +731,8 @@ check_for_redefinition (struct macro_source_file *source, int line, if (! same) { complaint (&symfile_complaints, - _("macro `%s' redefined at %s:%d; original definition at %s:%d"), + _("macro `%s' redefined at %s:%d; " + "original definition at %s:%d"), name, source->filename, line, found_key->start_file->filename, found_key->start_line); } diff --git a/contrib/gdb-7/gdb/macrotab.h b/contrib/gdb-7/gdb/macrotab.h index e929739d53..d2b2b63290 100644 --- a/contrib/gdb-7/gdb/macrotab.h +++ b/contrib/gdb-7/gdb/macrotab.h @@ -1,5 +1,6 @@ /* Interface to C preprocessor macro tables for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/main.c b/contrib/gdb-7/gdb/main.c index bfd1213573..ff305a1f69 100644 --- a/contrib/gdb-7/gdb/main.c +++ b/contrib/gdb-7/gdb/main.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -42,16 +42,17 @@ #include "source.h" #include "cli/cli-cmds.h" #include "python/python.h" +#include "objfiles.h" /* The selected interpreter. This will be used as a set command variable, so it should always be malloc'ed - since - do_setshow_command will free it. */ + do_setshow_command will free it. */ char *interpreter_p; -/* Whether xdb commands will be handled */ +/* Whether xdb commands will be handled. */ int xdb_commands = 0; -/* Whether dbx commands will be handled */ +/* Whether dbx commands will be handled. */ int dbx_commands = 0; /* System root path, used to find libraries etc. */ @@ -68,7 +69,7 @@ struct ui_file *gdb_stdout; struct ui_file *gdb_stderr; struct ui_file *gdb_stdlog; struct ui_file *gdb_stdin; -/* target IO streams */ +/* Target IO streams. */ struct ui_file *gdb_stdtargin; struct ui_file *gdb_stdtarg; struct ui_file *gdb_stdtargerr; @@ -85,7 +86,7 @@ int batch_silent = 0; int return_child_result = 0; int return_child_result_value = -1; -/* Whether to enable writing into executable and core files */ +/* Whether to enable writing into executable and core files. */ extern int write_files; /* GDB as it has been invoked from the command line (i.e. argv[0]). */ @@ -93,8 +94,8 @@ static char *gdb_program_name; static void print_gdb_help (struct ui_file *); -/* These two are used to set the external editor commands when gdb is farming - out files to be edited by another program. */ +/* These two are used to set the external editor commands when gdb is + farming out files to be edited by another program. */ extern char *external_editor_command; @@ -150,11 +151,11 @@ relocate_directory (const char *progname, const char *initial, int flag) return dir; } -/* Compute the locations of init files that GDB should source and return - them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If there is - no system gdbinit (resp. home gdbinit and local gdbinit) to be loaded, - then SYSTEM_GDBINIT (resp. HOME_GDBINIT and LOCAL_GDBINIT) is set to - NULL. */ +/* Compute the locations of init files that GDB should source and + return them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If + there is no system gdbinit (resp. home gdbinit and local gdbinit) + to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and + LOCAL_GDBINIT) is set to NULL. */ static void get_init_files (char **system_gdbinit, char **home_gdbinit, @@ -185,7 +186,7 @@ get_init_files (char **system_gdbinit, /* If the .gdbinit file in the current directory is the same as the $HOME/.gdbinit file, it should not be sourced. homebuf - and cwdbuf are used in that purpose. Make sure that the stats + and cwdbuf are used in that purpose. Make sure that the stats are zero in case one of them fails (this guarantees that they won't match if either exists). */ @@ -219,7 +220,7 @@ get_init_files (char **system_gdbinit, } /* Call command_loop. If it happens to return, pass that through as a - non-zero return status. */ + non-zero return status. */ static int captured_command_loop (void *data) @@ -231,12 +232,12 @@ captured_command_loop (void *data) the do_cleanups() below is redundant. Unfortunately, many FUNCs are not that well behaved. do_cleanups should either be replaced with a do_cleanups call (to cover the problem) or an assertion - check to detect bad FUNCs code. */ + check to detect bad FUNCs code. */ do_cleanups (ALL_CLEANUPS); /* If the command_loop returned, normally (rather than threw an - error) we try to quit. If the quit is aborted, catch_errors() + error) we try to quit. If the quit is aborted, catch_errors() which called this catch the signal and restart the command - loop. */ + loop. */ quit_command (NULL, instream == stdin); return 1; } @@ -259,7 +260,8 @@ captured_main (void *data) char *cdarg = NULL; char *ttyarg = NULL; - /* These are static so that we can take their address in an initializer. */ + /* These are static so that we can take their address in an + initializer. */ static int print_help; static int print_version; @@ -290,6 +292,7 @@ captured_main (void *data) int i; int save_auto_load; + struct objfile *objfile; struct cleanup *pre_stat_chain = make_command_stats_cleanup (0); @@ -315,7 +318,7 @@ captured_main (void *data) quit_flag = 0; line = (char *) xmalloc (linesize); - line[0] = '\0'; /* Terminate saved (now empty) cmd line */ + line[0] = '\0'; /* Terminate saved (now empty) cmd line. */ instream = stdin; gdb_stdout = stdio_fileopen (stdout); @@ -330,9 +333,10 @@ captured_main (void *data) if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) /* Don't use *_filtered or warning() (which relies on - current_target) until after initialize_all_files(). */ + current_target) until after initialize_all_files(). */ fprintf_unfiltered (gdb_stderr, - _("%s: warning: error finding working directory: %s\n"), + _("%s: warning: error finding " + "working directory: %s\n"), argv[0], safe_strerror (errno)); current_directory = gdb_dirbuf; @@ -348,11 +352,14 @@ captured_main (void *data) GDB_DATADIR_RELOCATABLE); #ifdef WITH_PYTHON_PATH - /* For later use in helping Python find itself. */ - python_libdir = relocate_directory (argv[0], - concat (WITH_PYTHON_PATH, - SLASH_STRING, "lib", NULL), - PYTHON_PATH_RELOCATABLE); + { + /* For later use in helping Python find itself. */ + char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", NULL); + + python_libdir = relocate_directory (argv[0], tmp, + PYTHON_PATH_RELOCATABLE); + xfree (tmp); + } #endif #ifdef RELOC_SRCDIR @@ -398,9 +405,9 @@ captured_main (void *data) {"batch", no_argument, &batch_flag, 1}, {"epoch", no_argument, &epoch_interface, 1}, - /* This is a synonym for "--annotate=1". --annotate is now preferred, - but keep this here for a long time because people will be running - emacses which use --fullname. */ + /* This is a synonym for "--annotate=1". --annotate is now + preferred, but keep this here for a long time because people + will be running emacses which use --fullname. */ {"fullname", no_argument, 0, 'f'}, {"f", no_argument, 0, 'f'}, @@ -430,6 +437,7 @@ captured_main (void *data) {"i", required_argument, 0, 'i'}, {"directory", required_argument, 0, 'd'}, {"d", required_argument, 0, 'd'}, + {"data-directory", required_argument, 0, 'D'}, {"cd", required_argument, 0, OPT_CD}, {"tty", required_argument, 0, 't'}, {"baud", required_argument, 0, 'b'}, @@ -510,7 +518,8 @@ captured_main (void *data) break; case 'f': annotation_level = 1; -/* We have probably been invoked from emacs. Disable window interface. */ + /* We have probably been invoked from emacs. Disable + window interface. */ use_windows = 0; break; case 's': @@ -549,13 +558,20 @@ captured_main (void *data) batch_flag = batch_silent = 1; gdb_stdout = ui_file_new(); break; + case 'D': + xfree (gdb_datadir); + gdb_datadir = xstrdup (optarg); + break; #ifdef GDBTK case 'z': { -extern int gdbtk_test (char *); + extern int gdbtk_test (char *); + if (!gdbtk_test (optarg)) { - fprintf_unfiltered (gdb_stderr, _("%s: unable to load tclcommand file \"%s\""), + fprintf_unfiltered (gdb_stderr, + _("%s: unable to load " + "tclcommand file \"%s\""), argv[0], optarg); exit (1); } @@ -598,7 +614,7 @@ extern int gdbtk_test (char *); if (i == 0 && p == optarg) /* Don't use *_filtered or warning() (which relies on - current_target) until after initialize_all_files(). */ + current_target) until after initialize_all_files(). */ fprintf_unfiltered (gdb_stderr, @@ -616,11 +632,11 @@ extern int gdbtk_test (char *); if (i == 0 && p == optarg) /* Don't use *_filtered or warning() (which relies on - current_target) until after initialize_all_files(). */ + current_target) until after initialize_all_files(). */ - fprintf_unfiltered - (gdb_stderr, - _("warning: could not set timeout limit to `%s'.\n"), optarg); + fprintf_unfiltered (gdb_stderr, + _("warning: could not set " + "timeout limit to `%s'.\n"), optarg); else remote_timeout = i; } @@ -628,7 +644,8 @@ extern int gdbtk_test (char *); case '?': fprintf_unfiltered (gdb_stderr, - _("Use `%s --help' for a complete list of options.\n"), + _("Use `%s --help' for a " + "complete list of options.\n"), argv[0]); exit (1); } @@ -648,8 +665,8 @@ extern int gdbtk_test (char *); control of the console via the deprecated_init_ui_hook (). */ gdb_init (argv[0]); - /* Now that gdb_init has created the initial inferior, we're in position - to set args for that inferior. */ + /* Now that gdb_init has created the initial inferior, we're in + position to set args for that inferior. */ if (set_args) { /* The remaining options are the command-line options for the @@ -658,7 +675,8 @@ extern int gdbtk_test (char *); if (optind >= argc) { fprintf_unfiltered (gdb_stderr, - _("%s: `--args' specified but no program specified\n"), + _("%s: `--args' specified but " + "no program specified\n"), argv[0]); exit (1); } @@ -693,15 +711,16 @@ extern int gdbtk_test (char *); /* Any argument left on the command line is unexpected and will be ignored. Inform the user. */ if (optind < argc) - fprintf_unfiltered (gdb_stderr, _("\ -Excess command line arguments ignored. (%s%s)\n"), + fprintf_unfiltered (gdb_stderr, + _("Excess command line " + "arguments ignored. (%s%s)\n"), argv[optind], (optind == argc - 1) ? "" : " ..."); } - /* Lookup gdbinit files. Note that the gdbinit file name may be overriden - during file initialization, so get_init_files should be called after - gdb_init. */ + /* Lookup gdbinit files. Note that the gdbinit file name may be + overriden during file initialization, so get_init_files should be + called after gdb_init. */ get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit); /* Do these (and anything which might call wrap_here or *_filtered) @@ -730,19 +749,19 @@ Excess command line arguments ignored. (%s%s)\n"), it isn't encapsulated in MI output. */ if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0) { - /* Print all the junk at the top, with trailing "..." if we are about - to read a symbol file (possibly slowly). */ + /* Print all the junk at the top, with trailing "..." if we are + about to read a symbol file (possibly slowly). */ print_gdb_version (gdb_stdout); if (symarg) printf_filtered (".."); wrap_here (""); printf_filtered ("\n"); - gdb_flush (gdb_stdout); /* Force to screen during slow operations */ + gdb_flush (gdb_stdout); /* Force to screen during slow + operations. */ } - /* Install the default UI. All the interpreters should have had a - look at things by now. Initialize the default interpreter. */ + look at things by now. Initialize the default interpreter. */ { /* Find it. */ @@ -766,14 +785,15 @@ Excess command line arguments ignored. (%s%s)\n"), any sane interpreter. */ if (!quiet && !current_interp_named_p (INTERP_MI1)) { - /* Print all the junk at the top, with trailing "..." if we are about - to read a symbol file (possibly slowly). */ + /* Print all the junk at the top, with trailing "..." if we are + about to read a symbol file (possibly slowly). */ print_gdb_version (gdb_stdout); if (symarg) printf_filtered (".."); wrap_here (""); printf_filtered ("\n"); - gdb_flush (gdb_stdout); /* Force to screen during slow operations */ + gdb_flush (gdb_stdout); /* Force to screen during slow + operations. */ } /* Set off error and warning messages with a blank line. */ @@ -807,7 +827,8 @@ Excess command line arguments ignored. (%s%s)\n"), xfree (dirarg); /* Skip auto-loading section-specified scripts until we've sourced - local_gdbinit (which is often used to augment the source search path). */ + local_gdbinit (which is often used to augment the source search + path). */ save_auto_load = gdbpy_global_auto_load; gdbpy_global_auto_load = 0; @@ -817,21 +838,25 @@ Excess command line arguments ignored. (%s%s)\n"), { /* The exec file and the symbol-file are the same. If we can't open it, better only print one error message. - catch_command_errors returns non-zero on success! */ - if (catch_command_errors (exec_file_attach, execarg, !batch_flag, RETURN_MASK_ALL)) - catch_command_errors (symbol_file_add_main, symarg, !batch_flag, RETURN_MASK_ALL); + catch_command_errors returns non-zero on success! */ + if (catch_command_errors (exec_file_attach, execarg, + !batch_flag, RETURN_MASK_ALL)) + catch_command_errors (symbol_file_add_main, symarg, + !batch_flag, RETURN_MASK_ALL); } else { if (execarg != NULL) - catch_command_errors (exec_file_attach, execarg, !batch_flag, RETURN_MASK_ALL); + catch_command_errors (exec_file_attach, execarg, + !batch_flag, RETURN_MASK_ALL); if (symarg != NULL) - catch_command_errors (symbol_file_add_main, symarg, !batch_flag, RETURN_MASK_ALL); + catch_command_errors (symbol_file_add_main, symarg, + !batch_flag, RETURN_MASK_ALL); } if (corearg && pidarg) - error (_("\ -Can't attach to process and specify a core file at the same time.")); + error (_("Can't attach to process and specify " + "a core file at the same time.")); if (corearg != NULL) catch_command_errors (core_file_command, corearg, @@ -860,7 +885,7 @@ Can't attach to process and specify a core file at the same time.")); if (ttyarg != NULL) set_inferior_io_terminal (ttyarg); - /* Error messages should no longer be distinguished with extra output. */ + /* Error messages should no longer be distinguished with extra output. */ error_pre_print = NULL; quit_pre_print = NULL; warning_pre_print = _("warning: "); @@ -875,8 +900,8 @@ Can't attach to process and specify a core file at the same time.")); We wait until now because it is common to add to the source search path in local_gdbinit. */ gdbpy_global_auto_load = save_auto_load; - if (symfile_objfile != NULL) - load_auto_scripts_for_objfile (symfile_objfile); + ALL_OBJFILES (objfile) + load_auto_scripts_for_objfile (objfile); for (i = 0; i < ncmd; i++) { @@ -889,7 +914,8 @@ Can't attach to process and specify a core file at the same time.")); } xfree (cmdarg); - /* Read in the old history after all the command files have been read. */ + /* Read in the old history after all the command files have been + read. */ init_history (); if (batch_flag) @@ -904,7 +930,7 @@ Can't attach to process and specify a core file at the same time.")); /* NOTE: cagney/1999-11-07: There is probably no reason for not moving this loop and the code found in captured_command_loop() into the command_loop() proper. The main thing holding back that - change - SET_TOP_LEVEL() - has been eliminated. */ + change - SET_TOP_LEVEL() - has been eliminated. */ while (1) { catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); diff --git a/contrib/gdb-7/gdb/main.h b/contrib/gdb-7/gdb/main.h index 4b27c1a325..fbbc473a45 100644 --- a/contrib/gdb-7/gdb/main.h +++ b/contrib/gdb-7/gdb/main.h @@ -1,6 +1,7 @@ /* Main interface for GDB, the GNU debugger. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/maint.c b/contrib/gdb-7/gdb/maint.c index 28fd610b2c..ca9b3cca64 100644 --- a/contrib/gdb-7/gdb/maint.c +++ b/contrib/gdb-7/gdb/maint.c @@ -1,7 +1,7 @@ /* Support for GDB maintenance commands. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, - 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -91,7 +91,8 @@ show_watchdog (struct ui_file *file, int from_tty, static void maintenance_command (char *args, int from_tty) { - printf_unfiltered (_("\"maintenance\" must be followed by the name of a maintenance command.\n")); + printf_unfiltered (_("\"maintenance\" must be followed by " + "the name of a maintenance command.\n")); help_list (maintenancelist, "maintenance ", -1, gdb_stdout); } @@ -116,7 +117,7 @@ maintenance_dump_me (char *args, int from_tty) /* Stimulate the internal error mechanism that GDB uses when an internal problem is detected. Allows testing of the mechanism. Also useful when the user wants to drop a core file but not exit - GDB. */ + GDB. */ static void maintenance_internal_error (char *args, int from_tty) @@ -127,7 +128,7 @@ maintenance_internal_error (char *args, int from_tty) /* Stimulate the internal error mechanism that GDB uses when an internal problem is detected. Allows testing of the mechanism. Also useful when the user wants to drop a core file but not exit - GDB. */ + GDB. */ static void maintenance_internal_warning (char *args, int from_tty) @@ -141,7 +142,7 @@ maintenance_internal_warning (char *args, int from_tty) debuggee's process space, and have gdb fetch and demangle that string. If we have a char* pointer "ptr" that points to a string, we might want to be able to given just the name and have GDB - demangle and print what it points to, etc. (FIXME) */ + demangle and print what it points to, etc. (FIXME) */ static void maintenance_demangle (char *args, int from_tty) @@ -150,7 +151,8 @@ maintenance_demangle (char *args, int from_tty) if (args == NULL || *args == '\0') { - printf_unfiltered (_("\"maintenance demangle\" takes an argument to demangle.\n")); + printf_unfiltered (_("\"maintenance demangle\" takes " + "an argument to demangle.\n")); } else { @@ -193,7 +195,8 @@ maintenance_space_display (char *args, int from_tty) static void maintenance_info_command (char *arg, int from_tty) { - printf_unfiltered (_("\"maintenance info\" must be followed by the name of an info command.\n")); + printf_unfiltered (_("\"maintenance info\" must be followed " + "by the name of an info command.\n")); help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout); } @@ -207,12 +210,12 @@ match_substring (const char *string, const char *substr) while ((tok = strstr (string, substr)) != NULL) { - /* Got a partial match. Is it a whole word? */ + /* Got a partial match. Is it a whole word? */ if (tok == string || tok[-1] == ' ' || tok[-1] == '\t') { - /* Token is delimited at the front... */ + /* Token is delimited at the front... */ if (tok[substr_len] == ' ' || tok[substr_len] == '\t' || tok[substr_len] == '\0') @@ -438,15 +441,15 @@ maintenance_print_architecture (char *args, int from_tty) static void maintenance_print_command (char *arg, int from_tty) { - printf_unfiltered (_("\"maintenance print\" must be followed by the name of a print command.\n")); + printf_unfiltered (_("\"maintenance print\" must be followed " + "by the name of a print command.\n")); help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout); } /* The "maintenance translate-address" command converts a section and address to a symbol. This can be called in two ways: maintenance translate-address - or maintenance translate-address - */ + or maintenance translate-address . */ static void maintenance_translate_address (char *arg, int from_tty) @@ -464,14 +467,14 @@ maintenance_translate_address (char *arg, int from_tty) p = arg; if (!isdigit (*p)) - { /* See if we have a valid section name */ - while (*p && !isspace (*p)) /* Find end of section name */ + { /* See if we have a valid section name. */ + while (*p && !isspace (*p)) /* Find end of section name. */ p++; - if (*p == '\000') /* End of command? */ + if (*p == '\000') /* End of command? */ error (_("Need to specify and

")); *p++ = '\000'; while (isspace (*p)) - p++; /* Skip whitespace */ + p++; /* Skip whitespace. */ ALL_OBJSECTIONS (objfile, sect) { @@ -493,7 +496,8 @@ maintenance_translate_address (char *arg, int from_tty) if (sym) { const char *symbol_name = SYMBOL_PRINT_NAME (sym); - const char *symbol_offset = pulongest (address - SYMBOL_VALUE_ADDRESS (sym)); + const char *symbol_offset + = pulongest (address - SYMBOL_VALUE_ADDRESS (sym)); sect = SYMBOL_OBJ_SECTION(sym); if (sect != NULL) @@ -509,7 +513,8 @@ maintenance_translate_address (char *arg, int from_tty) if (MULTI_OBJFILE_P ()) printf_filtered (_("%s + %s in section %s of %s\n"), - symbol_name, symbol_offset, section_name, obj_name); + symbol_name, symbol_offset, + section_name, obj_name); else printf_filtered (_("%s + %s in section %s\n"), symbol_name, symbol_offset, section_name); @@ -529,7 +534,7 @@ maintenance_translate_address (char *arg, int from_tty) /* When a command is deprecated the user will be warned the first time the command is used. If possible, a replacement will be - offered. */ + offered. */ static void maintenance_deprecate (char *args, int from_tty) @@ -559,7 +564,7 @@ the command you want to undeprecate.\n")); } -/* You really shouldn't be using this. It is just for the testsuite. +/* You really shouldn't be using this. It is just for the testsuite. Rather, you should use deprecate_cmd() when the command is created in _initialize_blah(). @@ -589,7 +594,7 @@ maintenance_do_deprecate (char *text, int deprecate) if (deprecate) { - /* look for a replacement command */ + /* Look for a replacement command. */ start_ptr = strchr (text, '\"'); if (start_ptr != NULL) { @@ -612,7 +617,7 @@ maintenance_do_deprecate (char *text, int deprecate) Note the MALLOCED_REPLACEMENT test. If the command's replacement string was allocated at compile time we don't want to free the - memory. */ + memory. */ if (alias) { if (alias->flags & MALLOCED_REPLACEMENT) @@ -639,6 +644,7 @@ maintenance_do_deprecate (char *text, int deprecate) cmd->flags |= MALLOCED_REPLACEMENT; return; } + xfree (replacement); } /* Maintenance set/show framework. */ @@ -649,7 +655,8 @@ struct cmd_list_element *maintenance_show_cmdlist; static void maintenance_set_cmd (char *args, int from_tty) { - printf_unfiltered (_("\"maintenance set\" must be followed by the name of a set command.\n")); + printf_unfiltered (_("\"maintenance set\" must be followed " + "by the name of a set command.\n")); help_list (maintenance_set_cmdlist, "maintenance set ", -1, gdb_stdout); } @@ -691,7 +698,8 @@ mcleanup_wrapper (void) } static void -maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c) +maintenance_set_profile_cmd (char *args, int from_tty, + struct cmd_list_element *c) { if (maintenance_profile_p == profiling_state) return; @@ -724,7 +732,8 @@ maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element * } #else static void -maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c) +maintenance_set_profile_cmd (char *args, int from_tty, + struct cmd_list_element *c) { error (_("Profiling support is not available on this system.")); } @@ -873,7 +882,8 @@ Takes an optional file parameter."), _("Check consistency of psymtabs and symtabs."), &maintenancelist); - add_cmd ("translate-address", class_maintenance, maintenance_translate_address, + add_cmd ("translate-address", class_maintenance, + maintenance_translate_address, _("Translate a section name and address to a symbol."), &maintenancelist); diff --git a/contrib/gdb-7/gdb/mdebugread.c b/contrib/gdb-7/gdb/mdebugread.c index 2e18fa461b..e224f19180 100644 --- a/contrib/gdb-7/gdb/mdebugread.c +++ b/contrib/gdb-7/gdb/mdebugread.c @@ -1,8 +1,8 @@ /* Read a symbol table in ECOFF format (Third-Eye). Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Original version contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor @@ -45,6 +45,7 @@ #include "symtab.h" #include "gdbtypes.h" #include "gdbcore.h" +#include "filenames.h" #include "objfiles.h" #include "gdb_obstack.h" #include "buildsym.h" @@ -61,17 +62,17 @@ #include "bfd.h" -#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */ +#include "coff/ecoff.h" /* COFF-like aspects of ecoff files. */ #include "libaout.h" /* Private BFD a.out information. */ #include "aout/aout64.h" -#include "aout/stab_gnu.h" /* STABS information */ +#include "aout/stab_gnu.h" /* STABS information. */ #include "expression.h" extern void _initialize_mdebugread (void); -/* Provide a way to test if we have both ECOFF and ELF symbol tables. +/* Provide a way to test if we have both ECOFF and ELF symbol tables. We use this define in order to know whether we should override a symbol's ECOFF section with its ELF section. This is necessary in case the symbol's ELF section could not be represented in ECOFF. */ @@ -119,7 +120,7 @@ struct symloc #define SC_IS_SBSS(sc) ((sc) == scSBss) #define SC_IS_UNDEF(sc) ((sc) == scUndefined || (sc) == scSUndefined) -/* Various complaints about symbol reading that don't abort the process */ +/* Various complaints about symbol reading that don't abort the process. */ static void index_complaint (const char *arg1) { @@ -142,7 +143,8 @@ basic_type_complaint (int arg1, const char *arg2) static void bad_tag_guess_complaint (const char *arg1) { - complaint (&symfile_complaints, _("guessed tag type of %s incorrectly"), arg1); + complaint (&symfile_complaints, + _("guessed tag type of %s incorrectly"), arg1); } static void @@ -158,18 +160,18 @@ unexpected_type_code_complaint (const char *arg1) complaint (&symfile_complaints, _("unexpected type code for %s"), arg1); } -/* Macros and extra defs */ +/* Macros and extra defs. */ -/* Puns: hard to find whether -g was used and how */ +/* Puns: hard to find whether -g was used and how. */ #define MIN_GLEVEL GLEVEL_0 #define compare_glevel(a,b) \ (((a) == GLEVEL_3) ? ((b) < GLEVEL_3) : \ ((b) == GLEVEL_3) ? -1 : (int)((b) - (a))) -/* Things that really are local to this module */ +/* Things that really are local to this module. */ -/* Remember what we deduced to be the source language of this psymtab. */ +/* Remember what we deduced to be the source language of this psymtab. */ static enum language psymtab_language = language_unknown; @@ -185,22 +187,22 @@ static const struct ecoff_debug_swap *debug_swap; static struct ecoff_debug_info *debug_info; -/* Pointer to current file decriptor record, and its index */ +/* Pointer to current file decriptor record, and its index. */ static FDR *cur_fdr; static int cur_fd; -/* Index of current symbol */ +/* Index of current symbol. */ static int cur_sdx; /* Note how much "debuggable" this image is. We would like - to see at least one FDR with full symbols */ + to see at least one FDR with full symbols. */ static int max_gdbinfo; static int max_glevel; -/* When examining .o files, report on undefined symbols */ +/* When examining .o files, report on undefined symbols. */ static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs; @@ -212,7 +214,7 @@ static char stabs_symbol[] = STABS_SYMBOL; static int found_ecoff_debugging_info; -/* Forward declarations */ +/* Forward declarations. */ static int upgrade_type (int, struct type **, int, union aux_ext *, int, char *); @@ -232,7 +234,7 @@ enum block_type { FUNCTION_BLOCK, NON_FUNCTION_BLOCK }; static struct block *new_block (enum block_type); -static struct symtab *new_symtab (char *, int, struct objfile *); +static struct symtab *new_symtab (const char *, int, struct objfile *); static struct linetable *new_linetable (int); @@ -248,7 +250,7 @@ static void sort_blocks (struct symtab *); static struct partial_symtab *new_psymtab (char *, struct objfile *); -static void psymtab_to_symtab_1 (struct partial_symtab *, char *); +static void psymtab_to_symtab_1 (struct partial_symtab *, const char *); static void add_block (struct block *, struct symtab *); @@ -266,7 +268,7 @@ static char *mdebug_next_symbol_text (struct objfile *); /* Exported procedure: Builds a symtab from the PST partial one. Restores the environment in effect when PST was created, delegates most of the work to an ancillary procedure, and sorts - and reorders the symtab list at the end */ + and reorders the symtab list at the end. */ static void mdebug_psymtab_to_symtab (struct partial_symtab *pst) @@ -285,16 +287,16 @@ mdebug_psymtab_to_symtab (struct partial_symtab *pst) psymtab_to_symtab_1 (pst, pst->filename); /* Match with global symbols. This only needs to be done once, - after all of the symtabs and dependencies have been read in. */ + after all of the symtabs and dependencies have been read in. */ scan_file_globals (pst->objfile); if (info_verbose) printf_filtered (_("done.\n")); } -/* File-level interface functions */ +/* File-level interface functions. */ -/* Find a file descriptor given its index RF relative to a file CF */ +/* Find a file descriptor given its index RF relative to a file CF. */ static FDR * get_rfd (int cf, int rf) @@ -305,7 +307,7 @@ get_rfd (int cf, int rf) fdrs = debug_info->fdr; f = fdrs + cf; - /* Object files do not have the RFD table, all refs are absolute */ + /* Object files do not have the RFD table, all refs are absolute. */ if (f->rfdBase == 0) return fdrs + rf; (*debug_swap->swap_rfd_in) (cur_bfd, @@ -316,7 +318,7 @@ get_rfd (int cf, int rf) return fdrs + rfd; } -/* Return a safer print NAME for a file descriptor */ +/* Return a safer print NAME for a file descriptor. */ static char * fdr_name (FDR *f) @@ -372,9 +374,11 @@ mdebug_build_psymtabs (struct objfile *objfile, if (compare_glevel (max_glevel, GLEVEL_2) < 0) { if (max_gdbinfo == 0) - printf_unfiltered (_("\n%s not compiled with -g, debugging support is limited.\n"), + printf_unfiltered (_("\n%s not compiled with -g, " + "debugging support is limited.\n"), objfile->name); - printf_unfiltered (_("You should compile with -g2 or -g3 for best debugging support.\n")); + printf_unfiltered (_("You should compile with -g2 or " + "-g3 for best debugging support.\n")); gdb_flush (gdb_stdout); } #endif @@ -382,7 +386,7 @@ mdebug_build_psymtabs (struct objfile *objfile, /* Local utilities */ -/* Map of FDR indexes to partial symtabs */ +/* Map of FDR indexes to partial symtabs. */ struct pst_map { @@ -395,13 +399,13 @@ struct pst_map /* Utility stack, used to nest procedures and blocks properly. It is a doubly linked list, to avoid too many alloc/free. Since we might need it quite a few times it is NOT deallocated - after use. */ + after use. */ static struct parse_stack { struct parse_stack *next, *prev; - struct symtab *cur_st; /* Current symtab. */ - struct block *cur_block; /* Block in it. */ + struct symtab *cur_st; /* Current symtab. */ + struct block *cur_block; /* Block in it. */ /* What are we parsing. stFile, or stBlock are for files and blocks. stProc or stStaticProc means we have seen the start of a @@ -411,28 +415,28 @@ static struct parse_stack int blocktype; - struct type *cur_type; /* Type we parse fields for. */ - int cur_field; /* Field number in cur_type. */ - CORE_ADDR procadr; /* Start addres of this procedure */ - int numargs; /* Its argument count */ + struct type *cur_type; /* Type we parse fields for. */ + int cur_field; /* Field number in cur_type. */ + CORE_ADDR procadr; /* Start addres of this procedure. */ + int numargs; /* Its argument count. */ } *top_stack; /* Top stack ptr */ -/* Enter a new lexical context */ +/* Enter a new lexical context. */ static void push_parse_stack (void) { struct parse_stack *new; - /* Reuse frames if possible */ + /* Reuse frames if possible. */ if (top_stack && top_stack->prev) new = top_stack->prev; else new = (struct parse_stack *) xzalloc (sizeof (struct parse_stack)); - /* Initialize new frame with previous content */ + /* Initialize new frame with previous content. */ if (top_stack) { struct parse_stack *prev = new->prev; @@ -445,7 +449,7 @@ push_parse_stack (void) top_stack = new; } -/* Exit a lexical context */ +/* Exit a lexical context. */ static void pop_parse_stack (void) @@ -460,7 +464,7 @@ pop_parse_stack (void) /* Cross-references might be to things we haven't looked at yet, e.g. type references. To avoid too many type duplications we keep a quick fixup table, an array - of lists of references indexed by file descriptor */ + of lists of references indexed by file descriptor. */ struct mdebug_pending { @@ -479,7 +483,7 @@ struct mdebug_pending static struct mdebug_pending **pending_list; -/* Check whether we already saw symbol SH in file FH */ +/* Check whether we already saw symbol SH in file FH. */ static struct mdebug_pending * is_pending_symbol (FDR *fh, char *sh) @@ -487,14 +491,14 @@ is_pending_symbol (FDR *fh, char *sh) int f_idx = fh - debug_info->fdr; struct mdebug_pending *p; - /* Linear search is ok, list is typically no more than 10 deep */ + /* Linear search is ok, list is typically no more than 10 deep. */ for (p = pending_list[f_idx]; p; p = p->next) if (p->s == sh) break; return p; } -/* Add a new symbol SH of type T */ +/* Add a new symbol SH of type T. */ static void add_pending (FDR *fh, char *sh, struct type *t) @@ -502,7 +506,7 @@ add_pending (FDR *fh, char *sh, struct type *t) int f_idx = fh - debug_info->fdr; struct mdebug_pending *p = is_pending_symbol (fh, sh); - /* Make sure we do not make duplicates */ + /* Make sure we do not make duplicates. */ if (!p) { p = ((struct mdebug_pending *) @@ -516,9 +520,9 @@ add_pending (FDR *fh, char *sh, struct type *t) } -/* Parsing Routines proper. */ +/* Parsing Routines proper. */ -/* Parse a single symbol. Mostly just make up a GDB symbol for it. +/* Parse a single symbol. Mostly just make up a GDB symbol for it. For blocks, procedures and types we open a new lexical context. This is basically just a big switch on the symbol's type. Argument AX is the base pointer of aux symbols for this file (fh->iauxBase). @@ -591,7 +595,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, case stNil: break; - case stGlobal: /* external symbol, goes into global block */ + case stGlobal: /* External symbol, goes into global block. */ class = LOC_STATIC; b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), GLOBAL_BLOCK); @@ -599,7 +603,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; goto data; - case stStatic: /* static data, goes into current block. */ + case stStatic: /* Static data, goes into current block. */ class = LOC_STATIC; b = top_stack->cur_block; s = new_symbol (name); @@ -616,7 +620,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; goto data; - case stLocal: /* local variable, goes into current block */ + case stLocal: /* Local variable, goes into current block. */ b = top_stack->cur_block; s = new_symbol (name); SYMBOL_VALUE (s) = svalue; @@ -628,7 +632,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, else class = LOC_LOCAL; - data: /* Common code for symbols describing data */ + data: /* Common code for symbols describing data. */ SYMBOL_DOMAIN (s) = VAR_DOMAIN; SYMBOL_CLASS (s) = class; add_symbol (s, top_stack->cur_st, b); @@ -639,17 +643,18 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, SYMBOL_TYPE (s) = objfile_type (objfile)->nodebug_data_symbol; else SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name); - /* Value of a data symbol is its memory address */ + /* Value of a data symbol is its memory address. */ break; - case stParam: /* arg to procedure, goes into current block */ + case stParam: /* Arg to procedure, goes into current + block. */ max_gdbinfo++; found_ecoff_debugging_info = 1; top_stack->numargs++; /* Special GNU C++ name. */ if (is_cplus_marker (name[0]) && name[1] == 't' && name[2] == 0) - name = "this"; /* FIXME, not alloc'd in obstack */ + name = "this"; /* FIXME, not alloc'd in obstack. */ s = new_symbol (name); SYMBOL_DOMAIN (s) = VAR_DOMAIN; @@ -680,17 +685,17 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, add_symbol (s, top_stack->cur_st, top_stack->cur_block); break; - case stLabel: /* label, goes into current block */ + case stLabel: /* label, goes into current block. */ s = new_symbol (name); - SYMBOL_DOMAIN (s) = VAR_DOMAIN; /* so that it can be used */ - SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused */ + SYMBOL_DOMAIN (s) = VAR_DOMAIN; /* So that it can be used */ + SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused. */ SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; SYMBOL_TYPE (s) = objfile_type (objfile)->builtin_int; add_symbol (s, top_stack->cur_st, top_stack->cur_block); break; - case stProc: /* Procedure, usually goes into global block */ - case stStaticProc: /* Static procedure, goes into current block */ + case stProc: /* Procedure, usually goes into global block. */ + case stStaticProc: /* Static procedure, goes into current block. */ /* For stProc symbol records, we need to check the storage class as well, as only (stProc, scText) entries represent "real" procedures - See the Compaq document titled "Object File / @@ -726,7 +731,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, s = new_symbol (name); SYMBOL_DOMAIN (s) = VAR_DOMAIN; SYMBOL_CLASS (s) = LOC_BLOCK; - /* Type of the return value */ + /* Type of the return value. */ if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil) t = objfile_type (objfile)->builtin_int; else @@ -743,8 +748,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, printf("howdy\n")" would fail with the error message "program has no memory available". To avoid this, we patch up the type and make it void* - instead. (davidm@azstarnet.com) - */ + instead. (davidm@azstarnet.com). */ t = make_pointer_type (t, NULL); } } @@ -766,7 +770,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, } add_symbol (s, top_stack->cur_st, b); - /* Make a type for the procedure itself */ + /* Make a type for the procedure itself. */ SYMBOL_TYPE (s) = lookup_function_type (t); /* All functions in C++ have prototypes. For C we don't have enough @@ -774,7 +778,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, if (SYMBOL_LANGUAGE (s) == language_cplus) TYPE_PROTOTYPED (SYMBOL_TYPE (s)) = 1; - /* Create and enter a new lexical context */ + /* Create and enter a new lexical context. */ b = new_block (FUNCTION_BLOCK); SYMBOL_BLOCK_VALUE (s) = b; BLOCK_FUNCTION (b) = s; @@ -782,7 +786,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, BLOCK_SUPERBLOCK (b) = top_stack->cur_block; add_block (b, top_stack->cur_st); - /* Not if we only have partial info */ + /* Not if we only have partial info. */ if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil) break; @@ -804,19 +808,19 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, long max_value; struct field *f; - case stStruct: /* Start a block defining a struct type */ + case stStruct: /* Start a block defining a struct type. */ type_code = TYPE_CODE_STRUCT; goto structured_common; - case stUnion: /* Start a block defining a union type */ + case stUnion: /* Start a block defining a union type. */ type_code = TYPE_CODE_UNION; goto structured_common; - case stEnum: /* Start a block defining an enum type */ + case stEnum: /* Start a block defining an enum type. */ type_code = TYPE_CODE_ENUM; goto structured_common; - case stBlock: /* Either a lexical block, or some type */ + case stBlock: /* Either a lexical block, or some type. */ if (sh->sc != scInfo && !SC_IS_COMMON (sh->sc)) goto case_stBlock_code; /* Lexical block */ @@ -830,7 +834,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, push_parse_stack (); top_stack->blocktype = stBlock; - /* First count the number of fields and the highest value. */ + /* First count the number of fields and the highest value. */ nfields = 0; max_value = 0; for (ext_tsym = ext_sh + external_sym_size; @@ -845,7 +849,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, { case stEnd: /* C++ encodes class types as structures where there the - methods are encoded as stProc. The scope of stProc + methods are encoded as stProc. The scope of stProc symbols also ends with stEnd, thus creating a risk of taking the wrong stEnd symbol record as the end of the current struct, which would cause GDB to undercount @@ -923,23 +927,24 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, /* mips cc puts out a typedef for struct x if it is not yet defined when it encounters struct y { struct x *xp; }; - Just ignore it. */ + Just ignore it. */ break; case stIndirect: /* Irix5 cc puts out a stIndirect for struct x if it is not yet defined when it encounters struct y { struct x *xp; }; - Just ignore it. */ + Just ignore it. */ break; default: complaint (&symfile_complaints, - _("declaration block contains unhandled symbol type %d"), + _("declaration block contains " + "unhandled symbol type %d"), tsym.st); } } - end_of_fields:; + end_of_fields: /* In an stBlock, there is no way to distinguish structs, unions, and enums at this point. This is a bug in the @@ -972,7 +977,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, differently from struct/union fields, and that is harder to patch up, but luckily we shouldn't need to. (If there are any enumeration members, we can tell for sure it's an enum - here.) */ + here.) */ if (type_code == TYPE_CODE_UNDEF) { @@ -998,8 +1003,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, if (sh->iss == 0 || name[0] == '.' || name[0] == '\0') TYPE_TAG_NAME (t) = NULL; else - TYPE_TAG_NAME (t) = obconcat (¤t_objfile->objfile_obstack, name, - (char *) NULL); + TYPE_TAG_NAME (t) = obconcat (¤t_objfile->objfile_obstack, + name, (char *) NULL); TYPE_CODE (t) = type_code; TYPE_LENGTH (t) = sh->value; @@ -1012,7 +1017,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, { int unsigned_enum = 1; - /* This is a non-empty enum. */ + /* This is a non-empty enum. */ /* DEC c89 has the number of enumerators in the sh.value field, not the type length, so we have to compensate for that @@ -1057,14 +1062,14 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, unsigned_enum = 0; add_symbol (enum_sym, top_stack->cur_st, top_stack->cur_block); - /* Skip the stMembers that we've handled. */ + /* Skip the stMembers that we've handled. */ count++; f++; } if (unsigned_enum) TYPE_UNSIGNED (t) = 1; } - /* make this the current type */ + /* Make this the current type. */ top_stack->cur_type = t; top_stack->cur_field = 0; @@ -1094,8 +1099,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, case_stBlock_code: found_ecoff_debugging_info = 1; - /* beginnning of (code) block. Value of symbol - is the displacement from procedure start */ + /* Beginnning of (code) block. Value of symbol + is the displacement from procedure start. */ push_parse_stack (); /* Do not start a new block if this is the outermost block of a @@ -1135,7 +1140,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, BLOCK_END (top_stack->cur_block) += sh->value; /* size */ - /* Make up special symbol to contain procedure specific info */ + /* Make up special symbol to contain procedure specific info. */ s = new_symbol (MDEBUG_EFI_SYMBOL_NAME); SYMBOL_DOMAIN (s) = LABEL_DOMAIN; SYMBOL_CLASS (s) = LOC_CONST; @@ -1167,7 +1172,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, if (TYPE_NFIELDS (ftype) <= 0) { /* No parameter type information is recorded with the function's - type. Set that from the type of the parameter symbols. */ + type. Set that from the type of the parameter symbols. */ int nparams = top_stack->numargs; int iparams; struct symbol *sym; @@ -1198,9 +1203,9 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, } else if (sh->sc == scText && top_stack->blocktype == stBlock) { - /* End of (code) block. The value of the symbol is the + /* End of (code) block. The value of the symbol is the displacement from the procedure`s start address of the - end of this block. */ + end of this block. */ BLOCK_END (top_stack->cur_block) = sh->value + top_stack->procadr; } else if (sh->sc == scText && top_stack->blocktype == stNil) @@ -1219,7 +1224,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, complaint (&symfile_complaints, _("stEnd with storage class %d not handled"), sh->sc); - pop_parse_stack (); /* restore previous lexical context */ + pop_parse_stack (); /* Restore previous lexical context. */ break; case stMember: /* member of struct or union */ @@ -1227,7 +1232,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, FIELD_NAME (*f) = name; SET_FIELD_BITPOS (*f, sh->value); bitsize = 0; - FIELD_TYPE (*f) = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name); + FIELD_TYPE (*f) = parse_type (cur_fd, ax, sh->index, + &bitsize, bigend, name); FIELD_BITSIZE (*f) = bitsize; break; @@ -1254,8 +1260,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, else t = pend->t; - /* mips cc puts out a typedef with the name of the struct for forward - declarations. These should not go into the symbol table and + /* Mips cc puts out a typedef with the name of the struct for forward + declarations. These should not go into the symbol table and TYPE_NAME should not be set for them. They can't be distinguished from an intentional typedef to the same name however: @@ -1509,7 +1515,7 @@ basic_type (int bt, struct objfile *objfile) } /* Parse the type information provided in the raw AX entries for - the symbol SH. Return the bitfield size in BS, in case. + the symbol SH. Return the bitfield size in BS, in case. We must byte-swap the AX entries before we use them; BIGEND says whether they are big-endian or little-endian (from fh->fBigendian). */ @@ -1521,7 +1527,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, struct type *tp = 0; enum type_code type_code = TYPE_CODE_UNDEF; - /* Handle undefined types, they have indexNil. */ + /* Handle undefined types, they have indexNil. */ if (aux_index == indexNil) return basic_type (btInt, current_objfile); @@ -1538,7 +1544,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, tp = basic_type (t->bt, current_objfile); if (tp == NULL) { - /* Cannot use builtin types -- build our own */ + /* Cannot use builtin types -- build our own. */ switch (t->bt) { case btStruct: @@ -1557,12 +1563,12 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, type_code = TYPE_CODE_SET; break; case btIndirect: - /* alpha cc -migrate uses this for typedefs. The true type will + /* alpha cc -migrate uses this for typedefs. The true type will be obtained by crossreferencing below. */ type_code = TYPE_CODE_ERROR; break; case btTypedef: - /* alpha cc uses this for typedefs. The true type will be + /* alpha cc uses this for typedefs. The true type will be obtained by crossreferencing below. */ type_code = TYPE_CODE_ERROR; break; @@ -1572,7 +1578,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, } } - /* Move on to next aux */ + /* Move on to next aux. */ ax++; if (t->fBitfield) @@ -1592,7 +1598,8 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, else if (t->bt == btEnum) ; else - complaint (&symfile_complaints, _("can't handle TIR fBitfield for %s"), + complaint (&symfile_complaints, + _("can't handle TIR fBitfield for %s"), sym_name); } else @@ -1633,7 +1640,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, /* All these types really point to some (common) MIPS type definition, and only the type-qualifiers fully identify - them. We'll make the same effort at sharing. */ + them. We'll make the same effort at sharing. */ if (t->bt == btStruct || t->bt == btUnion || t->bt == btEnum || @@ -1689,8 +1696,9 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, TYPE_TAG_NAME (tp) = NULL; else if (TYPE_TAG_NAME (tp) == NULL || strcmp (TYPE_TAG_NAME (tp), name) != 0) - TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name), - ¤t_objfile->objfile_obstack); + TYPE_TAG_NAME (tp) + = obsavestring (name, strlen (name), + ¤t_objfile->objfile_obstack); } } @@ -1717,7 +1725,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, else { /* Usually, TYPE_CODE(tp) is already type_code. The main - exception is if we guessed wrong re struct/union/enum. */ + exception is if we guessed wrong re struct/union/enum. */ if (TYPE_CODE (tp) != type_code) { bad_tag_guess_complaint (sym_name); @@ -1743,7 +1751,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, } } - /* Deal with range types */ + /* Deal with range types. */ if (t->bt == btRange) { TYPE_NFIELDS (tp) = 0; @@ -1755,8 +1763,8 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, ax++; } - /* Parse all the type qualifiers now. If there are more - than 6 the game will continue in the next aux */ + /* Parse all the type qualifiers now. If there are more + than 6 the game will continue in the next aux. */ while (1) { @@ -1784,17 +1792,18 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, /* Complain for illegal continuations due to corrupt aux entries. */ if (t->continued) - complaint (&symfile_complaints, _("illegal TIR continued for %s"), sym_name); + complaint (&symfile_complaints, + _("illegal TIR continued for %s"), sym_name); return tp; } /* Make up a complex type from a basic one. Type is passed by - reference in TPP and side-effected as necessary. The type + reference in TPP and side-effected as necessary. The type qualifier TQ says how to handle the aux symbols at AX for the symbol SX we are currently analyzing. BIGEND says whether aux symbols are big-endian or little-endian. - Returns the number of aux symbols we parsed. */ + Returns the number of aux symbols we parsed. */ static int upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, @@ -1803,7 +1812,7 @@ upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, int off; struct type *t; - /* Used in array processing */ + /* Used in array processing. */ int rf, id; FDR *fh; struct type *range; @@ -1826,7 +1835,7 @@ upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, case tqArray: off = 0; - /* Determine and record the domain type (type of index) */ + /* Determine and record the domain type (type of index). */ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, &rndx); id = rndx.index; rf = rndx.rfd; @@ -1847,7 +1856,8 @@ upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, if (TYPE_CODE (indx) != TYPE_CODE_INT) { complaint (&symfile_complaints, - _("illegal array index type for %s, assuming int"), sym_name); + _("illegal array index type for %s, assuming int"), + sym_name); indx = objfile_type (current_objfile)->builtin_int; } @@ -1921,12 +1931,12 @@ parse_procedure (PDR *pr, struct symtab *search_symtab, struct block *b; char *sh_name; - /* Simple rule to find files linked "-x" */ + /* Simple rule to find files linked "-x". */ if (cur_fdr->rss == -1) { if (pr->isym == -1) { - /* Static procedure at address pr->adr. Sigh. */ + /* Static procedure at address pr->adr. Sigh. */ /* FIXME-32x64. assuming pr->adr fits in long. */ complaint (&symfile_complaints, _("can't handle PDR for static proc at 0x%lx"), @@ -1999,11 +2009,11 @@ parse_procedure (PDR *pr, struct symtab *search_symtab, s = new_symbol (sh_name); SYMBOL_DOMAIN (s) = VAR_DOMAIN; SYMBOL_CLASS (s) = LOC_BLOCK; - /* Donno its type, hope int is ok */ + /* Donno its type, hope int is ok. */ SYMBOL_TYPE (s) = lookup_function_type (objfile_type (pst->objfile)->builtin_int); add_symbol (s, top_stack->cur_st, top_stack->cur_block); - /* Wont have symbols for this one */ + /* Won't have symbols for this one. */ b = new_block (2); SYMBOL_BLOCK_VALUE (s) = b; BLOCK_FUNCTION (b) = s; @@ -2059,11 +2069,11 @@ parse_procedure (PDR *pr, struct symtab *search_symtab, SYMBOL_TYPE (s) = objfile_type (pst->objfile)->nodebug_text_symbol; } -/* Parse the external symbol ES. Just call parse_symbol() after +/* Parse the external symbol ES. Just call parse_symbol() after making sure we know where the aux are for it. BIGEND says whether aux entries are big-endian or little-endian. - This routine clobbers top_stack->cur_block and ->cur_st. */ + This routine clobbers top_stack->cur_block and ->cur_st. */ static void parse_external (EXTR *, int, struct section_offsets *, struct objfile *); @@ -2114,7 +2124,7 @@ parse_external (EXTR *es, int bigend, struct section_offsets *section_offsets, break; } n_undef_symbols++; - /* FIXME: Turn this into a complaint? */ + /* FIXME: Turn this into a complaint? */ if (info_verbose) printf_filtered (_("Warning: %s `%s' is undefined (in %s)\n"), what, debug_info->ssext + es->asym.iss, @@ -2145,7 +2155,8 @@ parse_external (EXTR *es, int bigend, struct section_offsets *section_offsets, /* Note that the case of a symbol with indexNil must be handled anyways by parse_symbol(). */ - parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets, objfile); + parse_symbol (&es->asym, ax, (char *) NULL, + bigend, section_offsets, objfile); break; default: break; @@ -2156,7 +2167,7 @@ parse_external (EXTR *es, int bigend, struct section_offsets *section_offsets, GDB's linetable LT. MIPS' encoding requires a little bit of magic to get things out. Note also that MIPS' line numbers can go back and forth, apparently we can live - with that and do not need to reorder our linetables */ + with that and do not need to reorder our linetables. */ static void parse_lines (FDR *, PDR *, struct linetable *, int, struct partial_symtab *, CORE_ADDR); @@ -2172,7 +2183,7 @@ parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines, if (fh->cbLine == 0) return; - /* Scan by procedure descriptors */ + /* Scan by procedure descriptors. */ k = 0; for (j = 0; j < fh->cpd; j++, pr++) { @@ -2180,7 +2191,7 @@ parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines, CORE_ADDR adr; unsigned char *halt; - /* No code for this one */ + /* No code for this one. */ if (pr->iline == ilineNil || pr->lnLow == -1 || pr->lnHigh == -1) continue; @@ -2212,7 +2223,7 @@ parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines, } lineno += delta; /* first delta is 0 */ - /* Complain if the line table overflows. Could happen + /* Complain if the line table overflows. Could happen with corrupt binaries. */ if (lt->nitems >= maxlines) { @@ -2231,7 +2242,8 @@ static void function_outside_compilation_unit_complaint (const char *arg1) { complaint (&symfile_complaints, - _("function `%s' appears to be defined outside of all compilation units"), + _("function `%s' appears to be defined " + "outside of all compilation units"), arg1); } @@ -2341,13 +2353,13 @@ parse_partial_symbols (struct objfile *objfile) int textlow_not_set = 1; int past_first_source_file = 0; - /* List of current psymtab's include files */ + /* List of current psymtab's include files. */ char **psymtab_include_list; int includes_allocated; int includes_used; EXTR *extern_tab; struct pst_map *fdr_to_pst; - /* Index within current psymtab dependency list */ + /* Index within current psymtab dependency list. */ struct partial_symtab **dependency_list; int dependencies_used, dependencies_allocated; struct cleanup *old_chain; @@ -2390,7 +2402,7 @@ parse_partial_symbols (struct objfile *objfile) * Only parse the Local and External symbols, and the Relative FDR. * Fixup enough of the loader symtab to be able to use it. * Allocate space only for the file's portions we need to - * look at. (XXX) + * look at. (XXX) */ max_gdbinfo = 0; @@ -2398,8 +2410,9 @@ parse_partial_symbols (struct objfile *objfile) /* Allocate the map FDR -> PST. Minor hack: -O3 images might claim some global data belongs - to FDR -1. We`ll go along with that */ - fdr_to_pst = (struct pst_map *) xzalloc ((hdr->ifdMax + 1) * sizeof *fdr_to_pst); + to FDR -1. We`ll go along with that. */ + fdr_to_pst = (struct pst_map *) + xzalloc ((hdr->ifdMax + 1) * sizeof *fdr_to_pst); old_chain = make_cleanup (xfree, fdr_to_pst); fdr_to_pst++; { @@ -2427,7 +2440,7 @@ parse_partial_symbols (struct objfile *objfile) for (; ext_out < ext_out_end; ext_out += external_ext_size, ext_in++) (*swap_ext_in) (cur_bfd, ext_out, ext_in); - /* Pass 1 over external syms: Presize and partition the list */ + /* Pass 1 over external syms: Presize and partition the list. */ ext_in = ext_block; ext_in_end = ext_in + hdr->iextMax; for (; ext_in < ext_in_end; ext_in++) @@ -2440,7 +2453,7 @@ parse_partial_symbols (struct objfile *objfile) fdr_to_pst[ext_in->ifd].n_globals++; } - /* Pass 1.5 over files: partition out global symbol space */ + /* Pass 1.5 over files: partition out global symbol space. */ s_idx = 0; for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) { @@ -2461,7 +2474,7 @@ parse_partial_symbols (struct objfile *objfile) Since absolute sections don't get relocated, we end up calculating an address different from that of the symbol's minimal symbol (created earlier from the - Elf symtab). + Elf symtab). To fix this, either : 1) don't create the duplicate symbol @@ -2478,9 +2491,9 @@ parse_partial_symbols (struct objfile *objfile) I've implemented #1 here... Skip the creation of the minimal symbols based on the ECOFF - symbol table. */ + symbol table. */ - /* Pass 2 over external syms: fill in external symbols */ + /* Pass 2 over external syms: fill in external symbols. */ ext_in = ext_block; ext_in_end = ext_in + hdr->iextMax; for (; ext_in < ext_in_end; ext_in++) @@ -2493,8 +2506,8 @@ parse_partial_symbols (struct objfile *objfile) if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax) { complaint (&symfile_complaints, - _("bad ifd for external symbol: %d (max %ld)"), ext_in->ifd, - hdr->ifdMax); + _("bad ifd for external symbol: %d (max %ld)"), + ext_in->ifd, hdr->ifdMax); continue; } if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax) @@ -2513,20 +2526,22 @@ parse_partial_symbols (struct objfile *objfile) continue; - /* Pass 3 over files, over local syms: fill in static symbols */ + /* Pass 3 over files, over local syms: fill in static symbols. */ name = debug_info->ssext + ext_in->asym.iss; - /* Process ECOFF Symbol Types and Storage Classes */ + /* Process ECOFF Symbol Types and Storage Classes. */ switch (ext_in->asym.st) { case stProc: /* Beginnning of Procedure */ - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); break; case stStaticProc: /* Load time only static procs */ ms_type = mst_file_text; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); break; case stGlobal: /* External symbol */ @@ -2539,12 +2554,14 @@ parse_partial_symbols (struct objfile *objfile) else if (SC_IS_DATA (ext_in->asym.sc)) { ms_type = mst_data; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); } else if (SC_IS_BSS (ext_in->asym.sc)) { ms_type = mst_bss; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); } else if (SC_IS_SBSS (ext_in->asym.sc)) { @@ -2559,24 +2576,23 @@ parse_partial_symbols (struct objfile *objfile) /* Label */ /* On certain platforms, some extra label symbols can be - generated by the linker. One possible usage for this kind + generated by the linker. One possible usage for this kind of symbols is to represent the address of the begining of a - given section. For instance, on Tru64 5.1, the address of + given section. For instance, on Tru64 5.1, the address of the _ftext label is the start address of the .text section. The storage class of these symbols is usually directly - related to the section to which the symbol refers. For + related to the section to which the symbol refers. For instance, on Tru64 5.1, the storage class for the _fdata label is scData, refering to the .data section. It is actually possible that the section associated to the - storage class of the label does not exist. On True64 5.1 + storage class of the label does not exist. On True64 5.1 for instance, the libm.so shared library does not contain any .data section, although it contains a _fpdata label - which storage class is scData... Since these symbols are + which storage class is scData... Since these symbols are usually useless for the debugger user anyway, we just - discard these symbols. - */ + discard these symbols. */ if (SC_IS_TEXT (ext_in->asym.sc)) { @@ -2584,7 +2600,8 @@ parse_partial_symbols (struct objfile *objfile) continue; ms_type = mst_file_text; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); } else if (SC_IS_DATA (ext_in->asym.sc)) { @@ -2592,7 +2609,8 @@ parse_partial_symbols (struct objfile *objfile) continue; ms_type = mst_file_data; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); } else if (SC_IS_BSS (ext_in->asym.sc)) { @@ -2600,7 +2618,8 @@ parse_partial_symbols (struct objfile *objfile) continue; ms_type = mst_file_bss; - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); } else if (SC_IS_SBSS (ext_in->asym.sc)) { @@ -2618,10 +2637,10 @@ parse_partial_symbols (struct objfile *objfile) case stLocal: case stNil: /* The alpha has the section start addresses in stLocal symbols - whose name starts with a `.'. Skip those but complain for all + whose name starts with a `.'. Skip those but complain for all other stLocal symbols. Irix6 puts the section start addresses in stNil symbols, skip - those too. */ + those too. */ if (name[0] == '.') continue; /* Fall through. */ @@ -2634,7 +2653,7 @@ parse_partial_symbols (struct objfile *objfile) objfile); } - /* Pass 3 over files, over local syms: fill in static symbols */ + /* Pass 3 over files, over local syms: fill in static symbols. */ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) { struct partial_symtab *save_pst; @@ -2655,7 +2674,8 @@ parse_partial_symbols (struct objfile *objfile) { textlow = fh->adr; if (relocatable || textlow != 0) - textlow += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + textlow += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); } else textlow = 0; @@ -2675,7 +2695,7 @@ parse_partial_symbols (struct objfile *objfile) DEBUG_INFO (pst) = debug_info; PENDING_LIST (pst) = pending_list; - /* The way to turn this into a symtab is to call... */ + /* The way to turn this into a symtab is to call... */ pst->read_symtab = mdebug_psymtab_to_symtab; /* Set up language for the pst. @@ -2687,7 +2707,7 @@ parse_partial_symbols (struct objfile *objfile) a header file, which is not what we want. But the FDRs for the header files are after the FDR for the source file, so we can assign the language of the source file to the - following header files. Then we save the language in the private + following header files. Then we save the language in the private pst data so that we can reuse it when building symtabs. */ prev_language = psymtab_language; @@ -2711,7 +2731,7 @@ parse_partial_symbols (struct objfile *objfile) current object file uses encapsulated stabs instead of mips ecoff for local symbols. (It is the second symbol because the first symbol is the stFile used to signal the start of a - file). */ + file). */ processing_gcc_compilation = 0; if (fh->csym >= 2) { @@ -2743,7 +2763,8 @@ parse_partial_symbols (struct objfile *objfile) CORE_ADDR procaddr; long isym; - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); if (sh.st == stStaticProc) { namestring = debug_info->ss + fh->issBase + sh.iss; @@ -2790,7 +2811,8 @@ parse_partial_symbols (struct objfile *objfile) case scPData: case scXData: namestring = debug_info->ss + fh->issBase + sh.iss; - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); record_minimal_symbol (namestring, sh.value, mst_file_data, sh.sc, objfile); @@ -2798,9 +2820,10 @@ parse_partial_symbols (struct objfile *objfile) default: /* FIXME! Shouldn't this use cases for bss, - then have the default be abs? */ + then have the default be abs? */ namestring = debug_info->ss + fh->issBase + sh.iss; - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); record_minimal_symbol (namestring, sh.value, mst_file_bss, sh.sc, objfile); @@ -2809,7 +2832,7 @@ parse_partial_symbols (struct objfile *objfile) } continue; } - /* Handle stabs continuation */ + /* Handle stabs continuation. */ { char *stabstring = debug_info->ss + fh->issBase + sh.iss; int len = strlen (stabstring); @@ -2821,10 +2844,10 @@ parse_partial_symbols (struct objfile *objfile) char *stabstring2; int len2; - /* Ignore continuation char from 1st string */ + /* Ignore continuation char from 1st string. */ len--; - /* Read next stabstring */ + /* Read next stabstring. */ cur_sdx++; (*swap_sym_in) (cur_bfd, (((char *) debug_info->external_sym) @@ -2834,7 +2857,7 @@ parse_partial_symbols (struct objfile *objfile) stabstring2 = debug_info->ss + fh->issBase + sh2.iss; len2 = strlen (stabstring2); - /* Concatinate stabstring2 with stabstring1 */ + /* Concatinate stabstring2 with stabstring1. */ if (stabstring && stabstring != debug_info->ss + fh->issBase + sh.iss) stabstring = xrealloc (stabstring, len + len2 + 1); @@ -2851,39 +2874,41 @@ parse_partial_symbols (struct objfile *objfile) { char *p; - /* - * Standard, external, non-debugger, symbols - */ + /* Standard, external, non-debugger, symbols. */ case N_TEXT | N_EXT: case N_NBTEXT | N_EXT: - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); goto record_it; case N_DATA | N_EXT: case N_NBDATA | N_EXT: - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); goto record_it; case N_BSS: case N_BSS | N_EXT: case N_NBBSS | N_EXT: - case N_SETV | N_EXT: /* FIXME, is this in BSS? */ - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + case N_SETV | N_EXT: /* FIXME, is this in BSS? */ + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); goto record_it; case N_ABS | N_EXT: record_it: - continue; + continue; - /* Standard, local, non-debugger, symbols */ + /* Standard, local, non-debugger, symbols. */ case N_NBTEXT: - /* We need to be able to deal with both N_FN or N_TEXT, - because we have no way of knowing whether the sys-supplied ld - or GNU ld was used to make the executable. Sequents throw - in another wrinkle -- they renumbered N_FN. */ + /* We need to be able to deal with both N_FN or + N_TEXT, because we have no way of knowing + whether the sys-supplied ld or GNU ld was used + to make the executable. Sequents throw in + another wrinkle -- they renumbered N_FN. */ case N_FN: case N_FN_SEQ: @@ -2891,11 +2916,12 @@ parse_partial_symbols (struct objfile *objfile) continue; case N_DATA: - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); goto record_it; case N_UNDF | N_EXT: - continue; /* Just undefined, not COMMON */ + continue; /* Just undefined, not COMMON. */ case N_UNDF: continue; @@ -2907,7 +2933,7 @@ parse_partial_symbols (struct objfile *objfile) case N_NBBSS: continue; - /* Keep going . . . */ + /* Keep going . . . */ /* * Special symbol types for GNU @@ -2934,16 +2960,17 @@ parse_partial_symbols (struct objfile *objfile) CORE_ADDR valu; static int prev_so_symnum = -10; static int first_so_symnum; - char *p; + const char *p; int prev_textlow_not_set; - valu = sh.value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + valu = sh.value + ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); prev_textlow_not_set = textlow_not_set; - /* A zero value is probably an indication for the SunPRO 3.0 - compiler. end_psymtab explicitly tests for zero, so - don't relocate it. */ + /* A zero value is probably an indication for the + SunPRO 3.0 compiler. end_psymtab explicitly tests + for zero, so don't relocate it. */ if (sh.value == 0 && gdbarch_sofun_address_maybe_missing (gdbarch)) @@ -2957,7 +2984,7 @@ parse_partial_symbols (struct objfile *objfile) past_first_source_file = 1; if (prev_so_symnum != symnum - 1) - { /* Here if prev stab wasn't N_SO */ + { /* Here if prev stab wasn't N_SO. */ first_so_symnum = symnum; if (pst) @@ -2970,27 +2997,31 @@ parse_partial_symbols (struct objfile *objfile) prev_so_symnum = symnum; - /* End the current partial symtab and start a new one */ + /* End the current partial symtab and start a + new one. */ /* SET_NAMESTRING ();*/ namestring = stabstring; - /* Null name means end of .o file. Don't start a new one. */ + /* Null name means end of .o file. Don't start a new + one. */ if (*namestring == '\000') continue; - /* Some compilers (including gcc) emit a pair of initial N_SOs. - The first one is a directory name; the second the file name. - If pst exists, is empty, and has a filename ending in '/', - we assume the previous N_SO was a directory name. */ - - p = strrchr (namestring, '/'); - if (p && *(p + 1) == '\000') - continue; /* Simply ignore directory name SOs */ - - /* Some other compilers (C++ ones in particular) emit useless - SOs for non-existant .c files. We ignore all subsequent SOs that - immediately follow the first. */ + /* Some compilers (including gcc) emit a pair of + initial N_SOs. The first one is a directory name; + the second the file name. If pst exists, is + empty, and has a filename ending in '/', we assume + the previous N_SO was a directory name. */ + p = lbasename (namestring); + if (p != namestring && *p == '\000') + continue; /* Simply ignore directory + name SOs. */ + + /* Some other compilers (C++ ones in particular) emit + useless SOs for non-existant .c files. We ignore + all subsequent SOs that immediately follow the + first. */ if (!pst) pst = save_pst; @@ -3004,41 +3035,45 @@ parse_partial_symbols (struct objfile *objfile) { enum language tmp_language; - /* Mark down an include file in the current psymtab */ + /* Mark down an include file in the current psymtab. */ - /* SET_NAMESTRING ();*/ + /* SET_NAMESTRING (); */ namestring = stabstring; - tmp_language = deduce_language_from_filename (namestring); + tmp_language + = deduce_language_from_filename (namestring); - /* Only change the psymtab's language if we've learned - something useful (eg. tmp_language is not language_unknown). - In addition, to match what start_subfile does, never change - from C++ to C. */ + /* Only change the psymtab's language if we've + learned something useful (eg. tmp_language is not + language_unknown). In addition, to match what + start_subfile does, never change from C++ to + C. */ if (tmp_language != language_unknown && (tmp_language != language_c || psymtab_language != language_cplus)) psymtab_language = tmp_language; - /* In C++, one may expect the same filename to come round many - times, when code is coming alternately from the main file - and from inline functions in other files. So I check to see - if this is a file we've seen before -- either the main - source file, or a previously included file. - - This seems to be a lot of time to be spending on N_SOL, but - things like "break c-exp.y:435" need to work (I - suppose the psymtab_include_list could be hashed or put - in a binary tree, if profiling shows this is a major hog). */ - if (pst && strcmp (namestring, pst->filename) == 0) + /* In C++, one may expect the same filename to come + round many times, when code is coming alternately + from the main file and from inline functions in + other files. So I check to see if this is a file + we've seen before -- either the main source file, + or a previously included file. + + This seems to be a lot of time to be spending on + N_SOL, but things like "break c-exp.y:435" need to + work (I suppose the psymtab_include_list could be + hashed or put in a binary tree, if profiling shows + this is a major hog). */ + if (pst && filename_cmp (namestring, pst->filename) == 0) continue; { int i; for (i = 0; i < includes_used; i++) - if (strcmp (namestring, - psymtab_include_list[i]) == 0) + if (filename_cmp (namestring, + psymtab_include_list[i]) == 0) { i = -1; break; @@ -3060,43 +3095,46 @@ parse_partial_symbols (struct objfile *objfile) } continue; } - case N_LSYM: /* Typedef or automatic variable. */ - case N_STSYM: /* Data seg var -- static */ - case N_LCSYM: /* BSS " */ - case N_ROSYM: /* Read-only data seg var -- static. */ - case N_NBSTS: /* Gould nobase. */ - case N_NBLCS: /* symbols. */ + case N_LSYM: /* Typedef or automatic variable. */ + case N_STSYM: /* Data seg var -- static */ + case N_LCSYM: /* BSS " */ + case N_ROSYM: /* Read-only data seg var -- static. */ + case N_NBSTS: /* Gould nobase. */ + case N_NBLCS: /* symbols. */ case N_FUN: - case N_GSYM: /* Global (extern) variable; can be - data or bss (sigh FIXME). */ + case N_GSYM: /* Global (extern) variable; can be + data or bss (sigh FIXME). */ /* Following may probably be ignored; I'll leave them here for now (until I do Pascal and Modula 2 extensions). */ - case N_PC: /* I may or may not need this; I - suspect not. */ - case N_M2C: /* I suspect that I can ignore this here. */ - case N_SCOPE: /* Same. */ + case N_PC: /* I may or may not need this; I + suspect not. */ + case N_M2C: /* I suspect that I can ignore this + here. */ + case N_SCOPE: /* Same. */ - /* SET_NAMESTRING ();*/ + /* SET_NAMESTRING (); */ namestring = stabstring; p = (char *) strchr (namestring, ':'); if (!p) - continue; /* Not a debugging symbol. */ + continue; /* Not a debugging symbol. */ /* Main processing section for debugging symbols which - the initial read through the symbol tables needs to worry - about. If we reach this point, the symbol which we are - considering is definitely one we are interested in. - p must also contain the (valid) index into the namestring - which indicates the debugging type symbol. */ + the initial read through the symbol tables needs to + worry about. If we reach this point, the symbol + which we are considering is definitely one we are + interested in. p must also contain the (valid) + index into the namestring which indicates the + debugging type symbol. */ switch (p[1]) { case 'S': - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); if (gdbarch_static_transform_name_p (gdbarch)) namestring = gdbarch_static_transform_name @@ -3109,9 +3147,11 @@ parse_partial_symbols (struct objfile *objfile) psymtab_language, objfile); continue; case 'G': - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); - /* The addresses in these entries are reported to be - wrong. See the code that reads 'G's for symtabs. */ + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); + /* The addresses in these entries are reported + to be wrong. See the code that reads 'G's + for symtabs. */ add_psymbol_to_list (namestring, p - namestring, 1, VAR_DOMAIN, LOC_STATIC, &objfile->global_psymbols, @@ -3138,18 +3178,20 @@ parse_partial_symbols (struct objfile *objfile) if (p[2] == 't') { /* Also a typedef with the same name. */ - add_psymbol_to_list (namestring, p - namestring, - 1, + add_psymbol_to_list (namestring, + p - namestring, 1, VAR_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, sh.value, 0, - psymtab_language, objfile); + psymtab_language, + objfile); p += 1; } } goto check_enum; case 't': - if (p != namestring) /* a name is there, not just :T... */ + if (p != namestring) /* a name is there, not + just :T... */ { add_psymbol_to_list (namestring, p - namestring, 1, VAR_DOMAIN, LOC_TYPEDEF, @@ -3158,14 +3200,15 @@ parse_partial_symbols (struct objfile *objfile) psymtab_language, objfile); } check_enum: - /* If this is an enumerated type, we need to - add all the enum constants to the partial symbol - table. This does not cover enums without names, e.g. - "enum {a, b} c;" in C, but fortunately those are - rare. There is no way for GDB to find those from the - enum type without spending too much time on it. Thus - to solve this problem, the compiler needs to put out the - enum in a nameless type. GCC2 does this. */ + /* If this is an enumerated type, we need to add + all the enum constants to the partial symbol + table. This does not cover enums without names, + e.g. "enum {a, b} c;" in C, but fortunately + those are rare. There is no way for GDB to find + those from the enum type without spending too + much time on it. Thus to solve this problem, + the compiler needs to put out the enum in a + nameless type. GCC2 does this. */ /* We are looking for something of the form ":" ("t" | "T") [ "="] "e" @@ -3173,8 +3216,8 @@ parse_partial_symbols (struct objfile *objfile) /* Skip over the colon and the 't' or 'T'. */ p += 2; - /* This type may be given a number. Also, numbers can come - in pairs like (0,26). Skip over it. */ + /* This type may be given a number. Also, numbers + can come in pairs like (0,26). Skip over it. */ while ((*p >= '0' && *p <= '9') || *p == '(' || *p == ',' || *p == ')' || *p == '=') @@ -3182,7 +3225,8 @@ parse_partial_symbols (struct objfile *objfile) if (*p++ == 'e') { - /* The aix4 compiler emits extra crud before the members. */ + /* The aix4 compiler emits extra crud before + the members. */ if (*p == '-') { /* Skip over the type (?). */ @@ -3202,8 +3246,8 @@ parse_partial_symbols (struct objfile *objfile) { char *q; - /* Check for and handle cretinous dbx symbol name - continuation! */ + /* Check for and handle cretinous dbx + symbol name continuation! */ if (*p == '\\' || (*p == '?' && p[1] == '\0')) p = next_symbol_text (objfile); @@ -3212,11 +3256,13 @@ parse_partial_symbols (struct objfile *objfile) for (q = p; *q && *q != ':'; q++) ; /* Note that the value doesn't matter for - enum constants in psymtabs, just in symtabs. */ + enum constants in psymtabs, just in + symtabs. */ add_psymbol_to_list (p, q - p, 1, VAR_DOMAIN, LOC_CONST, - &objfile->static_psymbols, 0, - 0, psymtab_language, objfile); + &objfile->static_psymbols, + 0, 0, psymtab_language, + objfile); /* Point past the name. */ p = q; /* Skip over the value. */ @@ -3232,8 +3278,9 @@ parse_partial_symbols (struct objfile *objfile) /* Constant, e.g. from "const" in Pascal. */ add_psymbol_to_list (namestring, p - namestring, 1, VAR_DOMAIN, LOC_CONST, - &objfile->static_psymbols, sh.value, - 0, psymtab_language, objfile); + &objfile->static_psymbols, + sh.value, 0, psymtab_language, + objfile); continue; case 'f': @@ -3247,7 +3294,8 @@ parse_partial_symbols (struct objfile *objfile) function_outside_compilation_unit_complaint (name); xfree (name); } - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); add_psymbol_to_list (namestring, p - namestring, 1, VAR_DOMAIN, LOC_BLOCK, &objfile->static_psymbols, @@ -3256,8 +3304,9 @@ parse_partial_symbols (struct objfile *objfile) continue; /* Global functions were ignored here, but now they - are put into the global psymtab like one would expect. - They're also in the minimal symbol table. */ + are put into the global psymtab like one would + expect. They're also in the minimal symbol + table. */ case 'F': if (! pst) { @@ -3269,7 +3318,8 @@ parse_partial_symbols (struct objfile *objfile) function_outside_compilation_unit_complaint (name); xfree (name); } - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); add_psymbol_to_list (namestring, p - namestring, 1, VAR_DOMAIN, LOC_BLOCK, &objfile->global_psymbols, @@ -3277,9 +3327,10 @@ parse_partial_symbols (struct objfile *objfile) psymtab_language, objfile); continue; - /* Two things show up here (hopefully); static symbols of - local scope (static used inside braces) or extensions - of structure symbols. We can ignore both. */ + /* Two things show up here (hopefully); static + symbols of local scope (static used inside + braces) or extensions of structure symbols. We + can ignore both. */ case 'V': case '(': case '0': @@ -3293,25 +3344,27 @@ parse_partial_symbols (struct objfile *objfile) case '8': case '9': case '-': - case '#': /* for symbol identification (used in live ranges) */ + case '#': /* For symbol identification (used + in live ranges). */ continue; case ':': - /* It is a C++ nested symbol. We don't need to record it - (I don't think); if we try to look up foo::bar::baz, - then symbols for the symtab containing foo should get - read in, I think. */ + /* It is a C++ nested symbol. We don't need to + record it (I don't think); if we try to look up + foo::bar::baz, then symbols for the symtab + containing foo should get read in, I think. */ /* Someone says sun cc puts out symbols like /foo/baz/maclib::/usr/local/bin/maclib, which would get here with a symbol type of ':'. */ continue; default: - /* Unexpected symbol descriptor. The second and subsequent stabs - of a continued stab can show up here. The question is - whether they ever can mimic a normal stab--it would be - nice if not, since we certainly don't want to spend the - time searching to the end of every string looking for + /* Unexpected symbol descriptor. The second and + subsequent stabs of a continued stab can show up + here. The question is whether they ever can + mimic a normal stab--it would be nice if not, + since we certainly don't want to spend the time + searching to the end of every string looking for a backslash. */ complaint (&symfile_complaints, @@ -3347,12 +3400,14 @@ parse_partial_symbols (struct objfile *objfile) case N_EINCL: case N_DSLINE: case N_BSLINE: - case N_SSYM: /* Claim: Structure or union element. - Hopefully, I can ignore this. */ - case N_ENTRY: /* Alternate entry point; can ignore. */ - case N_MAIN: /* Can definitely ignore this. */ - case N_CATCH: /* These are GNU C++ extensions */ - case N_EHDECL: /* that can safely be ignored here. */ + case N_SSYM: /* Claim: Structure or union + element. Hopefully, I can + ignore this. */ + case N_ENTRY: /* Alternate entry point; can + ignore. */ + case N_MAIN: /* Can definitely ignore this. */ + case N_CATCH: /* These are GNU C++ extensions. */ + case N_EHDECL: /* that can safely be ignored here. */ case N_LENG: case N_BCOMM: case N_ECOMM: @@ -3364,19 +3419,22 @@ parse_partial_symbols (struct objfile *objfile) case N_LBRAC: case N_NSYMS: /* Ultrix 4.0: symbol count */ case N_DEFD: /* GNU Modula-2 */ - case N_ALIAS: /* SunPro F77: alias name, ignore for now. */ + case N_ALIAS: /* SunPro F77: alias name, ignore + for now. */ - case N_OBJ: /* useless types from Solaris */ + case N_OBJ: /* Useless types from Solaris. */ case N_OPT: - /* These symbols aren't interesting; don't worry about them */ + /* These symbols aren't interesting; don't worry about + them. */ continue; default: - /* If we haven't found it yet, ignore it. It's probably some - new type we don't know about yet. */ - complaint (&symfile_complaints, _("unknown symbol type %s"), - hex_string (type_code)); /*CUR_SYMBOL_TYPE*/ + /* If we haven't found it yet, ignore it. It's + probably some new type we don't know about yet. */ + complaint (&symfile_complaints, + _("unknown symbol type %s"), + hex_string (type_code)); /* CUR_SYMBOL_TYPE */ continue; } if (stabstring @@ -3410,7 +3468,7 @@ parse_partial_symbols (struct objfile *objfile) || (sh.index == indexNil && (sh.st != stStatic || sh.sc == scAbs))) { - /* FIXME, premature? */ + /* FIXME, premature? */ cur_sdx++; continue; } @@ -3424,18 +3482,21 @@ parse_partial_symbols (struct objfile *objfile) /* The value of a stEnd symbol is the displacement from the corresponding start symbol value, do not relocate it. */ if (sh.st != stEnd) - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); break; case scData: case scSData: case scRData: case scPData: case scXData: - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); break; case scBss: case scSBss: - sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + sh.value += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); break; } @@ -3448,8 +3509,8 @@ parse_partial_symbols (struct objfile *objfile) case stStaticProc: prim_record_minimal_symbol_and_info (name, sh.value, mst_file_text, - SECT_OFF_TEXT (objfile), NULL, - objfile); + SECT_OFF_TEXT (objfile), + NULL, objfile); /* FALLTHROUGH */ @@ -3460,7 +3521,7 @@ parse_partial_symbols (struct objfile *objfile) /* Should not happen, but does when cross-compiling with the MIPS compiler. FIXME -- pull later. */ index_complaint (name); - new_sdx = cur_sdx + 1; /* Don't skip at all */ + new_sdx = cur_sdx + 1; /* Don't skip at all. */ } else new_sdx = AUX_GET_ISYM (fh->fBigendian, @@ -3474,7 +3535,7 @@ parse_partial_symbols (struct objfile *objfile) complaint (&symfile_complaints, _("bad proc end in aux found from symbol %s"), name); - new_sdx = cur_sdx + 1; /* Don't skip backward */ + new_sdx = cur_sdx + 1; /* Don't skip backward. */ } /* For stProc symbol records, we need to check the @@ -3488,7 +3549,7 @@ parse_partial_symbols (struct objfile *objfile) goto skip; /* Usually there is a local and a global stProc symbol - for a function. This means that the function name + for a function. This means that the function name has already been entered into the mimimal symbol table while processing the global symbols in pass 2 above. One notable exception is the PROGRAM name from @@ -3547,7 +3608,7 @@ parse_partial_symbols (struct objfile *objfile) break; case stIndirect: /* Irix5 forward declaration */ - /* Skip forward declarations from Irix5 cc */ + /* Skip forward declarations from Irix5 cc. */ goto skip; case stTypedef: /* Typedef */ @@ -3567,7 +3628,7 @@ parse_partial_symbols (struct objfile *objfile) case stEnum: case stBlock: /* { }, str, un, enum */ /* Do not create a partial symbol for cc unnamed aggregates - and gcc empty aggregates. */ + and gcc empty aggregates. */ if ((sh.sc == scInfo || SC_IS_COMMON (sh.sc)) && sh.iss != 0 @@ -3581,14 +3642,14 @@ parse_partial_symbols (struct objfile *objfile) } handle_psymbol_enumerators (objfile, fh, sh.st, sh.value); - /* Skip over the block */ + /* Skip over the block. */ new_sdx = sh.index; if (new_sdx <= cur_sdx) { - /* This happens with the Ultrix kernel. */ + /* This happens with the Ultrix kernel. */ complaint (&symfile_complaints, _("bad aux index at block symbol %s"), name); - new_sdx = cur_sdx + 1; /* Don't skip backward */ + new_sdx = cur_sdx + 1; /* Don't skip backward. */ } cur_sdx = new_sdx; continue; @@ -3601,7 +3662,7 @@ parse_partial_symbols (struct objfile *objfile) case stLocal: /* Local variables */ /* Normally these are skipped because we skip over all blocks we see. However, these can occur - as visible symbols in a .h file that contains code. */ + as visible symbols in a .h file that contains code. */ goto skip; default: @@ -3613,16 +3674,16 @@ parse_partial_symbols (struct objfile *objfile) cur_sdx++; continue; } - /* Use this gdb symbol */ + /* Use this gdb symbol. */ add_psymbol_to_list (name, strlen (name), 1, VAR_DOMAIN, class, &objfile->static_psymbols, 0, sh.value, psymtab_language, objfile); skip: - cur_sdx++; /* Go to next file symbol */ + cur_sdx++; /* Go to next file symbol. */ } - /* Now do enter the external symbols. */ + /* Now do enter the external symbols. */ ext_ptr = &extern_tab[fdr_to_pst[f_idx].globals_offset]; cur_sdx = fdr_to_pst[f_idx].n_globals; PST_PRIVATE (save_pst)->extern_count = cur_sdx; @@ -3635,7 +3696,8 @@ parse_partial_symbols (struct objfile *objfile) CORE_ADDR svalue; if (ext_ptr->ifd != f_idx) - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); psh = &ext_ptr->asym; /* Do not add undefined symbols to the partial symbol table. */ @@ -3647,18 +3709,21 @@ parse_partial_symbols (struct objfile *objfile) { case scText: case scRConst: - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); break; case scData: case scSData: case scRData: case scPData: case scXData: - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); break; case scBss: case scSBss: - svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile)); + svalue += ANOFFSET (objfile->section_offsets, + SECT_OFF_BSS (objfile)); break; } @@ -3698,7 +3763,7 @@ parse_partial_symbols (struct objfile *objfile) } } - /* Link pst to FDR. end_psymtab returns NULL if the psymtab was + /* Link pst to FDR. end_psymtab returns NULL if the psymtab was empty and put on the free list. */ fdr_to_pst[f_idx].pst = end_psymtab (save_pst, psymtab_include_list, includes_used, @@ -3737,7 +3802,7 @@ parse_partial_symbols (struct objfile *objfile) } } - /* Now scan the FDRs for dependencies */ + /* Now scan the FDRs for dependencies. */ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) { fh = f_idx + debug_info->fdr; @@ -3746,12 +3811,12 @@ parse_partial_symbols (struct objfile *objfile) if (pst == (struct partial_symtab *) NULL) continue; - /* This should catch stabs-in-ecoff. */ + /* This should catch stabs-in-ecoff. */ if (fh->crfd <= 1) continue; - /* Skip the first file indirect entry as it is a self dependency - for source files or a reverse .h -> .c dependency for header files. */ + /* Skip the first file indirect entry as it is a self dependency for + source files or a reverse .h -> .c dependency for header files. */ pst->number_of_dependencies = 0; pst->dependencies = ((struct partial_symtab **) @@ -3779,7 +3844,8 @@ parse_partial_symbols (struct objfile *objfile) /* Do not add to dependeny list if psymtab was empty. */ if (fdr_to_pst[rh].pst == (struct partial_symtab *) NULL) continue; - pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst; + pst->dependencies[pst->number_of_dependencies++] + = fdr_to_pst[rh].pst; } } @@ -3794,7 +3860,7 @@ parse_partial_symbols (struct objfile *objfile) } /* If the current psymbol has an enumerated type, we need to add - all the the enum constants to the partial symbol table. */ + all the enum constants to the partial symbol table. */ static void handle_psymbol_enumerators (struct objfile *objfile, FDR *fh, int stype, @@ -3861,7 +3927,7 @@ handle_psymbol_enumerators (struct objfile *objfile, FDR *fh, int stype, } } -/* Get the next symbol. OBJFILE is unused. */ +/* Get the next symbol. OBJFILE is unused. */ static char * mdebug_next_symbol_text (struct objfile *objfile) @@ -3888,7 +3954,7 @@ mdebug_next_symbol_text (struct objfile *objfile) The flow of control and even the memory allocation differs. FIXME. */ static void -psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) +psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) { bfd_size_type external_sym_size; bfd_size_type external_pdr_size; @@ -3924,7 +3990,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) wrap_here (""); /* Flush output */ gdb_flush (gdb_stdout); } - /* We only pass the filename for debug purposes */ + /* We only pass the filename for debug purposes. */ psymtab_to_symtab_1 (pst->dependencies[i], pst->dependencies[i]->filename); } @@ -3935,7 +4001,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) && pst->textlow == 0 && pst->texthigh == 0) return; - /* Now read the symbols for this symtab */ + /* Now read the symbols for this symtab. */ cur_bfd = CUR_BFD (pst); debug_swap = DEBUG_SWAP (pst); @@ -3952,7 +4018,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) : debug_info->fdr + cur_fd); cur_fdr = fh; - /* See comment in parse_partial_symbols about the @stabs sentinel. */ + /* See comment in parse_partial_symbols about the @stabs sentinel. */ processing_gcc_compilation = 0; if (fh != (FDR *) NULL && fh->csym >= 2) { @@ -3977,9 +4043,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) /* This symbol table contains stabs-in-ecoff entries. */ - /* Parse local symbols first */ + /* Parse local symbols first. */ - if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr */ + if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr. */ { current_objfile = NULL; return; @@ -4010,7 +4076,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) it here instead of in process_one_symbol, so we can keep a handle to its symtab. The symtab would otherwise be ended twice, once in - process_one_symbol, and once after this loop. */ + process_one_symbol, and once after this loop. */ if (type_code == N_SO && last_source_file && previous_stab_code != (unsigned char) N_SO @@ -4040,7 +4106,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) if (type_code == N_FUN) { /* Make up special symbol to contain - procedure specific info */ + procedure specific info. */ struct mdebug_extra_func_info *e = ((struct mdebug_extra_func_info *) obstack_alloc (¤t_objfile->objfile_obstack, @@ -4066,23 +4132,26 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) } else { - /* Handle encoded stab line number. */ - valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (pst->objfile)); + /* Handle encoded stab line number. */ + valu += ANOFFSET (pst->section_offsets, + SECT_OFF_TEXT (pst->objfile)); record_line (current_subfile, sh.index, gdbarch_addr_bits_remove (gdbarch, valu)); } } else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stStatic || sh.st == stEnd) - /* These are generated by gcc-2.x, do not complain */ + /* These are generated by gcc-2.x, do not complain. */ ; else - complaint (&symfile_complaints, _("unknown stabs symbol %s"), name); + complaint (&symfile_complaints, + _("unknown stabs symbol %s"), name); } if (! last_symtab_ended) { - st = end_symtab (pst->texthigh, pst->objfile, SECT_OFF_TEXT (pst->objfile)); + st = end_symtab (pst->texthigh, pst->objfile, + SECT_OFF_TEXT (pst->objfile)); end_stabs (); } @@ -4157,7 +4226,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) lines = LINETABLE (st); - /* Get a new lexical context */ + /* Get a new lexical context. */ push_parse_stack (); top_stack->cur_st = st; @@ -4176,7 +4245,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) char *sym_ptr; char *sym_end; - /* Parse local symbols first */ + /* Parse local symbols first. */ sym_ptr = ((char *) debug_info->external_sym + fh->isymBase * external_sym_size); sym_end = sym_ptr + fh->csym * external_sym_size; @@ -4188,7 +4257,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) (*swap_sym_in) (cur_bfd, sym_ptr, &sh); c = parse_symbol (&sh, debug_info->external_aux + fh->iauxBase, - sym_ptr, fh->fBigendian, pst->section_offsets, pst->objfile); + sym_ptr, fh->fBigendian, + pst->section_offsets, pst->objfile); sym_ptr += c * external_sym_size; } @@ -4226,7 +4296,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) lowest_pdr_addr = pdr_in->adr; } - parse_lines (fh, pr_block, lines, maxlines, pst, lowest_pdr_addr); + parse_lines (fh, pr_block, lines, maxlines, + pst, lowest_pdr_addr); if (lines->nitems < fh->cline) lines = shrink_linetable (lines); @@ -4243,16 +4314,18 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) LINETABLE (st) = lines; /* .. and our share of externals. - XXX use the global list to speed up things here. how? - FIXME, Maybe quit once we have found the right number of ext's? */ + XXX use the global list to speed up things here. How? + FIXME, Maybe quit once we have found the right number of ext's? */ top_stack->cur_st = st; - top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), - GLOBAL_BLOCK); + top_stack->cur_block + = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), + GLOBAL_BLOCK); top_stack->blocktype = stFile; ext_ptr = PST_PRIVATE (pst)->extern_tab; for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++) - parse_external (ext_ptr, fh->fBigendian, pst->section_offsets, pst->objfile); + parse_external (ext_ptr, fh->fBigendian, + pst->section_offsets, pst->objfile); /* If there are undefined symbols, tell the user. The alpha has an undefined symbol for every symbol that is @@ -4261,7 +4334,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) { printf_filtered (_("File %s contains %d unresolved references:"), st->filename, n_undef_symbols); - printf_filtered ("\n\t%4d variables\n\t%4d procedures\n\t%4d labels\n", + printf_filtered ("\n\t%4d variables\n\t%4d " + "procedures\n\t%4d labels\n", n_undef_vars, n_undef_procs, n_undef_labels); n_undef_symbols = n_undef_labels = n_undef_vars = n_undef_procs = 0; @@ -4279,7 +4353,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename) current_objfile = NULL; } -/* Ancillary parsing procedures. */ +/* Ancillary parsing procedures. */ /* Return 1 if the symbol pointed to by SH has a cross reference to an opaque aggregate type, else 0. */ @@ -4314,10 +4388,12 @@ has_opaque_xref (FDR *fh, SYMR *sh) /* Lookup the type at relative index RN. Return it in TPP if found and in any event come up with its name PNAME. BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian). - Return value says how many aux symbols we ate. */ + Return value says how many aux symbols we ate. */ static int -cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_code, /* Use to alloc new type if none is found. */ +cross_ref (int fd, union aux_ext *ax, struct type **tpp, + enum type_code type_code, + /* Use to alloc new type if none is found. */ char **pname, int bigend, char *sym_name) { RNDXR rn[1]; @@ -4333,7 +4409,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn); - /* Escape index means 'the next one' */ + /* Escape index means 'the next one'. */ if (rn->rfd == 0xfff) { result++; @@ -4350,12 +4426,13 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod if (rf == -1) { *pname = ""; - *tpp = init_type (type_code, 0, TYPE_FLAG_STUB, (char *) NULL, current_objfile); + *tpp = init_type (type_code, 0, TYPE_FLAG_STUB, + (char *) NULL, current_objfile); return result; } /* mips cc uses an escaped rn->index of 0 for struct return types - of procedures that were compiled without -g. These will always remain + of procedures that were compiled without -g. These will always remain undefined. */ if (rn->rfd == 0xfff && rn->index == 0) { @@ -4416,12 +4493,12 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod two cases: a) forward declarations of structs/unions/enums which are not defined in this compilation unit. - For these the type will be void. This is a bad design decision + For these the type will be void. This is a bad design decision as cross referencing across compilation units is impossible due to the missing name. b) forward declarations of structs/unions/enums/typedefs which are defined later in this file or in another file in the same - compilation unit. Irix5 cc uses a stIndirect symbol for this. + compilation unit. Irix5 cc uses a stIndirect symbol for this. Simply cross reference those again to get the true type. The forward references are not entered in the pending list and in the symbol table. */ @@ -4452,10 +4529,10 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod break; case btTypedef: - /* Follow a forward typedef. This might recursively + /* Follow a forward typedef. This might recursively call cross_ref till we get a non typedef'ed type. FIXME: This is not correct behaviour, but gdb currently - cannot handle typedefs without type copying. Type + cannot handle typedefs without type copying. Type copying is impossible as we might have mutual forward references between two files and the copied type would not get filled in when we later parse its definition. */ @@ -4480,10 +4557,10 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod } else if (sh.st == stTypedef) { - /* Parse the type for a normal typedef. This might recursively call + /* Parse the type for a normal typedef. This might recursively call cross_ref till we get a non typedef'ed type. FIXME: This is not correct behaviour, but gdb currently - cannot handle typedefs without type copying. But type copying is + cannot handle typedefs without type copying. But type copying is impossible as we might have mutual forward references between two files and the copied type would not get filled in when we later parse its definition. */ @@ -4506,13 +4583,13 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, enum type_code type_cod add_pending (fh, esh, *tpp); } - /* We used one auxent normally, two if we got a "next one" rf. */ + /* We used one auxent normally, two if we got a "next one" rf. */ return result; } /* Quick&dirty lookup procedure, to avoid the MI ones that require - keeping the symtab sorted */ + keeping the symtab sorted. */ static struct symbol * mylookup_symbol (char *name, struct block *block, @@ -4548,7 +4625,7 @@ add_symbol (struct symbol *s, struct symtab *symtab, struct block *b) dict_add_symbol (BLOCK_DICT (b), s); } -/* Add a new block B to a symtab S */ +/* Add a new block B to a symtab S. */ static void add_block (struct block *b, struct symtab *s) @@ -4575,7 +4652,7 @@ add_block (struct block *b, struct symtab *s) a prologue than mips_skip_prologue). But due to the compressed line table format there are line number entries for the same line which are needed to bridge the gap to the next - line number entry. These entries have a bogus address info with them + line number entry. These entries have a bogus address info with them and we are unable to tell them from intended duplicate line number entries. This is another reason why -ggdb debugging format is preferable. */ @@ -4584,13 +4661,13 @@ static int add_line (struct linetable *lt, int lineno, CORE_ADDR adr, int last) { /* DEC c89 sometimes produces zero linenos which confuse gdb. - Change them to something sensible. */ + Change them to something sensible. */ if (lineno == 0) lineno = 1; if (last == 0) - last = -2; /* make sure we record first line */ + last = -2; /* Make sure we record first line. */ - if (last == lineno) /* skip continuation lines */ + if (last == lineno) /* Skip continuation lines. */ return lineno; lt->item[lt->nitems].line = lineno; @@ -4598,9 +4675,9 @@ add_line (struct linetable *lt, int lineno, CORE_ADDR adr, int last) return lineno; } -/* Sorting and reordering procedures */ +/* Sorting and reordering procedures. */ -/* Blocks with a smaller low bound should come first */ +/* Blocks with a smaller low bound should come first. */ static int compare_blocks (const void *arg1, const void *arg2) @@ -4617,7 +4694,7 @@ compare_blocks (const void *arg1, const void *arg2) /* Sort the blocks of a symtab S. Reorder the blocks in the blockvector by code-address, - as required by some MI search routines */ + as required by some MI search routines. */ static void sort_blocks (struct symtab *s) @@ -4665,19 +4742,19 @@ sort_blocks (struct symtab *s) } -/* Constructor/restructor/destructor procedures */ +/* Constructor/restructor/destructor procedures. */ /* Allocate a new symtab for NAME. Needs an estimate of how many - linenumbers MAXLINES we'll put in it */ + linenumbers MAXLINES we'll put in it. */ static struct symtab * -new_symtab (char *name, int maxlines, struct objfile *objfile) +new_symtab (const char *name, int maxlines, struct objfile *objfile) { struct symtab *s = allocate_symtab (name, objfile); LINETABLE (s) = new_linetable (maxlines); - /* All symtabs must have at least two blocks */ + /* All symtabs must have at least two blocks. */ BLOCKVECTOR (s) = new_bvect (2); BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK); @@ -4691,7 +4768,7 @@ new_symtab (char *name, int maxlines, struct objfile *objfile) return (s); } -/* Allocate a new partial_symtab NAME */ +/* Allocate a new partial_symtab NAME. */ static struct partial_symtab * new_psymtab (char *name, struct objfile *objfile) @@ -4701,7 +4778,7 @@ new_psymtab (char *name, struct objfile *objfile) psymtab = allocate_psymtab (name, objfile); psymtab->section_offsets = objfile->section_offsets; - /* Keep a backpointer to the file's symbols */ + /* Keep a backpointer to the file's symbols. */ psymtab->read_symtab_private = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symloc)); @@ -4711,7 +4788,7 @@ new_psymtab (char *name, struct objfile *objfile) DEBUG_INFO (psymtab) = debug_info; PENDING_LIST (psymtab) = pending_list; - /* The way to turn this into a symtab is to call... */ + /* The way to turn this into a symtab is to call... */ psymtab->read_symtab = mdebug_psymtab_to_symtab; return (psymtab); } @@ -4732,7 +4809,7 @@ new_linetable (int size) return l; } -/* Oops, too big. Shrink it. This was important with the 2.4 linetables, +/* Oops, too big. Shrink it. This was important with the 2.4 linetables, I am not so sure about the 3.4 ones. Since the struct linetable already includes one item, we subtract one when @@ -4747,7 +4824,7 @@ shrink_linetable (struct linetable *lt) * sizeof (lt->item)))); } -/* Allocate and zero a new blockvector of NBLOCKS blocks. */ +/* Allocate and zero a new blockvector of NBLOCKS blocks. */ static struct blockvector * new_bvect (int nblocks) @@ -4784,7 +4861,7 @@ new_block (enum block_type type) return retval; } -/* Create a new symbol with printname NAME */ +/* Create a new symbol with printname NAME. */ static struct symbol * new_symbol (char *name) @@ -4794,12 +4871,12 @@ new_symbol (char *name) sizeof (struct symbol))); memset (s, 0, sizeof (*s)); - SYMBOL_LANGUAGE (s) = psymtab_language; + SYMBOL_SET_LANGUAGE (s, psymtab_language); SYMBOL_SET_NAMES (s, name, strlen (name), 1, current_objfile); return s; } -/* Create a new type with printname NAME */ +/* Create a new type with printname NAME. */ static struct type * new_type (char *name) diff --git a/contrib/gdb-7/gdb/mdebugread.h b/contrib/gdb-7/gdb/mdebugread.h index e7774d2ba8..71427cbd8c 100644 --- a/contrib/gdb-7/gdb/mdebugread.h +++ b/contrib/gdb-7/gdb/mdebugread.h @@ -1,6 +1,7 @@ /* Read a symbol table in ECOFF format (Third-Eye). - Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -28,8 +29,8 @@ struct mdebug_extra_func_info { - long numargs; /* number of args to procedure (was iopt) */ - PDR pdr; /* Procedure descriptor record */ + long numargs; /* Number of args to procedure (was iopt). */ + PDR pdr; /* Procedure descriptor record. */ }; /* Special symbol found in blocks associated with routines. We can diff --git a/contrib/gdb-7/gdb/mem-break.c b/contrib/gdb-7/gdb/mem-break.c index 57c8a2338b..ba7dc242e5 100644 --- a/contrib/gdb-7/gdb/mem-break.c +++ b/contrib/gdb-7/gdb/mem-break.c @@ -1,7 +1,7 @@ /* Simulate breakpoints by patching locations in the target system, for GDB. Copyright (C) 1990, 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2000, 2002, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by John Gilmore. diff --git a/contrib/gdb-7/gdb/memattr.c b/contrib/gdb-7/gdb/memattr.c index 1215ca9a00..d576155c80 100644 --- a/contrib/gdb-7/gdb/memattr.c +++ b/contrib/gdb-7/gdb/memattr.c @@ -1,7 +1,7 @@ /* Memory attributes support, for GDB. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -27,6 +27,8 @@ #include "language.h" #include "vec.h" #include "gdb_string.h" +#include "breakpoint.h" +#include "cli/cli-utils.h" const struct mem_attrib default_mem_attrib = { @@ -73,11 +75,11 @@ show_inaccessible_by_default (struct ui_file *file, int from_tty, const char *value) { if (inaccessible_by_default) - fprintf_filtered (file, _("\ -Unknown memory addresses will be treated as inaccessible.\n")); + fprintf_filtered (file, _("Unknown memory addresses will " + "be treated as inaccessible.\n")); else - fprintf_filtered (file, _("\ -Unknown memory addresses will be treated as RAM.\n")); + fprintf_filtered (file, _("Unknown memory addresses " + "will be treated as RAM.\n")); } @@ -176,7 +178,7 @@ create_mem_region (CORE_ADDR lo, CORE_ADDR hi, struct mem_region new; int i, ix; - /* lo == hi is a useless empty region */ + /* lo == hi is a useless empty region. */ if (lo >= hi && hi != 0) { printf_unfiltered (_("invalid memory region: low >= high\n")); @@ -253,7 +255,8 @@ lookup_mem_region (CORE_ADDR addr) { if (m->enabled_p == 1) { - /* If the address is in the memory region, return that memory range. */ + /* If the address is in the memory region, return that + memory range. */ if (addr >= m->lo && (addr < m->hi || m->hi == 0)) return m; @@ -301,7 +304,7 @@ invalidate_target_mem_regions (void) mem_region_list = NULL; } -/* Clear memory region list */ +/* Clear memory region list. */ static void mem_clear (void) @@ -541,7 +544,7 @@ mem_info_command (char *args, int from_tty) } -/* Enable the memory region number NUM. */ +/* Enable the memory region number NUM. */ static void mem_enable (int num) @@ -561,8 +564,6 @@ mem_enable (int num) static void mem_enable_command (char *args, int from_tty) { - char *p = args; - char *p1; int num; struct mem_region *m; int ix; @@ -571,31 +572,26 @@ mem_enable_command (char *args, int from_tty) target_dcache_invalidate (); - if (p == 0) - { + if (args == NULL || *args == '\0') + { /* Enable all mem regions. */ for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++) m->enabled_p = 1; } else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be memory region numbers.")); - - num = atoi (p); - mem_enable (num); - - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + { + struct get_number_or_range_state state; + + init_number_or_range (&state, args); + while (!state.finished) + { + num = get_number_or_range (&state); + mem_enable (num); + } + } } -/* Disable the memory region number NUM. */ +/* Disable the memory region number NUM. */ static void mem_disable (int num) @@ -615,8 +611,6 @@ mem_disable (int num) static void mem_disable_command (char *args, int from_tty) { - char *p = args; - char *p1; int num; struct mem_region *m; int ix; @@ -625,30 +619,25 @@ mem_disable_command (char *args, int from_tty) target_dcache_invalidate (); - if (p == 0) + if (args == NULL || *args == '\0') { for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++) m->enabled_p = 0; } else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be memory region numbers.")); - - num = atoi (p); - mem_disable (num); - - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + { + struct get_number_or_range_state state; + + init_number_or_range (&state, args); + while (!state.finished) + { + num = get_number_or_range (&state); + mem_disable (num); + } + } } -/* Delete the memory region number NUM. */ +/* Delete the memory region number NUM. */ static void mem_delete (int num) @@ -678,15 +667,14 @@ mem_delete (int num) static void mem_delete_command (char *args, int from_tty) { - char *p = args; - char *p1; int num; + struct get_number_or_range_state state; require_user_regions (from_tty); target_dcache_invalidate (); - if (p == 0) + if (args == NULL || *args == '\0') { if (query (_("Delete all memory regions? "))) mem_clear (); @@ -694,20 +682,11 @@ mem_delete_command (char *args, int from_tty) return; } - while (*p) + init_number_or_range (&state, args); + while (!state.finished) { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be memory region numbers.")); - - num = atoi (p); + num = get_number_or_range (&state); mem_delete (num); - - p = p1; - while (*p == ' ' || *p == '\t') - p++; } dont_repeat (); @@ -738,19 +717,19 @@ where may be rw (read/write), ro (read-only) or wo (write-only),\n\ add_cmd ("mem", class_vars, mem_enable_command, _("\ Enable memory region.\n\ Arguments are the code numbers of the memory regions to enable.\n\ -Usage: enable mem \n\ +Usage: enable mem ...\n\ Do \"info mem\" to see current list of code numbers."), &enablelist); add_cmd ("mem", class_vars, mem_disable_command, _("\ Disable memory region.\n\ Arguments are the code numbers of the memory regions to disable.\n\ -Usage: disable mem \n\ +Usage: disable mem ...\n\ Do \"info mem\" to see current list of code numbers."), &disablelist); add_cmd ("mem", class_vars, mem_delete_command, _("\ Delete memory region.\n\ Arguments are the code numbers of the memory regions to delete.\n\ -Usage: delete mem \n\ +Usage: delete mem ...\n\ Do \"info mem\" to see current list of code numbers."), &deletelist); add_info ("mem", mem_info_command, diff --git a/contrib/gdb-7/gdb/memattr.h b/contrib/gdb-7/gdb/memattr.h index 739df9480f..5596730686 100644 --- a/contrib/gdb-7/gdb/memattr.h +++ b/contrib/gdb-7/gdb/memattr.h @@ -1,6 +1,6 @@ /* Memory attributes support, for GDB. - Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -25,7 +25,7 @@ enum mem_access_mode { - MEM_NONE, /* Memory that is not physically present. */ + MEM_NONE, /* Memory that is not physically present. */ MEM_RW, /* read/write */ MEM_RO, /* read only */ MEM_WO, /* write only */ @@ -51,7 +51,7 @@ enum mem_access_width the mem_region structure. FIXME: It would be useful if there was a mechanism for targets to - add their own attributes. For example, the number of wait states. */ + add their own attributes. For example, the number of wait states. */ struct mem_attrib { @@ -66,9 +66,9 @@ struct mem_attrib /* enables host-side caching of memory region data */ int cache; - /* enables memory verification. after a write, memory is re-read - to verify that the write was successful. */ - int verify; + /* Enables memory verification. After a write, memory is re-read + to verify that the write was successful. */ + int verify; /* Block size. Only valid if mode == MEM_FLASH. */ int blocksize; @@ -82,13 +82,14 @@ struct mem_region If 0, upper bound is "infinity". */ CORE_ADDR hi; - /* Item number of this memory region. */ + /* Item number of this memory region. */ int number; - /* Status of this memory region (enabled if non-zero, otherwise disabled) */ + /* Status of this memory region (enabled if non-zero, otherwise + disabled). */ int enabled_p; - /* Attributes for this region */ + /* Attributes for this region. */ struct mem_attrib attrib; }; diff --git a/contrib/gdb-7/gdb/memory-map.c b/contrib/gdb-7/gdb/memory-map.c index 5c58174037..5e61ca5722 100644 --- a/contrib/gdb-7/gdb/memory-map.c +++ b/contrib/gdb-7/gdb/memory-map.c @@ -1,6 +1,7 @@ /* Routines for handling XML memory maps provided by target. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -63,9 +64,9 @@ memory_map_start_memory (struct gdb_xml_parser *parser, struct mem_region *r = VEC_safe_push (mem_region_s, *data->memory_map, NULL); ULONGEST *start_p, *length_p, *type_p; - start_p = VEC_index (gdb_xml_value_s, attributes, 0)->value; - length_p = VEC_index (gdb_xml_value_s, attributes, 1)->value; - type_p = VEC_index (gdb_xml_value_s, attributes, 2)->value; + start_p = xml_find_attribute (attributes, "start")->value; + length_p = xml_find_attribute (attributes, "length")->value; + type_p = xml_find_attribute (attributes, "type")->value; mem_region_init (r); r->lo = *start_p; @@ -100,7 +101,7 @@ memory_map_start_property (struct gdb_xml_parser *parser, struct memory_map_parsing_data *data = user_data; char *name; - name = VEC_index (gdb_xml_value_s, attributes, 0)->value; + name = xml_find_attribute (attributes, "name")->value; snprintf (data->property_name, sizeof (data->property_name), "%s", name); } @@ -177,25 +178,22 @@ const struct gdb_xml_element memory_map_elements[] = { VEC(mem_region_s) * parse_memory_map (const char *memory_map) { - struct gdb_xml_parser *parser; VEC(mem_region_s) *result = NULL; - struct cleanup *before_deleting_result, *back_to; + struct cleanup *back_to; struct memory_map_parsing_data data = { NULL }; - back_to = make_cleanup (null_cleanup, NULL); - parser = gdb_xml_create_parser_and_cleanup (_("target memory map"), - memory_map_elements, &data); - - /* Note: 'clear_result' will zero 'result'. */ - before_deleting_result = make_cleanup (clear_result, &result); data.memory_map = &result; - - if (gdb_xml_parse (parser, memory_map) == 0) - /* Parsed successfully, don't need to delete the result. */ - discard_cleanups (before_deleting_result); + back_to = make_cleanup (clear_result, &result); + if (gdb_xml_parse_quick (_("target memory map"), NULL, memory_map_elements, + memory_map, &data) == 0) + { + /* Parsed successfully, keep the result. */ + discard_cleanups (back_to); + return result; + } do_cleanups (back_to); - return result; + return NULL; } #endif /* HAVE_LIBEXPAT */ diff --git a/contrib/gdb-7/gdb/memory-map.h b/contrib/gdb-7/gdb/memory-map.h index fc9d5558f7..64a711f94c 100644 --- a/contrib/gdb-7/gdb/memory-map.h +++ b/contrib/gdb-7/gdb/memory-map.h @@ -1,6 +1,7 @@ /* Routines for handling XML memory maps provided by target. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -25,7 +26,8 @@ /* Parses XML memory map passed as argument and returns the memory regions it describes. On any error, emits error message and - returns 0. Does not throw. Ownership of result is passed to the caller. */ + returns 0. Does not throw. Ownership of result is passed to the + caller. */ VEC(mem_region_s) *parse_memory_map (const char *memory_map); #endif diff --git a/contrib/gdb-7/gdb/memrange.c b/contrib/gdb-7/gdb/memrange.c new file mode 100644 index 0000000000..dcacff665e --- /dev/null +++ b/contrib/gdb-7/gdb/memrange.c @@ -0,0 +1,88 @@ +/* Memory ranges + + Copyright (C) 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "memrange.h" + +int +mem_ranges_overlap (CORE_ADDR start1, int len1, + CORE_ADDR start2, int len2) +{ + ULONGEST h, l; + + l = max (start1, start2); + h = min (start1 + len1, start2 + len2); + return (l < h); +} + +/* qsort comparison function, that compares mem_ranges. Ranges are + sorted in ascending START order. */ + +static int +compare_mem_ranges (const void *ap, const void *bp) +{ + const struct mem_range *r1 = ap; + const struct mem_range *r2 = bp; + + if (r1->start > r2->start) + return 1; + else if (r1->start < r2->start) + return -1; + else + return 0; +} + +void +normalize_mem_ranges (VEC(mem_range_s) *ranges) +{ + /* This function must not use any VEC operation on RANGES that + reallocates the memory block as that invalidates the RANGES + pointer, which callers expect to remain valid. */ + + if (!VEC_empty (mem_range_s, ranges)) + { + struct mem_range *ra, *rb; + int a, b; + + qsort (VEC_address (mem_range_s, ranges), + VEC_length (mem_range_s, ranges), + sizeof (mem_range_s), + compare_mem_ranges); + + a = 0; + ra = VEC_index (mem_range_s, ranges, a); + for (b = 1; VEC_iterate (mem_range_s, ranges, b, rb); b++) + { + /* If mem_range B overlaps or is adjacent to mem_range A, + merge them. */ + if (rb->start <= ra->start + ra->length) + { + ra->length = max (ra->length, + (rb->start - ra->start) + rb->length); + continue; /* next b, same a */ + } + a++; /* next a */ + ra = VEC_index (mem_range_s, ranges, a); + + if (a != b) + *ra = *rb; + } + VEC_truncate (mem_range_s, ranges, a + 1); + } +} diff --git a/contrib/gdb-7/gdb/memrange.h b/contrib/gdb-7/gdb/memrange.h new file mode 100644 index 0000000000..9071b88de5 --- /dev/null +++ b/contrib/gdb-7/gdb/memrange.h @@ -0,0 +1,51 @@ +/* The memory range data structure, and associated utilities. + + Copyright (C) 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef MEMRANGE_H +#define MEMRANGE_H + +#include "vec.h" + +/* Defines a [START, START + LENGTH) memory range. */ + +struct mem_range +{ + /* Lowest address in the range. */ + CORE_ADDR start; + + /* Length of the range. */ + int length; +}; + +typedef struct mem_range mem_range_s; + +DEF_VEC_O(mem_range_s); + +/* Returns true if the ranges defined by [start1, start1+len1) and + [start2, start2+len2) overlap. */ + +extern int mem_ranges_overlap (CORE_ADDR start1, int len1, + CORE_ADDR start2, int len2); + +/* Sort ranges by start address, then coalesce contiguous or + overlapping ranges. */ + +extern void normalize_mem_ranges (VEC(mem_range_s) *memory); + +#endif diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-break.c b/contrib/gdb-7/gdb/mi/mi-cmd-break.c index 34082440a1..fe007a5cea 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-break.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-break.c @@ -1,5 +1,5 @@ /* MI Command Set - breakpoint and watchpoint commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -103,7 +103,8 @@ mi_cmd_break_insert (char *command, char **argv, int argc) while (1) { - int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg); + int opt = mi_getopt ("-break-insert", argc, argv, + opts, &optind, &optarg); if (opt < 0) break; switch ((enum opt) opt) @@ -136,9 +137,9 @@ mi_cmd_break_insert (char *command, char **argv, int argc) } if (optind >= argc) - error (_("mi_cmd_break_insert: Missing ")); + error (_("-break-insert: Missing ")); if (optind < argc - 1) - error (_("mi_cmd_break_insert: Garbage following ")); + error (_("-break-insert: Garbage following ")); address = argv[optind]; /* Now we have what we need, let's insert the breakpoint! */ @@ -169,7 +170,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc) temp_p, type_wanted, ignore_count, pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, - NULL, 0, enabled); + NULL, 0, enabled, 0); do_cleanups (back_to); } @@ -234,7 +235,7 @@ mi_cmd_break_watch (char *command, char **argv, int argc) while (1) { - int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, + int opt = mi_getopt ("-break-watch", argc, argv, opts, &optind, &optarg); if (opt < 0) @@ -250,25 +251,25 @@ mi_cmd_break_watch (char *command, char **argv, int argc) } } if (optind >= argc) - error (_("mi_cmd_break_watch: Missing ")); + error (_("-break-watch: Missing ")); if (optind < argc - 1) - error (_("mi_cmd_break_watch: Garbage following ")); + error (_("-break-watch: Garbage following ")); expr = argv[optind]; /* Now we have what we need, let's insert the watchpoint! */ switch (type) { case REG_WP: - watch_command_wrapper (expr, FROM_TTY); + watch_command_wrapper (expr, FROM_TTY, 0); break; case READ_WP: - rwatch_command_wrapper (expr, FROM_TTY); + rwatch_command_wrapper (expr, FROM_TTY, 0); break; case ACCESS_WP: - awatch_command_wrapper (expr, FROM_TTY); + awatch_command_wrapper (expr, FROM_TTY, 0); break; default: - error (_("mi_cmd_break_watch: Unknown watchpoint type.")); + error (_("-break-watch: Unknown watchpoint type.")); } } @@ -299,19 +300,19 @@ mi_cmd_break_commands (char *command, char **argv, int argc) struct breakpoint *b; if (argc < 1) - error ("USAGE: %s [ [...]]", command); + error (_("USAGE: %s [ [...]]"), command); bnum = strtol (argv[0], &endptr, 0); if (endptr == argv[0]) - error ("breakpoint number argument \"%s\" is not a number.", + error (_("breakpoint number argument \"%s\" is not a number."), argv[0]); else if (*endptr != '\0') - error ("junk at the end of breakpoint number argument \"%s\".", + error (_("junk at the end of breakpoint number argument \"%s\"."), argv[0]); b = get_breakpoint (bnum); if (b == NULL) - error ("breakpoint %d not found.", bnum); + error (_("breakpoint %d not found."), bnum); mi_command_line_array = argv; mi_command_line_array_ptr = 1; diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-disas.c b/contrib/gdb-7/gdb/mi/mi-cmd-disas.c index b543acc6c2..28e84f661d 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-disas.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-disas.c @@ -1,5 +1,5 @@ /* MI Command Set - disassemble commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -40,21 +40,24 @@ FILENAME: The name of the file where we want disassemble from. LINE: The line around which we want to disassemble. It will disassemble the function that contins that line. - HOW_MANY: Number of disassembly lines to display. In mixed mode, it + HOW_MANY: Number of disassembly lines to display. With source, it is the number of disassembly lines only, not counting the source lines. always required: - MODE: 0 or 1 for disassembly only, or mixed source and disassembly, - respectively. */ + MODE: 0 -- disassembly. + 1 -- disassembly and source. + 2 -- disassembly and opcodes. + 3 -- disassembly, source and opcodes. +*/ void mi_cmd_disassemble (char *command, char **argv, int argc) { struct gdbarch *gdbarch = get_current_arch (); CORE_ADDR start; - int mixed_source_and_assembly; + int mode, disasm_flags; struct symtab *s; /* Which options have we processed ... */ @@ -70,6 +73,7 @@ mi_cmd_disassemble (char *command, char **argv, int argc) int how_many = -1; CORE_ADDR low = 0; CORE_ADDR high = 0; + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); /* Options processing stuff. */ int optind = 0; @@ -91,7 +95,7 @@ mi_cmd_disassemble (char *command, char **argv, int argc) encountered. */ while (1) { - int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts, + int opt = mi_getopt ("-data-disassemble", argc, argv, opts, &optind, &optarg); if (opt < 0) break; @@ -100,6 +104,7 @@ mi_cmd_disassemble (char *command, char **argv, int argc) case FILE_OPT: file_string = xstrdup (optarg); file_seen = 1; + make_cleanup (xfree, file_string); break; case LINE_OPT: line_num = atoi (optarg); @@ -128,17 +133,24 @@ mi_cmd_disassemble (char *command, char **argv, int argc) if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen) || (line_seen && file_seen && !num_seen && !start_seen && !end_seen) || (!line_seen && !file_seen && !num_seen && start_seen && end_seen))) - error - ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode."); + error (_("-data-disassemble: Usage: ( [-f filename -l linenum [-n " + "howmany]] | [-s startaddr -e endaddr]) [--] mode.")); if (argc != 1) - error - ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode."); + error (_("-data-disassemble: Usage: [-f filename -l linenum " + "[-n howmany]] [-s startaddr -e endaddr] [--] mode.")); - mixed_source_and_assembly = atoi (argv[0]); - if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1)) - error (_("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.")); + mode = atoi (argv[0]); + if (mode < 0 || mode > 3) + error (_("-data-disassemble: Mode argument must be 0, 1, 2, or 3.")); + /* Convert the mode into a set of disassembly flags */ + + disasm_flags = 0; + if (mode & 0x1) + disasm_flags |= DISASSEMBLY_SOURCE; + if (mode & 0x2) + disasm_flags |= DISASSEMBLY_RAW_INSN; /* We must get the function beginning and end where line_num is contained. */ @@ -147,15 +159,18 @@ mi_cmd_disassemble (char *command, char **argv, int argc) { s = lookup_symtab (file_string); if (s == NULL) - error (_("mi_cmd_disassemble: Invalid filename.")); + error (_("-data-disassemble: Invalid filename.")); if (!find_line_pc (s, line_num, &start)) - error (_("mi_cmd_disassemble: Invalid line number")); + error (_("-data-disassemble: Invalid line number")); if (find_pc_partial_function (start, NULL, &low, &high) == 0) - error (_("mi_cmd_disassemble: No function contains specified address")); + error (_("-data-disassemble: " + "No function contains specified address")); } gdb_disassembly (gdbarch, uiout, file_string, - mixed_source_and_assembly? DISASSEMBLY_SOURCE : 0, + disasm_flags, how_many, low, high); + + do_cleanups (cleanups); } diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-env.c b/contrib/gdb-7/gdb/mi/mi-cmd-env.c index 24f6426989..ad34aacf56 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-env.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-env.c @@ -1,6 +1,6 @@ /* MI Command Set - environment commands. - Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Red Hat Inc. @@ -70,7 +70,7 @@ void mi_cmd_env_pwd (char *command, char **argv, int argc) { if (argc > 0) - error (_("mi_cmd_env_pwd: No arguments required")); + error (_("-environment-pwd: No arguments required")); if (mi_version (uiout) < 2) { @@ -81,7 +81,7 @@ mi_cmd_env_pwd (char *command, char **argv, int argc) /* Otherwise the mi level is 2 or higher. */ if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) - error (_("mi_cmd_env_pwd: error finding name of working directory: %s"), + error (_("-environment-pwd: error finding name of working directory: %s"), safe_strerror (errno)); ui_out_field_string (uiout, "cwd", gdb_dirbuf); @@ -92,7 +92,7 @@ void mi_cmd_env_cd (char *command, char **argv, int argc) { if (argc == 0 || argc > 1) - error (_("mi_cmd_env_cd: Usage DIRECTORY")); + error (_("-environment-cd: Usage DIRECTORY")); env_execute_cli_command ("cd", argv[0]); } @@ -140,7 +140,7 @@ mi_cmd_env_path (char *command, char **argv, int argc) /* Otherwise the mi level is 2 or higher. */ while (1) { - int opt = mi_getopt ("mi_cmd_env_path", argc, argv, opts, + int opt = mi_getopt ("-environment-path", argc, argv, opts, &optind, &optarg); if (opt < 0) @@ -211,7 +211,7 @@ mi_cmd_env_dir (char *command, char **argv, int argc) /* Otherwise mi level is 2 or higher. */ while (1) { - int opt = mi_getopt ("mi_cmd_env_dir", argc, argv, opts, + int opt = mi_getopt ("-environment-directory", argc, argv, opts, &optind, &optarg); if (opt < 0) @@ -253,8 +253,8 @@ mi_cmd_inferior_tty_show (char *command, char **argv, int argc) { const char *inferior_io_terminal = get_inferior_io_terminal (); - if ( !mi_valid_noargs ("mi_cmd_inferior_tty_show", argc, argv)) - error (_("mi_cmd_inferior_tty_show: Usage: No args")); + if ( !mi_valid_noargs ("-inferior-tty-show", argc, argv)) + error (_("-inferior-tty-show: Usage: No args")); if (inferior_io_terminal) ui_out_field_string (uiout, "inferior_tty_terminal", inferior_io_terminal); @@ -279,4 +279,5 @@ _initialize_mi_cmd_env (void) if (!env) env = ""; orig_path = xstrdup (env); + free_environ (environment); } diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-file.c b/contrib/gdb-7/gdb/mi/mi-cmd-file.c index 5542eaa8f7..0150ca07d4 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-file.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-file.c @@ -1,5 +1,5 @@ /* MI Command Set - breakpoint and watchpoint commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -35,8 +35,8 @@ mi_cmd_file_list_exec_source_file (char *command, char **argv, int argc) { struct symtab_and_line st; - if (!mi_valid_noargs ("mi_cmd_file_list_exec_source_file", argc, argv)) - error (_("mi_cmd_file_list_exec_source_file: Usage: No args")); + if (!mi_valid_noargs ("-file-list-exec-source-file", argc, argv)) + error (_("-file-list-exec-source-file: Usage: No args")); /* Set the default file and line, also get them */ set_default_source_symtab_and_line (); @@ -46,7 +46,7 @@ mi_cmd_file_list_exec_source_file (char *command, char **argv, int argc) Apparently, filename does not need to be tested for NULL. The documentation in symtab.h suggests it will always be correct */ if (!st.symtab) - error (_("mi_cmd_file_list_exec_source_file: No symtab")); + error (_("-file-list-exec-source-file: No symtab")); /* Extract the fullname if it is not known yet */ symtab_to_fullname (st.symtab); @@ -83,8 +83,8 @@ mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc) struct symtab *s; struct objfile *objfile; - if (!mi_valid_noargs ("mi_cmd_file_list_exec_source_files", argc, argv)) - error (_("mi_cmd_file_list_exec_source_files: Usage: No args")); + if (!mi_valid_noargs ("-file-list-exec-source-files", argc, argv)) + error (_("-file-list-exec-source-files: Usage: No args")); /* Print the table header */ ui_out_begin (uiout, ui_out_type_list, "files"); diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-stack.c b/contrib/gdb-7/gdb/mi/mi-cmd-stack.c index 67970558c0..ad2085115b 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-stack.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-stack.c @@ -1,5 +1,5 @@ /* MI Command Set - stack commands. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -31,7 +31,7 @@ #include "gdb_string.h" #include "language.h" #include "valprint.h" - +#include "exceptions.h" enum what_to_list { locals, arguments, all }; @@ -53,7 +53,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) struct frame_info *fi; if (argc > 2 || argc == 1) - error (_("mi_cmd_stack_list_frames: Usage: [FRAME_LOW FRAME_HIGH]")); + error (_("-stack-list-frames: Usage: [FRAME_LOW FRAME_HIGH]")); if (argc == 2) { @@ -76,7 +76,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) i++, fi = get_prev_frame (fi)); if (fi == NULL) - error (_("mi_cmd_stack_list_frames: Not enough frames in stack.")); + error (_("-stack-list-frames: Not enough frames in stack.")); cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "stack"); @@ -103,7 +103,7 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc) struct frame_info *fi; if (argc > 1) - error (_("mi_cmd_stack_info_depth: Usage: [MAX_DEPTH]")); + error (_("-stack-info-depth: Usage: [MAX_DEPTH]")); if (argc == 1) frame_high = atoi (argv[0]); @@ -147,7 +147,7 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) struct frame_info *frame; if (argc != 1) - error (_("mi_cmd_stack_list_locals: Usage: PRINT_VALUES")); + error (_("-stack-list-locals: Usage: PRINT_VALUES")); frame = get_selected_frame (NULL); @@ -168,7 +168,8 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) enum print_values print_values; if (argc < 1 || argc > 3 || argc == 2) - error (_("mi_cmd_stack_list_args: Usage: PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + error (_("-stack-list-arguments: Usage: " + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); if (argc == 3) { @@ -193,9 +194,10 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) i++, fi = get_prev_frame (fi)); if (fi == NULL) - error (_("mi_cmd_stack_list_args: Not enough frames in stack.")); + error (_("-stack-list-arguments: Not enough frames in stack.")); - cleanup_stack_args = make_cleanup_ui_out_list_begin_end (uiout, "stack-args"); + cleanup_stack_args + = make_cleanup_ui_out_list_begin_end (uiout, "stack-args"); /* Now let's print the frames up to frame_high, or until there are frames in the stack. */ @@ -334,27 +336,47 @@ list_args_or_locals (enum what_to_list what, int values, struct frame_info *fi) && TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) { - struct value_print_options opts; - - val = read_var_value (sym2, fi); - get_raw_print_options (&opts); - opts.deref_ref = 1; - common_val_print - (val, stb->stream, 0, &opts, - language_def (SYMBOL_LANGUAGE (sym2))); + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + struct value_print_options opts; + + val = read_var_value (sym2, fi); + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print + (val, stb->stream, 0, &opts, + language_def (SYMBOL_LANGUAGE (sym2))); + } + if (except.reason < 0) + fprintf_filtered (stb->stream, + _(""), + except.message); + ui_out_field_stream (uiout, "value", stb); } break; case PRINT_ALL_VALUES: { - struct value_print_options opts; - - val = read_var_value (sym2, fi); - get_raw_print_options (&opts); - opts.deref_ref = 1; - common_val_print - (val, stb->stream, 0, &opts, - language_def (SYMBOL_LANGUAGE (sym2))); + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + struct value_print_options opts; + + val = read_var_value (sym2, fi); + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print + (val, stb->stream, 0, &opts, + language_def (SYMBOL_LANGUAGE (sym2))); + } + if (except.reason < 0) + fprintf_filtered (stb->stream, + _(""), + except.message); + ui_out_field_stream (uiout, "value", stb); } break; @@ -377,7 +399,7 @@ void mi_cmd_stack_select_frame (char *command, char **argv, int argc) { if (argc == 0 || argc > 1) - error (_("mi_cmd_stack_select_frame: Usage: FRAME_SPEC")); + error (_("-stack-select-frame: Usage: FRAME_SPEC")); select_frame_command (argv[0], 1 /* not used */ ); } @@ -386,7 +408,7 @@ void mi_cmd_stack_info_frame (char *command, char **argv, int argc) { if (argc > 0) - error (_("mi_cmd_stack_info_frame: No arguments required")); + error (_("-stack-info-frame: No arguments required")); print_frame_info (get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0); } diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-target.c b/contrib/gdb-7/gdb/mi/mi-cmd-target.c index 0e5df2179e..295a38bd4b 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-target.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-target.c @@ -1,5 +1,5 @@ /* MI Command Set - target commands. - Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -33,11 +33,11 @@ mi_cmd_target_file_get (char *command, char **argv, int argc) { { 0, 0, 0 } }; - static const char *prefix = "mi_cmd_target_file_get"; + static const char *prefix = "-target-file-get"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 2) - error (_("mi_cmd_target_file_get: Usage: REMOTE_FILE LOCAL_FILE")); + error (_("-target-file-get: Usage: REMOTE_FILE LOCAL_FILE")); remote_file = argv[optind]; local_file = argv[optind + 1]; @@ -57,11 +57,11 @@ mi_cmd_target_file_put (char *command, char **argv, int argc) { { 0, 0, 0 } }; - static const char *prefix = "mi_cmd_target_file_put"; + static const char *prefix = "-target-file-put"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 2) - error (_("mi_cmd_target_file_put: Usage: LOCAL_FILE REMOTE_FILE")); + error (_("-target-file-put: Usage: LOCAL_FILE REMOTE_FILE")); local_file = argv[optind]; remote_file = argv[optind + 1]; @@ -81,11 +81,11 @@ mi_cmd_target_file_delete (char *command, char **argv, int argc) { { 0, 0, 0 } }; - static const char *prefix = "mi_cmd_target_file_delete"; + static const char *prefix = "-target-file-delete"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 1) - error (_("mi_cmd_target_file_delete: Usage: REMOTE_FILE")); + error (_("-target-file-delete: Usage: REMOTE_FILE")); remote_file = argv[optind]; diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-var.c b/contrib/gdb-7/gdb/mi/mi-cmd-var.c index 310ade9d03..a40184680d 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-var.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-var.c @@ -1,6 +1,6 @@ /* MI Command Set - varobj commands. - Copyright (C) 2000, 2002, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2002, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -41,7 +41,8 @@ static void varobj_update_one (struct varobj *var, enum print_values print_values, int explicit); -static int mi_print_value_p (struct varobj *var, enum print_values print_values); +static int mi_print_value_p (struct varobj *var, + enum print_values print_values); /* Print variable object VAR. The PRINT_VALUES parameter controls if the value should be printed. The PRINT_EXPRESSION parameter @@ -107,9 +108,9 @@ mi_cmd_var_create (char *command, char **argv, int argc) if (argc != 3) { - /* mi_error_message = xstrprintf ("mi_cmd_var_create: Usage: + /* mi_error_message = xstrprintf ("-var-create: Usage: ...."); return MI_CMD_ERROR; */ - error (_("mi_cmd_var_create: Usage: NAME FRAME EXPRESSION.")); + error (_("-var-create: Usage: NAME FRAME EXPRESSION.")); } name = xstrdup (argv[0]); @@ -129,7 +130,7 @@ mi_cmd_var_create (char *command, char **argv, int argc) name = varobj_gen_name (); } else if (!isalpha (*name)) - error (_("mi_cmd_var_create: name of object must begin with a letter")); + error (_("-var-create: name of object must begin with a letter")); if (strcmp (frame, "*") == 0) var_type = USE_CURRENT_FRAME; @@ -149,7 +150,7 @@ mi_cmd_var_create (char *command, char **argv, int argc) var = varobj_create (name, expr, frameaddr, var_type); if (var == NULL) - error (_("mi_cmd_var_create: unable to create variable object")); + error (_("-var-create: unable to create variable object")); print_varobj (var, PRINT_ALL_VALUES, 0 /* don't print expression */); @@ -168,7 +169,7 @@ mi_cmd_var_delete (char *command, char **argv, int argc) struct cleanup *old_cleanups; if (argc < 1 || argc > 2) - error (_("mi_cmd_var_delete: Usage: [-c] EXPRESSION.")); + error (_("-var-delete: Usage: [-c] EXPRESSION.")); name = xstrdup (argv[0]); /* Add cleanup for name. Must be free_current_contents as @@ -180,9 +181,10 @@ mi_cmd_var_delete (char *command, char **argv, int argc) if (argc == 1) { if (strcmp (name, "-c") == 0) - error (_("mi_cmd_var_delete: Missing required argument after '-c': variable object name")); + error (_("-var-delete: Missing required " + "argument after '-c': variable object name")); if (*name == '-') - error (_("mi_cmd_var_delete: Illegal variable object name")); + error (_("-var-delete: Illegal variable object name")); } /* If we have 2 arguments they must be '-c' followed by a string @@ -190,7 +192,7 @@ mi_cmd_var_delete (char *command, char **argv, int argc) if (argc == 2) { if (strcmp (name, "-c") != 0) - error (_("mi_cmd_var_delete: Invalid option.")); + error (_("-var-delete: Invalid option.")); children_only_p = 1; do_cleanups (old_cleanups); name = xstrdup (argv[1]); @@ -232,7 +234,8 @@ mi_parse_format (const char *arg) return FORMAT_OCTAL; } - error (_("Must specify the format as: \"natural\", \"binary\", \"decimal\", \"hexadecimal\", or \"octal\"")); + error (_("Must specify the format as: \"natural\", " + "\"binary\", \"decimal\", \"hexadecimal\", or \"octal\"")); } void @@ -243,7 +246,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) char *val; if (argc != 2) - error (_("mi_cmd_var_set_format: Usage: NAME FORMAT.")); + error (_("-var-set-format: Usage: NAME FORMAT.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -268,12 +271,12 @@ mi_cmd_var_set_visualizer (char *command, char **argv, int argc) struct varobj *var; if (argc != 2) - error ("Usage: NAME VISUALIZER_FUNCTION."); + error (_("Usage: NAME VISUALIZER_FUNCTION.")); var = varobj_get_handle (argv[0]); if (var == NULL) - error ("Variable object not found"); + error (_("Variable object not found")); varobj_set_visualizer (var, argv[1]); } @@ -311,7 +314,7 @@ mi_cmd_var_show_format (char *command, char **argv, int argc) struct varobj *var; if (argc != 1) - error (_("mi_cmd_var_show_format: Usage: NAME.")); + error (_("-var-show-format: Usage: NAME.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -328,7 +331,7 @@ mi_cmd_var_info_num_children (char *command, char **argv, int argc) struct varobj *var; if (argc != 1) - error (_("mi_cmd_var_info_num_children: Usage: NAME.")); + error (_("-var-info-num-children: Usage: NAME.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -400,7 +403,8 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) char *display_hint; if (argc < 1 || argc > 4) - error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME [FROM TO]")); + error (_("-var-list-children: Usage: " + "[PRINT_VALUES] NAME [FROM TO]")); /* Get varobj handle, if a valid var obj name was specified */ if (argc == 1 || argc == 3) @@ -465,7 +469,7 @@ mi_cmd_var_info_type (char *command, char **argv, int argc) struct varobj *var; if (argc != 1) - error (_("mi_cmd_var_info_type: Usage: NAME.")); + error (_("-var-info-type: Usage: NAME.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -497,7 +501,7 @@ mi_cmd_var_info_expression (char *command, char **argv, int argc) struct varobj *var; if (argc != 1) - error (_("mi_cmd_var_info_expression: Usage: NAME.")); + error (_("-var-info-expression: Usage: NAME.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -516,7 +520,7 @@ mi_cmd_var_show_attributes (char *command, char **argv, int argc) struct varobj *var; if (argc != 1) - error (_("mi_cmd_var_show_attributes: Usage: NAME.")); + error (_("-var-show-attributes: Usage: NAME.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); @@ -606,18 +610,19 @@ mi_cmd_var_assign (char *command, char **argv, int argc) char *expression, *val; if (argc != 2) - error (_("mi_cmd_var_assign: Usage: NAME EXPRESSION.")); + error (_("-var-assign: Usage: NAME EXPRESSION.")); /* Get varobj handle, if a valid var obj name was specified */ var = varobj_get_handle (argv[0]); if (!varobj_editable_p (var)) - error (_("mi_cmd_var_assign: Variable object is not editable")); + error (_("-var-assign: Variable object is not editable")); expression = xstrdup (argv[1]); if (!varobj_set_value (var, expression)) - error (_("mi_cmd_var_assign: Could not assign expression to variable object")); + error (_("-var-assign: Could not assign " + "expression to variable object")); val = varobj_get_value (var); ui_out_field_string (uiout, "value", val); @@ -667,7 +672,7 @@ mi_cmd_var_update (char *command, char **argv, int argc) enum print_values print_values; if (argc != 1 && argc != 2) - error (_("mi_cmd_var_update: Usage: [PRINT_VALUES] NAME.")); + error (_("-var-update: Usage: [PRINT_VALUES] NAME.")); if (argc == 1) name = argv[0]; @@ -793,7 +798,8 @@ varobj_update_one (struct varobj *var, enum print_values print_values, { struct cleanup *cleanup_child; - cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + cleanup_child + = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); print_varobj (child, print_values, 1 /* print_expression */); do_cleanups (cleanup_child); } @@ -813,7 +819,7 @@ void mi_cmd_enable_pretty_printing (char *command, char **argv, int argc) { if (argc != 0) - error (_("mi_cmd_enable_pretty_printing: no arguments allowed")); + error (_("-enable-pretty-printing: no arguments allowed")); varobj_enable_pretty_printing (); } @@ -824,7 +830,7 @@ mi_cmd_var_set_update_range (char *command, char **argv, int argc) int from, to; if (argc != 3) - error (_("mi_cmd_var_set_update_range: Usage: VAROBJ FROM TO")); + error (_("-var-set-update-range: Usage: VAROBJ FROM TO")); var = varobj_get_handle (argv[0]); from = atoi (argv[1]); diff --git a/contrib/gdb-7/gdb/mi/mi-cmds.c b/contrib/gdb-7/gdb/mi/mi-cmds.c index 8441e178b4..0b32db0c9a 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmds.c +++ b/contrib/gdb-7/gdb/mi/mi-cmds.c @@ -1,6 +1,6 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -47,12 +47,17 @@ struct mi_cmd mi_cmds[] = { "break-watch", { NULL, 0 }, mi_cmd_break_watch}, { "data-disassemble", { NULL, 0 }, mi_cmd_disassemble}, { "data-evaluate-expression", { NULL, 0 }, mi_cmd_data_evaluate_expression}, - { "data-list-changed-registers", { NULL, 0 }, mi_cmd_data_list_changed_registers}, + { "data-list-changed-registers", { NULL, 0 }, + mi_cmd_data_list_changed_registers}, { "data-list-register-names", { NULL, 0 }, mi_cmd_data_list_register_names}, - { "data-list-register-values", { NULL, 0 }, mi_cmd_data_list_register_values}, + { "data-list-register-values", { NULL, 0 }, + mi_cmd_data_list_register_values}, { "data-read-memory", { NULL, 0 }, mi_cmd_data_read_memory}, + { "data-read-memory-bytes", { NULL, 0 }, mi_cmd_data_read_memory_bytes}, { "data-write-memory", { NULL, 0 }, mi_cmd_data_write_memory}, - { "data-write-register-values", { NULL, 0 }, mi_cmd_data_write_register_values}, + { "data-write-memory-bytes", {NULL, 0}, mi_cmd_data_write_memory_bytes}, + { "data-write-register-values", { NULL, 0 }, + mi_cmd_data_write_register_values}, { "enable-timings", { NULL, 0 }, mi_cmd_enable_timings}, { "enable-pretty-printing", { NULL, 0 }, mi_cmd_enable_pretty_printing}, { "environment-cd", { NULL, 0 }, mi_cmd_env_cd}, @@ -73,8 +78,10 @@ struct mi_cmd mi_cmds[] = { "exec-until", { "until", 1 }, NULL}, { "file-exec-and-symbols", { "file", 1 }, NULL }, { "file-exec-file", { "exec-file", 1 }, NULL }, - { "file-list-exec-source-file", { NULL, 0 }, mi_cmd_file_list_exec_source_file}, - { "file-list-exec-source-files", { NULL, 0 }, mi_cmd_file_list_exec_source_files }, + { "file-list-exec-source-file", { NULL, 0 }, + mi_cmd_file_list_exec_source_file}, + { "file-list-exec-source-files", { NULL, 0 }, + mi_cmd_file_list_exec_source_files }, { "file-symbol-file", { "symbol-file", 1 }, NULL }, { "gdb-exit", { NULL, 0 }, mi_cmd_gdb_exit}, { "gdb-set", { "set", 1 }, NULL }, diff --git a/contrib/gdb-7/gdb/mi/mi-cmds.h b/contrib/gdb-7/gdb/mi/mi-cmds.h index 5954aef182..18b4ad7d3b 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmds.h +++ b/contrib/gdb-7/gdb/mi/mi-cmds.h @@ -1,6 +1,6 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2000, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -47,7 +47,9 @@ extern mi_cmd_argv_ftype mi_cmd_data_list_register_names; extern mi_cmd_argv_ftype mi_cmd_data_list_register_values; extern mi_cmd_argv_ftype mi_cmd_data_list_changed_registers; extern mi_cmd_argv_ftype mi_cmd_data_read_memory; +extern mi_cmd_argv_ftype mi_cmd_data_read_memory_bytes; extern mi_cmd_argv_ftype mi_cmd_data_write_memory; +extern mi_cmd_argv_ftype mi_cmd_data_write_memory_bytes; extern mi_cmd_argv_ftype mi_cmd_data_write_register_values; extern mi_cmd_argv_ftype mi_cmd_enable_timings; extern mi_cmd_argv_ftype mi_cmd_env_cd; diff --git a/contrib/gdb-7/gdb/mi/mi-common.c b/contrib/gdb-7/gdb/mi/mi-common.c index 68d66d3265..ab126f6b85 100644 --- a/contrib/gdb-7/gdb/mi/mi-common.c +++ b/contrib/gdb-7/gdb/mi/mi-common.c @@ -1,5 +1,6 @@ /* Interface for common GDB/MI data - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-common.h b/contrib/gdb-7/gdb/mi/mi-common.h index f9b40503c6..e3aab7d785 100644 --- a/contrib/gdb-7/gdb/mi/mi-common.h +++ b/contrib/gdb-7/gdb/mi/mi-common.h @@ -1,5 +1,6 @@ /* Interface for common GDB/MI data - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -19,8 +20,9 @@ #ifndef MI_COMMON_H #define MI_COMMON_H -/* Represents the reason why GDB is sending an asynchronous command to the - front end. NOTE: When modifing this, don't forget to update gdb.texinfo! */ +/* Represents the reason why GDB is sending an asynchronous command to + the front end. NOTE: When modifing this, don't forget to update + gdb.texinfo! */ enum async_reply_reason { EXEC_ASYNC_BREAKPOINT_HIT = 0, diff --git a/contrib/gdb-7/gdb/mi/mi-console.c b/contrib/gdb-7/gdb/mi/mi-console.c index eb5d0749d0..df64b6cc4e 100644 --- a/contrib/gdb-7/gdb/mi/mi-console.c +++ b/contrib/gdb-7/gdb/mi/mi-console.c @@ -1,6 +1,6 @@ /* MI Console code. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -104,7 +104,8 @@ mi_console_raw_packet (void *data, if (mi_console->quote) { fputs_unfiltered ("\"", mi_console->raw); - fputstrn_unfiltered (buf, length_buf, mi_console->quote, mi_console->raw); + fputstrn_unfiltered (buf, length_buf, + mi_console->quote, mi_console->raw); fputs_unfiltered ("\"\n", mi_console->raw); } else diff --git a/contrib/gdb-7/gdb/mi/mi-console.h b/contrib/gdb-7/gdb/mi/mi-console.h index ea14722113..f5dfadcdc4 100644 --- a/contrib/gdb-7/gdb/mi/mi-console.h +++ b/contrib/gdb-7/gdb/mi/mi-console.h @@ -1,5 +1,6 @@ /* MI Command Set - MI Console. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-getopt.c b/contrib/gdb-7/gdb/mi/mi-getopt.c index 19a318acf7..81b833a30b 100644 --- a/contrib/gdb-7/gdb/mi/mi-getopt.c +++ b/contrib/gdb-7/gdb/mi/mi-getopt.c @@ -1,5 +1,5 @@ /* MI Command Set - MI Option Parser. - Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). diff --git a/contrib/gdb-7/gdb/mi/mi-getopt.h b/contrib/gdb-7/gdb/mi/mi-getopt.h index 32fa8a6b01..a34a354e45 100644 --- a/contrib/gdb-7/gdb/mi/mi-getopt.h +++ b/contrib/gdb-7/gdb/mi/mi-getopt.h @@ -1,5 +1,6 @@ /* MI Option Parser. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-interp.c b/contrib/gdb-7/gdb/mi/mi-interp.c index f18406bb37..5e01abc7a1 100644 --- a/contrib/gdb-7/gdb/mi/mi-interp.c +++ b/contrib/gdb-7/gdb/mi/mi-interp.c @@ -1,6 +1,6 @@ /* MI Interpreter Definitions and Commands for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -192,14 +192,17 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc) struct cleanup *old_chain; if (argc < 2) - error ("mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command"); + error (_("-interpreter-exec: " + "Usage: -interpreter-exec interp command")); interp_to_use = interp_lookup (argv[0]); if (interp_to_use == NULL) - error ("mi_cmd_interpreter_exec: could not find interpreter \"%s\"", argv[0]); + error (_("-interpreter-exec: could not find interpreter \"%s\""), + argv[0]); if (!interp_exec_p (interp_to_use)) - error ("mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution", + error (_("-interpreter-exec: interpreter \"%s\" " + "does not support command execution"), argv[0]); /* Insert the MI out hooks, making sure to also call the interpreter's hooks @@ -231,11 +234,12 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc) } /* - * mi_insert_notify_hooks - This inserts a number of hooks that are meant to produce - * async-notify ("=") MI messages while running commands in another interpreter - * using mi_interpreter_exec. The canonical use for this is to allow access to - * the gdb CLI interpreter from within the MI, while still producing MI style output - * when actions in the CLI command change gdb's state. + * mi_insert_notify_hooks - This inserts a number of hooks that are + * meant to produce async-notify ("=") MI messages while running + * commands in another interpreter using mi_interpreter_exec. The + * canonical use for this is to allow access to the gdb CLI + * interpreter from within the MI, while still producing MI style + * output when actions in the CLI command change gdb's state. */ static void @@ -355,8 +359,14 @@ mi_inferior_exit (struct inferior *inf) struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); - fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"i%d\"", - inf->num); + if (inf->has_exit_code) + fprintf_unfiltered (mi->event_channel, + "thread-group-exited,id=\"i%d\",exit-code=\"%s\"", + inf->num, int_string (inf->exit_code, 8, 0, 0, 1)); + else + fprintf_unfiltered (mi->event_channel, + "thread-group-exited,id=\"i%d\"", inf->num); + gdb_flush (mi->event_channel); } @@ -434,7 +444,7 @@ mi_about_to_proceed (void) { struct thread_info *tp = inferior_thread (); - if (tp->in_infcall) + if (tp->control.in_infcall) return; } @@ -477,7 +487,7 @@ mi_on_resume (ptid_t ptid) tp = find_thread_ptid (ptid); /* Suppress output while calling an inferior function. */ - if (tp->in_infcall) + if (tp->control.in_infcall) return; /* To cater for older frontends, emit ^running, but do it only once diff --git a/contrib/gdb-7/gdb/mi/mi-main.c b/contrib/gdb-7/gdb/mi/mi-main.c index b9964753b6..ef6bfc3013 100644 --- a/contrib/gdb-7/gdb/mi/mi-main.c +++ b/contrib/gdb-7/gdb/mi/mi-main.c @@ -1,7 +1,7 @@ /* MI Command Set. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -96,7 +96,7 @@ static void mi_cmd_execute (struct mi_parse *parse); static void mi_execute_cli_command (const char *cmd, int args_p, const char *args); static void mi_execute_async_cli_command (char *cli_command, - char **argv, int argc); + char **argv, int argc); static int register_changed_p (int regnum, struct regcache *, struct regcache *); static void get_register (struct frame_info *, int regnum, int format); @@ -240,7 +240,9 @@ exec_continue (char **argv, int argc) if (!current_context->all) { - struct inferior *inf = find_inferior_id (current_context->thread_group); + struct inferior *inf + = find_inferior_id (current_context->thread_group); + pid = inf->pid; } iterate_over_threads (proceed_thread_callback, &pid); @@ -418,19 +420,40 @@ void mi_cmd_target_detach (char *command, char **argv, int argc) { if (argc != 0 && argc != 1) - error ("Usage: -target-detach [thread-group]"); + error (_("Usage: -target-detach [pid | thread-group]")); if (argc == 1) { struct thread_info *tp; char *end = argv[0]; - int pid = strtol (argv[0], &end, 10); + int pid; - if (*end != '\0') - error (_("Cannot parse thread group id '%s'"), argv[0]); + /* First see if we are dealing with a thread-group id. */ + if (*argv[0] == 'i') + { + struct inferior *inf; + int id = strtoul (argv[0] + 1, &end, 0); + + if (*end != '\0') + error (_("Invalid syntax of thread-group id '%s'"), argv[0]); + + inf = find_inferior_id (id); + if (!inf) + error (_("Non-existent thread-group id '%d'"), id); + + pid = inf->pid; + } + else + { + /* We must be dealing with a pid. */ + pid = strtol (argv[0], &end, 10); + + if (*end != '\0') + error (_("Invalid identifier '%s'"), argv[0]); + } /* Pick any thread in the desired process. Current - target_detach deteches from the parent of inferior_ptid. */ + target_detach detaches from the parent of inferior_ptid. */ tp = iterate_over_threads (find_thread_of_process, &pid); if (!tp) error (_("Thread group is empty")); @@ -448,7 +471,7 @@ mi_cmd_thread_select (char *command, char **argv, int argc) char *mi_error_message; if (argc != 1) - error ("mi_cmd_thread_select: USAGE: threadnum."); + error (_("-thread-select: USAGE: threadnum.")); rc = gdb_thread_select (uiout, argv[0], &mi_error_message); @@ -466,7 +489,7 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) char *mi_error_message; if (argc != 0) - error ("mi_cmd_thread_list_ids: No arguments required."); + error (_("-thread-list-ids: No arguments required.")); rc = gdb_list_thread_ids (uiout, &mi_error_message); @@ -480,15 +503,10 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) void mi_cmd_thread_info (char *command, char **argv, int argc) { - int thread = -1; - if (argc != 0 && argc != 1) - error ("Invalid MI command"); + error (_("Invalid MI command")); - if (argc == 1) - thread = atoi (argv[0]); - - print_thread_info (uiout, thread, -1); + print_thread_info (uiout, argv[0], -1); } struct collect_cores_data @@ -584,7 +602,7 @@ print_one_inferior (struct inferior *inferior, void *xdata) } if (top_data->recurse) - print_thread_info (uiout, -1, inferior->pid); + print_thread_info (uiout, NULL, inferior->pid); do_cleanups (back_to); } @@ -809,7 +827,8 @@ mi_cmd_list_thread_groups (char *command, char **argv, int argc) else if (strcmp (optarg, "1") == 0) recurse = 1; else - error ("only '0' and '1' are valid values for the '--recurse' option"); + error (_("only '0' and '1' are valid values " + "for the '--recurse' option")); break; } } @@ -820,12 +839,12 @@ mi_cmd_list_thread_groups (char *command, char **argv, int argc) int inf; if (*(argv[optind]) != 'i') - error ("invalid syntax of group id '%s'", argv[optind]); + error (_("invalid syntax of group id '%s'"), argv[optind]); inf = strtoul (argv[optind] + 1, &end, 0); if (*end != '\0') - error ("invalid syntax of group id '%s'", argv[optind]); + error (_("invalid syntax of group id '%s'"), argv[optind]); VEC_safe_push (int, ids, inf); } if (VEC_length (int, ids) > 1) @@ -846,9 +865,9 @@ mi_cmd_list_thread_groups (char *command, char **argv, int argc) struct inferior *inf = find_inferior_id (id); if (!inf) - error ("Non-existent thread group id '%d'", id); + error (_("Non-existent thread group id '%d'"), id); - print_thread_info (uiout, -1, inf->pid); + print_thread_info (uiout, NULL, inf->pid); } else { @@ -908,7 +927,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) { regnum = atoi (argv[i]); if (regnum < 0 || regnum >= numregs) - error ("bad register number"); + error (_("bad register number")); if (gdbarch_register_name (gdbarch, regnum) == NULL || *(gdbarch_register_name (gdbarch, regnum)) == '\0') @@ -960,7 +979,8 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) continue; changed = register_changed_p (regnum, prev_regs, this_regs); if (changed < 0) - error ("mi_cmd_data_list_changed_registers: Unable to read register contents."); + error (_("-data-list-changed-registers: " + "Unable to read register contents.")); else if (changed) ui_out_field_int (uiout, NULL, regnum); } @@ -978,12 +998,13 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) { changed = register_changed_p (regnum, prev_regs, this_regs); if (changed < 0) - error ("mi_cmd_data_list_register_change: Unable to read register contents."); + error (_("-data-list-changed-registers: " + "Unable to read register contents.")); else if (changed) ui_out_field_int (uiout, NULL, regnum); } else - error ("bad register number"); + error (_("bad register number")); } do_cleanups (cleanup); } @@ -995,23 +1016,25 @@ register_changed_p (int regnum, struct regcache *prev_regs, struct gdbarch *gdbarch = get_regcache_arch (this_regs); gdb_byte prev_buffer[MAX_REGISTER_SIZE]; gdb_byte this_buffer[MAX_REGISTER_SIZE]; + enum register_status prev_status; + enum register_status this_status; - /* Registers not valid in this frame return count as unchanged. */ - if (!regcache_valid_p (this_regs, regnum)) - return 0; - - /* First time through or after gdbarch change consider all registers as - changed. Same for registers not valid in the previous frame. */ - if (!prev_regs || get_regcache_arch (prev_regs) != gdbarch - || !regcache_valid_p (prev_regs, regnum)) + /* First time through or after gdbarch change consider all registers + as changed. */ + if (!prev_regs || get_regcache_arch (prev_regs) != gdbarch) return 1; /* Get register contents and compare. */ - regcache_cooked_read (prev_regs, regnum, prev_buffer); - regcache_cooked_read (this_regs, regnum, this_buffer); + prev_status = regcache_cooked_read (prev_regs, regnum, prev_buffer); + this_status = regcache_cooked_read (this_regs, regnum, this_buffer); - return memcmp (prev_buffer, this_buffer, - register_size (gdbarch, regnum)) != 0; + if (this_status != prev_status) + return 1; + else if (this_status == REG_VALID) + return memcmp (prev_buffer, this_buffer, + register_size (gdbarch, regnum)) != 0; + else + return 0; } /* Return a list of register number and value pairs. The valid @@ -1037,7 +1060,8 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) upon the particular processor being debugged. */ if (argc == 0) - error ("mi_cmd_data_list_register_values: Usage: -data-list-register-values [...]"); + error (_("-data-list-register-values: Usage: " + "-data-list-register-values [...]")); format = (int) argv[0][0]; @@ -1079,7 +1103,7 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) do_cleanups (tuple_cleanup); } else - error ("bad register number"); + error (_("bad register number")); } do_cleanups (list_cleanup); } @@ -1089,27 +1113,26 @@ static void get_register (struct frame_info *frame, int regnum, int format) { struct gdbarch *gdbarch = get_frame_arch (frame); - gdb_byte buffer[MAX_REGISTER_SIZE]; - int optim; - int realnum; CORE_ADDR addr; enum lval_type lval; static struct ui_stream *stb = NULL; + struct value *val; stb = ui_out_stream_new (uiout); if (format == 'N') format = 0; - frame_register (frame, regnum, &optim, &lval, &addr, &realnum, buffer); + val = get_frame_register_value (frame, regnum); - if (optim) - error ("Optimized out"); + if (value_optimized_out (val)) + error (_("Optimized out")); if (format == 'r') { int j; char *ptr, buf[1024]; + const gdb_byte *valaddr = value_contents_for_printing (val); strcpy (buf, "0x"); ptr = buf + 2; @@ -1118,7 +1141,7 @@ get_register (struct frame_info *frame, int regnum, int format) int idx = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? j : register_size (gdbarch, regnum) - 1 - j; - sprintf (ptr, "%02x", (unsigned char) buffer[idx]); + sprintf (ptr, "%02x", (unsigned char) valaddr[idx]); ptr += 2; } ui_out_field_string (uiout, "value", buf); @@ -1130,8 +1153,10 @@ get_register (struct frame_info *frame, int regnum, int format) get_formatted_print_options (&opts, format); opts.deref_ref = 1; - val_print (register_type (gdbarch, regnum), buffer, 0, 0, - stb->stream, 0, NULL, &opts, current_language); + val_print (value_type (val), + value_contents_for_printing (val), + value_embedded_offset (val), 0, + stb->stream, 0, val, &opts, current_language); ui_out_field_stream (uiout, "value", stb); ui_out_stream_delete (stb); } @@ -1139,7 +1164,8 @@ get_register (struct frame_info *frame, int regnum, int format) /* Write given values into registers. The registers and values are given as pairs. The corresponding MI command is - -data-write-register-values [ ... ]*/ + -data-write-register-values + [ ... ] */ void mi_cmd_data_write_register_values (char *command, char **argv, int argc) { @@ -1159,18 +1185,20 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); if (argc == 0) - error ("mi_cmd_data_write_register_values: Usage: -data-write-register-values [ ... ]"); + error (_("-data-write-register-values: Usage: -data-write-register-" + "values [ ... ]")); format = (int) argv[0][0]; if (!target_has_registers) - error ("mi_cmd_data_write_register_values: No registers."); + error (_("-data-write-register-values: No registers.")); if (!(argc - 1)) - error ("mi_cmd_data_write_register_values: No regs and values specified."); + error (_("-data-write-register-values: No regs and values specified.")); if ((argc - 1) % 2) - error ("mi_cmd_data_write_register_values: Regs and vals are not in pairs."); + error (_("-data-write-register-values: " + "Regs and vals are not in pairs.")); for (i = 1; i < argc; i = i + 2) { @@ -1189,7 +1217,7 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) regcache_cooked_write_signed (regcache, regnum, value); } else - error ("bad register number"); + error (_("bad register number")); } } @@ -1210,7 +1238,8 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) if (argc != 1) { ui_out_stream_delete (stb); - error ("mi_cmd_data_evaluate_expression: Usage: -data-evaluate-expression expression"); + error (_("-data-evaluate-expression: " + "Usage: -data-evaluate-expression expression")); } expr = parse_expression (argv[0]); @@ -1280,7 +1309,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) while (1) { - int opt = mi_getopt ("mi_cmd_data_read_memory", argc, argv, opts, + int opt = mi_getopt ("-data-read-memory", argc, argv, opts, &optind, &optarg); if (opt < 0) @@ -1296,7 +1325,8 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) argc -= optind; if (argc < 5 || argc > 6) - error ("mi_cmd_data_read_memory: Usage: ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR]."); + error (_("-data-read-memory: Usage: " + "ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR].")); /* Extract all the arguments. */ @@ -1332,12 +1362,12 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) /* The number of rows. */ nr_rows = atol (argv[3]); if (nr_rows <= 0) - error ("mi_cmd_data_read_memory: invalid number of rows."); + error (_("-data-read-memory: invalid number of rows.")); /* Number of bytes per row. */ nr_cols = atol (argv[4]); if (nr_cols <= 0) - error ("mi_cmd_data_read_memory: invalid number of columns."); + error (_("-data-read-memory: invalid number of columns.")); /* The un-printable character when printing ascii. */ if (argc == 6) @@ -1352,11 +1382,11 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) /* Dispatch memory reads to the topmost target, not the flattened current_target. */ - nr_bytes = target_read_until_error (current_target.beneath, - TARGET_OBJECT_MEMORY, NULL, mbuf, - addr, total_bytes); + nr_bytes = target_read (current_target.beneath, + TARGET_OBJECT_MEMORY, NULL, mbuf, + addr, total_bytes); if (nr_bytes <= 0) - error ("Unable to read memory."); + error (_("Unable to read memory.")); /* Output the header information. */ ui_out_field_core_addr (uiout, "addr", gdbarch, addr); @@ -1389,7 +1419,8 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_core_addr (uiout, "addr", gdbarch, addr + row_byte); - /* ui_out_field_core_addr_symbolic (uiout, "saddr", addr + row_byte); */ + /* ui_out_field_core_addr_symbolic (uiout, "saddr", addr + + row_byte); */ cleanup_list_data = make_cleanup_ui_out_list_begin_end (uiout, "data"); get_formatted_print_options (&opts, word_format); for (col = 0, col_byte = row_byte; @@ -1414,7 +1445,8 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) int byte; ui_file_rewind (stream->stream); - for (byte = row_byte; byte < row_byte + word_size * nr_cols; byte++) + for (byte = row_byte; + byte < row_byte + word_size * nr_cols; byte++) { if (byte >= nr_bytes) { @@ -1437,6 +1469,88 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) do_cleanups (cleanups); } +void +mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc) +{ + struct gdbarch *gdbarch = get_current_arch (); + struct cleanup *cleanups; + CORE_ADDR addr; + LONGEST length; + memory_read_result_s *read_result; + int ix; + VEC(memory_read_result_s) *result; + long offset = 0; + int optind = 0; + char *optarg; + enum opt + { + OFFSET_OPT + }; + static struct mi_opt opts[] = + { + {"o", OFFSET_OPT, 1}, + { 0, 0, 0 } + }; + + while (1) + { + int opt = mi_getopt ("-data-read-memory-bytes", argc, argv, opts, + &optind, &optarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case OFFSET_OPT: + offset = atol (optarg); + break; + } + } + argv += optind; + argc -= optind; + + if (argc != 2) + error (_("Usage: [ -o OFFSET ] ADDR LENGTH.")); + + addr = parse_and_eval_address (argv[0]) + offset; + length = atol (argv[1]); + + result = read_memory_robust (current_target.beneath, addr, length); + + cleanups = make_cleanup (free_memory_read_result_vector, result); + + if (VEC_length (memory_read_result_s, result) == 0) + error (_("Unable to read memory.")); + + make_cleanup_ui_out_list_begin_end (uiout, "memory"); + for (ix = 0; + VEC_iterate (memory_read_result_s, result, ix, read_result); + ++ix) + { + struct cleanup *t = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + char *data, *p; + int i; + + ui_out_field_core_addr (uiout, "begin", gdbarch, read_result->begin); + ui_out_field_core_addr (uiout, "offset", gdbarch, read_result->begin + - addr); + ui_out_field_core_addr (uiout, "end", gdbarch, read_result->end); + + data = xmalloc ((read_result->end - read_result->begin) * 2 + 1); + + for (i = 0, p = data; + i < (read_result->end - read_result->begin); + ++i, p += 2) + { + sprintf (p, "%02x", read_result->data[i]); + } + ui_out_field_string (uiout, "contents", data); + xfree (data); + do_cleanups (t); + } + do_cleanups (cleanups); +} + + /* DATA-MEMORY-WRITE: COLUMN_OFFSET: optional argument. Must be preceeded by '-o'. The @@ -1481,7 +1595,7 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) while (1) { - int opt = mi_getopt ("mi_cmd_data_write_memory", argc, argv, opts, + int opt = mi_getopt ("-data-write-memory", argc, argv, opts, &optind, &optarg); if (opt < 0) @@ -1497,7 +1611,8 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) argc -= optind; if (argc != 4) - error ("mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE."); + error (_("-data-write-memory: Usage: " + "[-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE.")); /* Extract all the arguments. */ /* Start address of the memory dump. */ @@ -1523,6 +1638,44 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) do_cleanups (old_chain); } +/* DATA-MEMORY-WRITE-RAW: + + ADDR: start address + DATA: string of bytes to write at that address. */ +void +mi_cmd_data_write_memory_bytes (char *command, char **argv, int argc) +{ + CORE_ADDR addr; + char *cdata; + gdb_byte *data; + int len, r, i; + struct cleanup *back_to; + + if (argc != 2) + error (_("Usage: ADDR DATA.")); + + addr = parse_and_eval_address (argv[0]); + cdata = argv[1]; + len = strlen (cdata)/2; + + data = xmalloc (len); + back_to = make_cleanup (xfree, data); + + for (i = 0; i < len; ++i) + { + int x; + sscanf (cdata + i * 2, "%02x", &x); + data[i] = (gdb_byte)x; + } + + r = target_write_memory (addr, data, len); + if (r != 0) + error (_("Could not write memory")); + + do_cleanups (back_to); +} + + void mi_cmd_enable_timings (char *command, char **argv, int argc) { @@ -1543,7 +1696,7 @@ mi_cmd_enable_timings (char *command, char **argv, int argc) return; usage_error: - error ("mi_cmd_enable_timings: Usage: %s {yes|no}", command); + error (_("-enable-timings: Usage: %s {yes|no}"), command); } void @@ -1557,6 +1710,7 @@ mi_cmd_list_features (char *command, char **argv, int argc) ui_out_field_string (uiout, NULL, "frozen-varobjs"); ui_out_field_string (uiout, NULL, "pending-breakpoints"); ui_out_field_string (uiout, NULL, "thread-info"); + ui_out_field_string (uiout, NULL, "data-read-memory-bytes"); #if HAVE_PYTHON ui_out_field_string (uiout, NULL, "python"); @@ -1566,7 +1720,7 @@ mi_cmd_list_features (char *command, char **argv, int argc) return; } - error ("-list-features should be passed no arguments"); + error (_("-list-features should be passed no arguments")); } void @@ -1586,7 +1740,7 @@ mi_cmd_list_target_features (char *command, char **argv, int argc) return; } - error ("-list-target-features should be passed no arguments"); + error (_("-list-target-features should be passed no arguments")); } void @@ -1602,6 +1756,18 @@ mi_cmd_add_inferior (char *command, char **argv, int argc) ui_out_field_fmt (uiout, "inferior", "i%d", inf->num); } +/* Callback used to find the first inferior other than the + current one. */ + +static int +get_other_inferior (struct inferior *inf, void *arg) +{ + if (inf == current_inferior ()) + return 0; + + return 1; +} + void mi_cmd_remove_inferior (char *command, char **argv, int argc) { @@ -1609,14 +1775,33 @@ mi_cmd_remove_inferior (char *command, char **argv, int argc) struct inferior *inf; if (argc != 1) - error ("-remove-inferior should be passed a single argument"); + error (_("-remove-inferior should be passed a single argument")); if (sscanf (argv[0], "i%d", &id) != 1) - error ("the thread group id is syntactically invalid"); + error (_("the thread group id is syntactically invalid")); inf = find_inferior_id (id); if (!inf) - error ("the specified thread group does not exist"); + error (_("the specified thread group does not exist")); + + if (inf->pid != 0) + error (_("cannot remove an active inferior")); + + if (inf == current_inferior ()) + { + struct thread_info *tp = 0; + struct inferior *new_inferior + = iterate_over_inferiors (get_other_inferior, NULL); + + if (new_inferior == NULL) + error (_("Cannot remove last inferior")); + + set_current_inferior (new_inferior); + if (new_inferior->pid != 0) + tp = any_thread_of_process (new_inferior->pid); + switch_to_thread (tp ? tp->ptid : null_ptid); + set_current_program_space (new_inferior->pspace); + } delete_inferior_1 (inf, 1 /* silent */); } @@ -1723,11 +1908,26 @@ captured_mi_execute_command (struct ui_out *uiout, void *data) return; } +/* Print a gdb exception to the MI output stream. */ + +static void +mi_print_exception (const char *token, struct gdb_exception exception) +{ + fputs_unfiltered (token, raw_stdout); + fputs_unfiltered ("^error,msg=\"", raw_stdout); + if (exception.message == NULL) + fputs_unfiltered ("unknown error", raw_stdout); + else + fputstr_unfiltered (exception.message, '"', raw_stdout); + fputs_unfiltered ("\"\n", raw_stdout); +} void mi_execute_command (char *cmd, int from_tty) { - struct mi_parse *command; + char *token; + struct mi_parse *command = NULL; + volatile struct gdb_exception exception; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ @@ -1736,13 +1936,22 @@ mi_execute_command (char *cmd, int from_tty) target_log_command (cmd); - command = mi_parse (cmd); - - if (command != NULL) + TRY_CATCH (exception, RETURN_MASK_ALL) + { + command = mi_parse (cmd, &token); + } + if (exception.reason < 0) + { + mi_print_exception (token, exception); + xfree (token); + } + else { struct gdb_exception result; ptid_t previous_ptid = inferior_ptid; + command->token = token; + if (do_timings) { command->cmd_start = (struct mi_timestamp *) @@ -1756,13 +1965,7 @@ mi_execute_command (char *cmd, int from_tty) { /* The command execution failed and error() was called somewhere. */ - fputs_unfiltered (command->token, raw_stdout); - fputs_unfiltered ("^error,msg=\"", raw_stdout); - if (result.message == NULL) - fputs_unfiltered ("unknown error", raw_stdout); - else - fputstr_unfiltered (result.message, '"', raw_stdout); - fputs_unfiltered ("\"\n", raw_stdout); + mi_print_exception (command->token, result); mi_out_rewind (uiout); } diff --git a/contrib/gdb-7/gdb/mi/mi-main.h b/contrib/gdb-7/gdb/mi/mi-main.h index da1dfc0593..3ad6d0f5a8 100644 --- a/contrib/gdb-7/gdb/mi/mi-main.h +++ b/contrib/gdb-7/gdb/mi/mi-main.h @@ -1,6 +1,7 @@ /* MI Internal Functions for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-out.c b/contrib/gdb-7/gdb/mi/mi-out.c index 2b6b4a5713..9aaeec6654 100644 --- a/contrib/gdb-7/gdb/mi/mi-out.c +++ b/contrib/gdb-7/gdb/mi/mi-out.c @@ -1,6 +1,6 @@ /* MI Command Set - output generating routines. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). diff --git a/contrib/gdb-7/gdb/mi/mi-out.h b/contrib/gdb-7/gdb/mi/mi-out.h index a33741bfc2..515aefa764 100644 --- a/contrib/gdb-7/gdb/mi/mi-out.h +++ b/contrib/gdb-7/gdb/mi/mi-out.h @@ -1,5 +1,6 @@ /* MI Command Set - MI output generating routines for GDB. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-parse.c b/contrib/gdb-7/gdb/mi/mi-parse.c index a5a4e75b52..fcaf151242 100644 --- a/contrib/gdb-7/gdb/mi/mi-parse.c +++ b/contrib/gdb-7/gdb/mi/mi-parse.c @@ -1,6 +1,6 @@ /* MI Command Set - MI parser. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -223,12 +223,20 @@ mi_parse_free (struct mi_parse *parse) xfree (parse); } +/* A cleanup that calls mi_parse_free. */ + +static void +mi_parse_cleanup (void *arg) +{ + mi_parse_free (arg); +} struct mi_parse * -mi_parse (char *cmd) +mi_parse (char *cmd, char **token) { char *chp; struct mi_parse *parse = XMALLOC (struct mi_parse); + struct cleanup *cleanup; memset (parse, 0, sizeof (*parse)); parse->all = 0; @@ -236,6 +244,8 @@ mi_parse (char *cmd) parse->thread = -1; parse->frame = -1; + cleanup = make_cleanup (mi_parse_cleanup, parse); + /* Before starting, skip leading white space. */ while (isspace (*cmd)) cmd++; @@ -243,9 +253,9 @@ mi_parse (char *cmd) /* Find/skip any token and then extract it. */ for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++) ; - parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *)); - memcpy (parse->token, cmd, (chp - cmd)); - parse->token[chp - cmd] = '\0'; + *token = xmalloc ((chp - cmd + 1) * sizeof (char *)); + memcpy (*token, cmd, (chp - cmd)); + (*token)[chp - cmd] = '\0'; /* This wasn't a real MI command. Return it as a CLI_COMMAND. */ if (*chp != '-') @@ -254,6 +264,9 @@ mi_parse (char *cmd) chp++; parse->command = xstrdup (chp); parse->op = CLI_COMMAND; + + discard_cleanups (cleanup); + return parse; } @@ -271,15 +284,7 @@ mi_parse (char *cmd) /* Find the command in the MI table. */ parse->cmd = mi_lookup (parse->command); if (parse->cmd == NULL) - { - /* FIXME: This should be a function call. */ - fprintf_unfiltered - (raw_stdout, - "%s^error,msg=\"Undefined MI command: %s\"\n", - parse->token, parse->command); - mi_parse_free (parse); - return NULL; - } + error (_("Undefined MI command: %s"), parse->command); /* Skip white space following the command. */ while (isspace (*chp)) @@ -292,7 +297,7 @@ mi_parse (char *cmd) to CLI. */ for (;;) { - char *start = chp; + const char *option; size_t as = sizeof ("--all ") - 1; size_t tgs = sizeof ("--thread-group ") - 1; size_t ts = sizeof ("--thread ") - 1; @@ -311,6 +316,7 @@ mi_parse (char *cmd) } if (strncmp (chp, "--thread-group ", tgs) == 0) { + option = "--thread-group"; if (parse->thread_group != -1) error (_("Duplicate '--thread-group' option")); chp += tgs; @@ -319,8 +325,9 @@ mi_parse (char *cmd) chp += 1; parse->thread_group = strtol (chp, &chp, 10); } - if (strncmp (chp, "--thread ", ts) == 0) + else if (strncmp (chp, "--thread ", ts) == 0) { + option = "--thread"; if (parse->thread != -1) error (_("Duplicate '--thread' option")); chp += ts; @@ -328,6 +335,7 @@ mi_parse (char *cmd) } else if (strncmp (chp, "--frame ", fs) == 0) { + option = "--frame"; if (parse->frame != -1) error (_("Duplicate '--frame' option")); chp += fs; @@ -337,8 +345,7 @@ mi_parse (char *cmd) break; if (*chp != '\0' && !isspace (*chp)) - error (_("Invalid value for the '%s' option"), - start[2] == 't' ? "--thread" : "--frame"); + error (_("Invalid value for the '%s' option"), option); while (isspace (*chp)) chp++; } @@ -349,15 +356,7 @@ mi_parse (char *cmd) { mi_parse_argv (chp, parse); if (parse->argv == NULL) - { - /* FIXME: This should be a function call. */ - fprintf_unfiltered - (raw_stdout, - "%s^error,msg=\"Problem parsing arguments: %s %s\"\n", - parse->token, parse->command, chp); - mi_parse_free (parse); - return NULL; - } + error (_("Problem parsing arguments: %s %s"), parse->command, chp); } /* FIXME: DELETE THIS */ @@ -366,6 +365,8 @@ mi_parse (char *cmd) if (parse->cmd->cli.cmd != NULL) parse->args = xstrdup (chp); + discard_cleanups (cleanup); + /* Fully parsed. */ parse->op = MI_COMMAND; return parse; diff --git a/contrib/gdb-7/gdb/mi/mi-parse.h b/contrib/gdb-7/gdb/mi/mi-parse.h index 3c6cd9a31e..91bc5a4115 100644 --- a/contrib/gdb-7/gdb/mi/mi-parse.h +++ b/contrib/gdb-7/gdb/mi/mi-parse.h @@ -1,5 +1,6 @@ /* MI Command Set - MI Command Parser. - Copyright (C) 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -52,13 +53,15 @@ struct mi_parse int frame; }; -/* Attempts to parse CMD returning a ``struct mi_command''. If CMD is - invalid, an error mesage is reported (MI format) and NULL is - returned. For a CLI_COMMAND, COMMAND, TOKEN and OP are initialized. - For an MI_COMMAND COMMAND, TOKEN, ARGS and OP are - initialized. Un-initialized fields are zero. */ +/* Attempts to parse CMD returning a ``struct mi_parse''. If CMD is + invalid, an exception is thrown. For an MI_COMMAND COMMAND, ARGS + and OP are initialized. Un-initialized fields are zero. *TOKEN is + set to the token, even if an exception is thrown. It is allocated + with xmalloc; it must either be freed with xfree, or assigned to + the TOKEN field of the resultant mi_parse object, to be freed by + mi_parse_free. */ -extern struct mi_parse *mi_parse (char *cmd); +extern struct mi_parse *mi_parse (char *cmd, char **token); /* Free a command returned by mi_parse_command. */ diff --git a/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c b/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c index 4fc1acb192..17ff8c361a 100644 --- a/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c +++ b/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c @@ -1,5 +1,6 @@ /* MI Command Set - symbol commands. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -38,13 +39,13 @@ mi_cmd_symbol_list_lines (char *command, char **argv, int argc) struct cleanup *cleanup_stack, *cleanup_tuple; if (argc != 1) - error (_("mi_cmd_symbol_list_lines: Usage: SOURCE_FILENAME")); + error (_("-symbol-list-lines: Usage: SOURCE_FILENAME")); filename = argv[0]; s = lookup_symtab (filename); if (s == NULL) - error (_("mi_cmd_symbol_list_lines: Unknown source file name.")); + error (_("-symbol-list-lines: Unknown source file name.")); /* Now, dump the associated line table. The pc addresses are already sorted by increasing values in the symbol table, so no need to diff --git a/contrib/gdb-7/gdb/minsyms.c b/contrib/gdb-7/gdb/minsyms.c index cb4545c06f..b054e3ff98 100644 --- a/contrib/gdb-7/gdb/minsyms.c +++ b/contrib/gdb-7/gdb/minsyms.c @@ -1,6 +1,7 @@ /* GDB routines for manipulating the minimal symbol tables. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -34,7 +35,7 @@ Even when a file contains enough debugging information to build a full symbol table, these minimal symbols are still useful for quickly mapping between names and addresses, and vice versa. They are also sometimes used - to figure out what full symbol table entries need to be read in. */ + to figure out what full symbol table entries need to be read in. */ #include "defs.h" @@ -42,6 +43,7 @@ #include "gdb_string.h" #include "symtab.h" #include "bfd.h" +#include "filenames.h" #include "symfile.h" #include "objfiles.h" #include "demangle.h" @@ -131,8 +133,8 @@ add_minsym_to_demangled_hash_table (struct minimal_symbol *sym, { if (sym->demangled_hash_next == NULL) { - unsigned int hash - = msymbol_hash_iw (SYMBOL_SEARCH_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE; + unsigned int hash = msymbol_hash_iw (SYMBOL_SEARCH_NAME (sym)) + % MINIMAL_SYMBOL_HASH_SIZE; sym->demangled_hash_next = table[hash]; table[hash] = sym; @@ -197,14 +199,9 @@ lookup_minimal_symbol (const char *name, const char *sfile, const char *modified_name; if (sfile != NULL) - { - char *p = strrchr (sfile, '/'); + sfile = lbasename (sfile); - if (p != NULL) - sfile = p + 1; - } - - /* For C++, canonicalize the input name. */ + /* For C++, canonicalize the input name. */ modified_name = name; if (current_language->la_language == language_cplus) { @@ -259,16 +256,16 @@ lookup_minimal_symbol (const char *name, const char *sfile, case mst_file_data: case mst_file_bss: if (sfile == NULL - || strcmp (msymbol->filename, sfile) == 0) + || filename_cmp (msymbol->filename, sfile) == 0) found_file_symbol = msymbol; break; case mst_solib_trampoline: /* If a trampoline symbol is found, we prefer to - keep looking for the *real* symbol. If the + keep looking for the *real* symbol. If the actual symbol is not found, then we'll use the - trampoline entry. */ + trampoline entry. */ if (trampoline_symbol == NULL) trampoline_symbol = msymbol; break; @@ -337,8 +334,9 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf) msymbol = msymbol->hash_next) { if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 && - (MSYMBOL_TYPE (msymbol) == mst_text || - MSYMBOL_TYPE (msymbol) == mst_file_text)) + (MSYMBOL_TYPE (msymbol) == mst_text + || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc + || MSYMBOL_TYPE (msymbol) == mst_file_text)) { switch (MSYMBOL_TYPE (msymbol)) { @@ -488,7 +486,7 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc, a binary search. Note that a minimal symbol table always consists of at least two symbols, a "real" symbol and the terminating "null symbol". If there are no real symbols, then there is no - minimal symbol table at all. */ + minimal symbol table at all. */ if (objfile->minimal_symbol_count > 0) { @@ -514,15 +512,15 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc, terminates. In essence, we are iterating the test interval down until the pc value is pushed out of it from the high end. - Warning: this code is trickier than it would appear at first. */ + Warning: this code is trickier than it would appear at first. */ - /* Should also require that pc is <= end of objfile. FIXME! */ + /* Should also require that pc is <= end of objfile. FIXME! */ if (pc >= SYMBOL_VALUE_ADDRESS (&msymbol[lo])) { while (SYMBOL_VALUE_ADDRESS (&msymbol[hi]) > pc) { - /* pc is still strictly less than highest address */ - /* Note "new" will always be >= lo */ + /* pc is still strictly less than highest address. */ + /* Note "new" will always be >= lo. */ new = (lo + hi) / 2; if ((SYMBOL_VALUE_ADDRESS (&msymbol[new]) >= pc) || (lo == new)) @@ -661,7 +659,7 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc, /* The minimal symbol indexed by hi now is the best one in this objfile's minimal symbol table. See if it is the best one - overall. */ + overall. */ if (hi >= 0 && ((best_symbol == NULL) || @@ -692,7 +690,7 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc, struct obj_section *section) } /* Backward compatibility: search through the minimal symbol table - for a matching PC (no section given) */ + for a matching PC (no section given). */ struct minimal_symbol * lookup_minimal_symbol_by_pc (CORE_ADDR pc) @@ -700,6 +698,69 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc) return lookup_minimal_symbol_by_pc_section (pc, NULL); } +/* Return non-zero iff PC is in an STT_GNU_IFUNC function resolver. */ + +int +in_gnu_ifunc_stub (CORE_ADDR pc) +{ + struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc); + + return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; +} + +/* See elf_gnu_ifunc_resolve_addr for its real implementation. */ + +static CORE_ADDR +stub_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + error (_("GDB cannot resolve STT_GNU_IFUNC symbol at address %s without " + "the ELF support compiled in."), + paddress (gdbarch, pc)); +} + +/* See elf_gnu_ifunc_resolve_name for its real implementation. */ + +static int +stub_gnu_ifunc_resolve_name (const char *function_name, + CORE_ADDR *function_address_p) +{ + error (_("GDB cannot resolve STT_GNU_IFUNC symbol \"%s\" without " + "the ELF support compiled in."), + function_name); +} + +/* See elf_gnu_ifunc_resolver_stop for its real implementation. */ + +static void +stub_gnu_ifunc_resolver_stop (struct breakpoint *b) +{ + internal_error (__FILE__, __LINE__, + _("elf_gnu_ifunc_resolver_stop cannot be reached.")); +} + +/* See elf_gnu_ifunc_resolver_return_stop for its real implementation. */ + +static void +stub_gnu_ifunc_resolver_return_stop (struct breakpoint *b) +{ + internal_error (__FILE__, __LINE__, + _("elf_gnu_ifunc_resolver_return_stop cannot be reached.")); +} + +/* See elf_gnu_ifunc_fns for its real implementation. */ + +static const struct gnu_ifunc_fns stub_gnu_ifunc_fns = +{ + stub_gnu_ifunc_resolve_addr, + stub_gnu_ifunc_resolve_name, + stub_gnu_ifunc_resolver_stop, + stub_gnu_ifunc_resolver_return_stop, +}; + +/* A placeholder for &elf_gnu_ifunc_fns. */ + +const struct gnu_ifunc_fns *gnu_ifunc_fns_p = &stub_gnu_ifunc_fns; + /* Find the minimal symbol named NAME, and return both the minsym struct and its objfile. This only checks the linkage name. Sets *OBJFILE_P and returns the minimal symbol, if it is found. If it @@ -732,7 +793,7 @@ lookup_minimal_symbol_and_objfile (const char *name, } -/* Return leading symbol character for a BFD. If BFD is NULL, +/* Return leading symbol character for a BFD. If BFD is NULL, return the leading symbol character from the main objfile. */ static int get_symbol_leading_char (bfd *); @@ -749,7 +810,7 @@ get_symbol_leading_char (bfd *abfd) /* Prepare to start collecting minimal symbols. Note that presetting msym_bunch_index to BUNCH_SIZE causes the first call to save a minimal - symbol to allocate the memory for the first bunch. */ + symbol to allocate the memory for the first bunch. */ void init_minimal_symbol_collection (void) @@ -769,6 +830,7 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address, switch (ms_type) { case mst_text: + case mst_text_gnu_ifunc: case mst_file_text: case mst_solib_trampoline: section = SECT_OFF_TEXT (objfile); @@ -815,7 +877,7 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name, return (NULL); /* It's safe to strip the leading char here once, since the name - is also stored stripped in the minimal symbol table. */ + is also stored stripped in the minimal symbol table. */ if (name[0] == get_symbol_leading_char (objfile->obfd)) { ++name; @@ -833,8 +895,7 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name, msym_bunch = new; } msymbol = &msym_bunch->contents[msym_bunch_index]; - SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown); - SYMBOL_LANGUAGE (msymbol) = language_auto; + SYMBOL_SET_LANGUAGE (msymbol, language_auto); SYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile); SYMBOL_VALUE_ADDRESS (msymbol) = address; @@ -858,7 +919,7 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name, MSYMBOL_SIZE (msymbol) = 0; /* The hash pointers must be cleared! If they're not, - add_minsym_to_hash_table will NOT add this msymbol to the hash table. */ + add_minsym_to_hash_table will NOT add this msymbol to the hash table. */ msymbol->hash_next = NULL; msymbol->demangled_hash_next = NULL; @@ -884,7 +945,7 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address, } /* Compare two minimal symbols by address and return a signed result based - on unsigned comparisons, so that we sort into unsigned numeric order. + on unsigned comparisons, so that we sort into unsigned numeric order. Within groups with the same address, sort by name. */ static int @@ -898,11 +959,11 @@ compare_minimal_symbols (const void *fn1p, const void *fn2p) if (SYMBOL_VALUE_ADDRESS (fn1) < SYMBOL_VALUE_ADDRESS (fn2)) { - return (-1); /* addr 1 is less than addr 2 */ + return (-1); /* addr 1 is less than addr 2. */ } else if (SYMBOL_VALUE_ADDRESS (fn1) > SYMBOL_VALUE_ADDRESS (fn2)) { - return (1); /* addr 1 is greater than addr 2 */ + return (1); /* addr 1 is greater than addr 2. */ } else /* addrs are equal: sort by name */ @@ -913,11 +974,11 @@ compare_minimal_symbols (const void *fn1p, const void *fn2p) if (name1 && name2) /* both have names */ return strcmp (name1, name2); else if (name2) - return 1; /* fn1 has no name, so it is "less" */ - else if (name1) /* fn2 has no name, so it is "less" */ + return 1; /* fn1 has no name, so it is "less". */ + else if (name1) /* fn2 has no name, so it is "less". */ return -1; else - return (0); /* neither has a name, so they're equal. */ + return (0); /* Neither has a name, so they're equal. */ } } @@ -927,7 +988,7 @@ compare_minimal_symbols (const void *fn1p, const void *fn2p) FIXME: We could allocate the minimal symbol bunches on their own obstack and then simply blow the obstack away when we are done with - it. Is it worth the extra trouble though? */ + it. Is it worth the extra trouble though? */ static void do_discard_minimal_symbols_cleanup (void *arg) @@ -1020,7 +1081,7 @@ compact_minimal_symbols (struct minimal_symbol *msymbol, int mcount, /* Build (or rebuild) the minimal symbol hash tables. This is necessary after compacting or sorting the table since the entries move around - thus causing the internal minimal_symbol pointers to become jumbled. */ + thus causing the internal minimal_symbol pointers to become jumbled. */ static void build_minimal_symbol_hash_tables (struct objfile *objfile) @@ -1028,14 +1089,14 @@ build_minimal_symbol_hash_tables (struct objfile *objfile) int i; struct minimal_symbol *msym; - /* Clear the hash tables. */ + /* Clear the hash tables. */ for (i = 0; i < MINIMAL_SYMBOL_HASH_SIZE; i++) { objfile->msymbol_hash[i] = 0; objfile->msymbol_demangled_hash[i] = 0; } - /* Now, (re)insert the actual entries. */ + /* Now, (re)insert the actual entries. */ for (i = objfile->minimal_symbol_count, msym = objfile->msymbols; i > 0; i--, msym++) @@ -1071,7 +1132,7 @@ build_minimal_symbol_hash_tables (struct objfile *objfile) to demangle it, and if successful, record it as a language_cplus symbol and cache the demangled form on the symbol obstack. Symbols which don't demangle are marked as language_unknown symbols, which inhibits future - attempts to demangle them if we later add more minimal symbols. */ + attempts to demangle them if we later add more minimal symbols. */ void install_minimal_symbols (struct objfile *objfile) @@ -1105,7 +1166,7 @@ install_minimal_symbols (struct objfile *objfile) to the new contiguous array of symbols. Note that we start with the current, possibly partially filled bunch (thus we use the current msym_bunch_index for the first bunch we copy over), and thereafter - each bunch is full. */ + each bunch is full. */ mcount = objfile->minimal_symbol_count; @@ -1137,7 +1198,7 @@ install_minimal_symbols (struct objfile *objfile) to some symbol in the middle of it. Zero out the fields in the "null symbol" allocated at the end of the array. Note that the symbol count does *not* include this null symbol, which is why it - is indexed by mcount and not mcount-1. */ + is indexed by mcount and not mcount-1. */ SYMBOL_LINKAGE_NAME (&msymbols[mcount]) = NULL; SYMBOL_VALUE_ADDRESS (&msymbols[mcount]) = 0; @@ -1145,7 +1206,7 @@ install_minimal_symbols (struct objfile *objfile) MSYMBOL_TARGET_FLAG_2 (&msymbols[mcount]) = 0; MSYMBOL_SIZE (&msymbols[mcount]) = 0; MSYMBOL_TYPE (&msymbols[mcount]) = mst_unknown; - SYMBOL_INIT_LANGUAGE_SPECIFIC (&msymbols[mcount], language_unknown); + SYMBOL_SET_LANGUAGE (&msymbols[mcount], language_unknown); /* Attach the minimal symbol table to the specified objfile. The strings themselves are also located in the objfile_obstack @@ -1180,7 +1241,7 @@ install_minimal_symbols (struct objfile *objfile) /* Now build the hash tables; we can't do this incrementally at an earlier point since we weren't finished with the obstack yet. (And if the msymbol obstack gets moved, all the internal - pointers to other msymbols need to be adjusted.) */ + pointers to other msymbols need to be adjusted.) */ build_minimal_symbol_hash_tables (objfile); } } @@ -1221,7 +1282,7 @@ lookup_solib_trampoline_symbol_by_pc (CORE_ADDR pc) We may fail to find the right function if a function with the same name is defined in more than one shared library, but this - is considered bad programming style. We could return 0 if we find + is considered bad programming style. We could return 0 if we find a duplicate function in case this matters someday. */ CORE_ADDR @@ -1235,7 +1296,8 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc) { ALL_MSYMBOLS (objfile, msymbol) { - if (MSYMBOL_TYPE (msymbol) == mst_text + if ((MSYMBOL_TYPE (msymbol) == mst_text + || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc) && strcmp (SYMBOL_LINKAGE_NAME (msymbol), SYMBOL_LINKAGE_NAME (tsymbol)) == 0) return SYMBOL_VALUE_ADDRESS (msymbol); diff --git a/contrib/gdb-7/gdb/mipsread.c b/contrib/gdb-7/gdb/mipsread.c index cb186b1292..74d795d4a6 100644 --- a/contrib/gdb-7/gdb/mipsread.c +++ b/contrib/gdb-7/gdb/mipsread.c @@ -1,7 +1,7 @@ /* Read a symbol table in MIPS' format (Third-Eye). Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work @@ -92,7 +92,7 @@ mipscoff_symfile_read (struct objfile *objfile, int symfile_flags) read_alphacoff_dynamic_symtab (objfile->section_offsets, objfile); /* Install any minimal symbols that have been collected as the current - minimal symbols for this objfile. */ + minimal symbols for this objfile. */ install_minimal_symbols (objfile); do_cleanups (back_to); @@ -110,7 +110,7 @@ mipscoff_symfile_finish (struct objfile *objfile) standard COFF section. The ELF format for the symbols differs from the format defined in elf/external.h. It seems that a normal ELF 32-bit format is used, and the representation only changes because - longs are 64-bit on the alpha. In addition, the handling of + longs are 64-bit on the alpha. In addition, the handling of text/data section indices for symbols is different from the ELF ABI. As the BFD linker currently does not support dynamic linking on the alpha, there seems to be no reason to pollute BFD with @@ -341,7 +341,7 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets, } else { - /* Symbols defined in the executable itself. We only care + /* Symbols defined in the executable itself. We only care about them if this is a stripped executable, otherwise they have been retrieved from the normal symbol table already. */ @@ -390,20 +390,19 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets, /* Initialization. */ -static struct sym_fns ecoff_sym_fns = +static const struct sym_fns ecoff_sym_fns = { bfd_target_ecoff_flavour, - mipscoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ - mipscoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - mipscoff_symfile_read, /* sym_read: read a symbol file into symtab */ - mipscoff_symfile_finish, /* sym_finish: finished with file, cleanup */ - default_symfile_offsets, /* sym_offsets: dummy FIXME til implem sym reloc */ - default_symfile_segments, /* sym_segments: Get segment information from - a file. */ - NULL, /* sym_read_linetable */ - default_symfile_relocate, /* sym_relocate: Relocate a debug section. */ - &psym_functions, - NULL /* next: pointer to next struct sym_fns */ + mipscoff_new_init, /* init anything gbl to entire symtab */ + mipscoff_symfile_init, /* read initial info, setup for sym_read() */ + mipscoff_symfile_read, /* read a symbol file into symtab */ + NULL, /* sym_read_psymbols */ + mipscoff_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* dummy FIXME til implem sym reloc */ + default_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &psym_functions }; /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/contrib/gdb-7/gdb/objc-exp.y b/contrib/gdb-7/gdb/objc-exp.y index 888bd201e4..852adff642 100644 --- a/contrib/gdb-7/gdb/objc-exp.y +++ b/contrib/gdb-7/gdb/objc-exp.y @@ -1,7 +1,7 @@ /* YACC parser for C expressions, for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 2002, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -107,14 +107,11 @@ #define YYDEBUG 0 /* Default to no yydebug support. */ #endif -int -yyparse (void); +int yyparse (void); -static int -yylex (void); +static int yylex (void); -void -yyerror (char *); +void yyerror (char *); %} @@ -150,8 +147,7 @@ yyerror (char *); %{ /* YYSTYPE gets defined by %union. */ -static int -parse_number (char *, int, int, YYSTYPE *); +static int parse_number (char *, int, int, YYSTYPE *); %} %type exp exp1 type_exp start variable qualified_name lcurly @@ -178,7 +174,7 @@ parse_number (char *, int, int, YYSTYPE *); %token STRING %token NSSTRING /* ObjC Foundation "NSString" literal */ %token SELECTOR /* ObjC "@selector" pseudo-operator */ -%token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token NAME /* BLOCKNAME defined below to give it higher precedence. */ %token TYPENAME %token CLASSNAME /* ObjC Class name */ %type name @@ -336,7 +332,7 @@ exp : '[' TYPENAME class = lookup_objc_class (parse_gdbarch, copy_name ($2.stoken)); if (class == 0) - error ("%s is not an ObjC Class", + error (_("%s is not an ObjC Class"), copy_name ($2.stoken)); write_exp_elt_opcode (OP_LONG); write_exp_elt_type (parse_type->builtin_int); @@ -544,10 +540,12 @@ exp : INT exp : NAME_OR_INT { YYSTYPE val; - parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); + parse_number ($1.stoken.ptr, + $1.stoken.length, 0, &val); write_exp_elt_opcode (OP_LONG); write_exp_elt_type (val.typed_val_int.type); - write_exp_elt_longcst ((LONGEST)val.typed_val_int.val); + write_exp_elt_longcst ((LONGEST) + val.typed_val_int.val); write_exp_elt_opcode (OP_LONG); } ; @@ -624,9 +622,10 @@ block : BLOCKNAME struct symtab *tem = lookup_symtab (copy_name ($1.stoken)); if (tem) - $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK); + $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), + STATIC_BLOCK); else - error ("No file or function \"%s\".", + error (_("No file or function \"%s\"."), copy_name ($1.stoken)); } } @@ -637,7 +636,7 @@ block : block COLONCOLON name = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) - error ("No function \"%s\" in specified context.", + error (_("No function \"%s\" in specified context."), copy_name ($3)); $$ = SYMBOL_BLOCK_VALUE (tem); } ; @@ -647,7 +646,7 @@ variable: block COLONCOLON name sym = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (sym == 0) - error ("No symbol \"%s\" in specified context.", + error (_("No symbol \"%s\" in specified context."), copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); @@ -662,7 +661,7 @@ qualified_name: typebase COLONCOLON name struct type *type = $1; if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) - error ("`%s' is not defined as an aggregate type.", + error (_("`%s' is not defined as an aggregate type."), TYPE_NAME (type)); write_exp_elt_opcode (OP_SCOPE); @@ -676,11 +675,11 @@ qualified_name: typebase COLONCOLON name struct stoken tmp_token; if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) - error ("`%s' is not defined as an aggregate type.", + error (_("`%s' is not defined as an aggregate type."), TYPE_NAME (type)); if (strcmp (type_name_no_tag (type), $4.ptr) != 0) - error ("invalid destructor `%s::~%s'", + error (_("invalid destructor `%s::~%s'"), type_name_no_tag (type), $4.ptr); tmp_token.ptr = (char*) alloca ($4.length + 2); @@ -717,10 +716,13 @@ variable: qualified_name msymbol = lookup_minimal_symbol (name, NULL, NULL); if (msymbol != NULL) write_exp_msymbol (msymbol); - else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + else if (!have_full_symbols () + && !have_partial_symbols ()) + error (_("No symbol table is loaded. " + "Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", name); + error (_("No symbol \"%s\" in current context."), + name); } ; @@ -770,9 +772,10 @@ variable: name_not_typename write_exp_msymbol (msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + error (_("No symbol table is loaded. " + "Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name ($1.stoken)); } } @@ -855,7 +858,7 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier. */ | CLASSNAME { if ($1.type == NULL) - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name($1.stoken)); else $$ = $1.type; @@ -1012,26 +1015,10 @@ parse_number (p, len, parsed_float, putithere) if (parsed_float) { - char c; - - /* It's a float since it contains a point or an exponent. */ - - sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c", - &putithere->typed_val_float.dval, &c); - - /* See if it has `f' or `l' suffix (float or long double). */ - - c = tolower (p[len - 1]); - - if (c == 'f') - putithere->typed_val_float.type = parse_type->builtin_float; - else if (c == 'l') - putithere->typed_val_float.type = parse_type->builtin_long_double; - else if (isdigit (c) || c == '.') - putithere->typed_val_float.type = parse_type->builtin_double; - else + if (! parse_c_float (parse_gdbarch, p, len, + &putithere->typed_val_float.dval, + &putithere->typed_val_float.type)) return ERROR; - return FLOAT; } @@ -1115,7 +1102,7 @@ parse_number (p, len, parsed_float, putithere) if (c != 'l' && c != 'u' && n != 0) { if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n)) - error ("Numeric constant too large."); + error (_("Numeric constant too large.")); } prevn = n; } @@ -1136,7 +1123,8 @@ parse_number (p, len, parsed_float, putithere) if (long_p == 0 && (un >> (gdbarch_int_bit (parse_gdbarch) - 2)) == 0) { - high_bit = ((unsigned LONGEST)1) << (gdbarch_int_bit (parse_gdbarch) - 1); + high_bit + = ((unsigned LONGEST)1) << (gdbarch_int_bit (parse_gdbarch) - 1); /* A large decimal (not hex or octal) constant (between INT_MAX and UINT_MAX) is a long or unsigned long, according to ANSI, @@ -1150,7 +1138,8 @@ parse_number (p, len, parsed_float, putithere) else if (long_p <= 1 && (un >> (gdbarch_long_bit (parse_gdbarch) - 2)) == 0) { - high_bit = ((unsigned LONGEST)1) << (gdbarch_long_bit (parse_gdbarch) - 1); + high_bit + = ((unsigned LONGEST)1) << (gdbarch_long_bit (parse_gdbarch) - 1); unsigned_type = parse_type->builtin_unsigned_long; signed_type = parse_type->builtin_long; } @@ -1225,7 +1214,7 @@ static const struct token tokentab2[] = /* Read one token, getting characters through lexptr. */ static int -yylex () +yylex (void) { int c, tokchr; int namelen; @@ -1278,7 +1267,7 @@ yylex () if (c == '\\') c = parse_escape (parse_gdbarch, &lexptr); else if (c == '\'') - error ("Empty character constant."); + error (_("Empty character constant.")); yylval.typed_val_int.val = c; yylval.typed_val_int.type = parse_type->builtin_char; @@ -1291,12 +1280,12 @@ yylex () { lexptr = tokstart + namelen; if (lexptr[-1] != '\'') - error ("Unmatched single quote."); + error (_("Unmatched single quote.")); namelen -= 2; tokstart++; goto tryname; } - error ("Invalid character constant."); + error (_("Invalid character constant.")); } return INT; @@ -1347,7 +1336,8 @@ yylex () hex = 1; local_radix = 16; } - else if (tokchr == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) + else if (tokchr == '0' && (p[1]=='t' || p[1]=='T' + || p[1]=='d' || p[1]=='D')) { p += 2; hex = 0; @@ -1406,7 +1396,7 @@ yylex () memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - error ("Invalid number \"%s\".", err_copy); + error (_("Invalid number \"%s\"."), err_copy); } lexptr = p; return toktype; @@ -1444,7 +1434,7 @@ yylex () tokptr = strchr(tokstart, '('); if (tokptr == NULL) { - error ("Missing '(' in @selector(...)"); + error (_("Missing '(' in @selector(...)")); } tempbufindex = 0; tokptr++; /* Skip the '('. */ @@ -1459,7 +1449,7 @@ yylex () } while ((*tokptr != ')') && (*tokptr != '\0')); if (*tokptr++ != ')') { - error ("Missing ')' in @selector(...)"); + error (_("Missing ')' in @selector(...)")); } tempbuf[tempbufindex] = '\0'; yylval.sval.ptr = tempbuf; @@ -1520,7 +1510,7 @@ yylex () } while ((*tokptr != '"') && (*tokptr != '\0')); if (*tokptr++ != '"') { - error ("Unterminated string in expression."); + error (_("Unterminated string in expression.")); } tempbuf[tempbufindex] = '\0'; /* See note above. */ yylval.sval.ptr = tempbuf; @@ -1532,7 +1522,7 @@ yylex () if (!(tokchr == '_' || tokchr == '$' || (tokchr >= 'a' && tokchr <= 'z') || (tokchr >= 'A' && tokchr <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; @@ -1790,8 +1780,8 @@ yyerror (msg) char *msg; { if (*lexptr == '\0') - error("A %s near end of expression.", (msg ? msg : "error")); + error(_("A %s near end of expression."), (msg ? msg : "error")); else - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), + error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); } diff --git a/contrib/gdb-7/gdb/objc-lang.c b/contrib/gdb-7/gdb/objc-lang.c index d5897c036b..592b52e3ca 100644 --- a/contrib/gdb-7/gdb/objc-lang.c +++ b/contrib/gdb-7/gdb/objc-lang.c @@ -1,6 +1,6 @@ /* Objective-C language support routines for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Apple Computer, Inc. @@ -125,7 +125,8 @@ lookup_objc_class (struct gdbarch *gdbarch, char *classname) function = find_function_in_inferior("objc_lookup_class", NULL); else { - complaint (&symfile_complaints, _("no way to lookup Objective-C classes")); + complaint (&symfile_complaints, + _("no way to lookup Objective-C classes")); return 0; } @@ -153,12 +154,14 @@ lookup_child_selector (struct gdbarch *gdbarch, char *selname) function = find_function_in_inferior("sel_get_any_uid", NULL); else { - complaint (&symfile_complaints, _("no way to lookup Objective-C selectors")); + complaint (&symfile_complaints, + _("no way to lookup Objective-C selectors")); return 0; } selstring = value_coerce_array (value_string (selname, - strlen (selname) + 1, char_type)); + strlen (selname) + 1, + char_type)); return value_as_long (call_function_by_hand (function, 1, &selstring)); } @@ -233,25 +236,26 @@ objc_demangle (const char *mangled, int options) *cp++ = '+'; /* for class method */ *cp++ = '['; /* opening left brace */ - strcpy(cp, mangled+3); /* tack on the rest of the mangled name */ + strcpy(cp, mangled+3); /* Tack on the rest of the mangled name. */ while (*cp && *cp == '_') - cp++; /* skip any initial underbars in class name */ + cp++; /* Skip any initial underbars in class + name. */ cp = strchr(cp, '_'); - if (!cp) /* find first non-initial underbar */ + if (!cp) /* Find first non-initial underbar. */ { xfree(demangled); /* not mangled name */ return NULL; } - if (cp[1] == '_') /* easy case: no category name */ + if (cp[1] == '_') /* Easy case: no category name. */ { - *cp++ = ' '; /* replace two '_' with one ' ' */ + *cp++ = ' '; /* Replace two '_' with one ' '. */ strcpy(cp, mangled + (cp - demangled) + 2); } else { - *cp++ = '('; /* less easy case: category name */ + *cp++ = '('; /* Less easy case: category name. */ cp = strchr(cp, '_'); if (!cp) { @@ -259,16 +263,17 @@ objc_demangle (const char *mangled, int options) return NULL; } *cp++ = ')'; - *cp++ = ' '; /* overwriting 1st char of method name... */ - strcpy(cp, mangled + (cp - demangled)); /* get it back */ + *cp++ = ' '; /* Overwriting 1st char of method name... */ + strcpy(cp, mangled + (cp - demangled)); /* Get it back. */ } while (*cp && *cp == '_') - cp++; /* skip any initial underbars in method name */ + cp++; /* Skip any initial underbars in + method name. */ for (; *cp; cp++) if (*cp == '_') - *cp = ':'; /* replace remaining '_' with ':' */ + *cp = ':'; /* Replace remaining '_' with ':'. */ *cp++ = ']'; /* closing right brace */ *cp++ = 0; /* string terminator */ @@ -434,7 +439,7 @@ objc_printstr (struct ui_file *stream, struct type *type, /* Determine if we are currently in the Objective-C dispatch function. If so, get the address of the method function that the dispatcher - would call and use that as the function to step into instead. Also + would call and use that as the function to step into instead. Also skip over the trampoline for the function (if any). This is better for the user since they are only interested in stepping into the method function anyway. */ @@ -525,7 +530,8 @@ const struct language_defn objc_language_defn = { basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ objc_demangle, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, /* Language specific + class_name_from_physname */ objc_op_print_tab, /* Expression operators for printing */ 1, /* C-style arrays */ 0, /* String lower bound */ @@ -540,7 +546,7 @@ const struct language_defn objc_language_defn = { /* * ObjC: - * Following functions help construct Objective-C message calls + * Following functions help construct Objective-C message calls. */ struct selname /* For parsing Objective-C. */ @@ -645,10 +651,10 @@ specialcmp (char *a, char *b) a++, b++; } if (*a && *a != ' ' && *a != ']') - return 1; /* a is longer therefore greater */ + return 1; /* a is longer therefore greater. */ if (*b && *b != ' ' && *b != ']') - return -1; /* a is shorter therefore lesser */ - return 0; /* a and b are identical */ + return -1; /* a is shorter therefore lesser. */ + return 0; /* a and b are identical. */ } /* @@ -714,6 +720,9 @@ selectors_info (char *regexp, int from_tty) strcpy(myregexp, ".*]"); else { + /* Allow a few extra bytes because of the strcat below. */ + if (sizeof (myregexp) < strlen (regexp) + 4) + error (_("Regexp is too long: %s"), regexp); strcpy(myregexp, regexp); if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */ myregexp[strlen(myregexp) - 1] = ']'; /* end of method name */ @@ -734,19 +743,26 @@ selectors_info (char *regexp, int from_tty) { QUIT; name = SYMBOL_NATURAL_NAME (msymbol); - if (name && - (name[0] == '-' || name[0] == '+') && - name[1] == '[') /* Got a method name. */ + if (name + && (name[0] == '-' || name[0] == '+') + && name[1] == '[') /* Got a method name. */ { /* Filter for class/instance methods. */ if (plusminus && name[0] != plusminus) continue; /* Find selector part. */ - name = (char *) strchr(name+2, ' '); + name = (char *) strchr (name+2, ' '); + if (name == NULL) + { + complaint (&symfile_complaints, + _("Bad method name '%s'"), + SYMBOL_NATURAL_NAME (msymbol)); + continue; + } if (regexp == NULL || re_exec(++name) != 0) { char *mystart = name; - char *myend = (char *) strchr(mystart, ']'); + char *myend = (char *) strchr (mystart, ']'); if (myend && (myend - mystart > maxlen)) maxlen = myend - mystart; /* Get longest selector. */ @@ -803,7 +819,8 @@ selectors_info (char *regexp, int from_tty) begin_line(); } else - printf_filtered (_("No selectors matching \"%s\"\n"), regexp ? regexp : "*"); + printf_filtered (_("No selectors matching \"%s\"\n"), + regexp ? regexp : "*"); } /* @@ -854,6 +871,9 @@ classes_info (char *regexp, int from_tty) strcpy(myregexp, ".* "); /* Null input: match all objc classes. */ else { + /* Allow a few extra bytes because of the strcat below. */ + if (sizeof (myregexp) < strlen (regexp) + 4) + error (_("Regexp is too long: %s"), regexp); strcpy(myregexp, regexp); if (myregexp[strlen(myregexp) - 1] == '$') /* In the method name, the end of the class name is marked by ' '. */ @@ -959,7 +979,7 @@ classes_info (char *regexp, int from_tty) * into two parts: debuggable (struct symbol) syms, and * non_debuggable (struct minimal_symbol) syms. The debuggable * ones will come first, before NUM_DEBUGGABLE (which will thus - * be the index of the first non-debuggable one). + * be the index of the first non-debuggable one). */ /* @@ -1201,6 +1221,8 @@ find_methods (struct symtab *symtab, char type, pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc, ¤t_target); + objfile_csym++; + if (symtab) if (pc < BLOCK_START (block) || pc >= BLOCK_END (block)) /* Not in the specified symtab. */ @@ -1214,10 +1236,9 @@ find_methods (struct symtab *symtab, char type, } strcpy (tmp, symname); - if (parse_method (tmp, &ntype, &nclass, &ncategory, &nselector) == NULL) + if (parse_method (tmp, &ntype, &nclass, + &ncategory, &nselector) == NULL) continue; - - objfile_csym++; if ((type != '\0') && (ntype != type)) continue; @@ -1363,7 +1384,7 @@ char *find_imps (struct symtab *symtab, struct block *block, * with debug symbols from the first batch. Repeat until either the * second section is out of debug symbols or the first section is * full of debug symbols. Either way we have all debug symbols - * packed to the beginning of the buffer. + * packed to the beginning of the buffer. */ if (syms != NULL) @@ -1468,7 +1489,7 @@ print_object_command (char *args, int from_tty) /* The data structure 'methcalls' is used to detect method calls (thru * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.), - * and ultimately find the method being called. + * and ultimately find the method being called. */ struct objc_methcall { @@ -1501,7 +1522,7 @@ static struct objc_methcall methcalls[] = { * structure "objc_msgs" by finding the addresses of each of the * (currently four) functions that it holds (of which objc_msgSend is * the first). This must be called each time symbols are loaded, in - * case the functions have moved for some reason. + * case the functions have moved for some reason. */ static void @@ -1545,7 +1566,7 @@ find_objc_msgsend (void) * returning the address of the shlib function that would be called. * That functionality has been moved into the gdbarch_skip_trampoline_code and * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target- - * dependent modules. + * dependent modules. */ struct objc_submethod_helper_data { @@ -1579,7 +1600,8 @@ find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *), if (catch_errors (find_objc_msgcall_submethod_helper, (void *) &s, - "Unable to determine target of Objective-C method call (ignoring):\n", + "Unable to determine target of " + "Objective-C method call (ignoring):\n", RETURN_MASK_ALL) == 0) return 1; else @@ -1610,7 +1632,8 @@ find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc) return 0; } -extern initialize_file_ftype _initialize_objc_language; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_objc_language; void _initialize_objc_language (void) @@ -1682,7 +1705,8 @@ read_objc_class (struct gdbarch *gdbarch, CORE_ADDR addr, class->name = read_memory_unsigned_integer (addr + 8, 4, byte_order); class->version = read_memory_unsigned_integer (addr + 12, 4, byte_order); class->info = read_memory_unsigned_integer (addr + 16, 4, byte_order); - class->instance_size = read_memory_unsigned_integer (addr + 18, 4, byte_order); + class->instance_size = read_memory_unsigned_integer (addr + 18, 4, + byte_order); class->ivars = read_memory_unsigned_integer (addr + 24, 4, byte_order); class->methods = read_memory_unsigned_integer (addr + 28, 4, byte_order); class->cache = read_memory_unsigned_integer (addr + 32, 4, byte_order); @@ -1731,7 +1755,7 @@ find_implementation_from_class (struct gdbarch *gdbarch, if (meth_str.name == sel) /* FIXME: hppa arch was doing a pointer dereference - here. There needs to be a better way to do that. */ + here. There needs to be a better way to do that. */ return meth_str.imp; } mlistnum++; diff --git a/contrib/gdb-7/gdb/objc-lang.h b/contrib/gdb-7/gdb/objc-lang.h index 97283707df..ee4cc293a3 100644 --- a/contrib/gdb-7/gdb/objc-lang.h +++ b/contrib/gdb-7/gdb/objc-lang.h @@ -1,6 +1,6 @@ /* Objective-C language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 1992, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Apple Computer, Inc. diff --git a/contrib/gdb-7/gdb/objfiles.c b/contrib/gdb-7/gdb/objfiles.c index 953bc88fdc..7b0c450ccb 100644 --- a/contrib/gdb-7/gdb/objfiles.c +++ b/contrib/gdb-7/gdb/objfiles.c @@ -1,7 +1,8 @@ /* GDB routines for manipulating objfiles. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -21,7 +22,7 @@ along with this program. If not, see . */ /* This file contains support routines for creating, manipulating, and - destroying objfile structures. */ + destroying objfile structures. */ #include "defs.h" #include "bfd.h" /* Binary File Description */ @@ -61,7 +62,7 @@ static void objfile_alloc_data (struct objfile *objfile); static void objfile_free_data (struct objfile *objfile); /* Externally visible variables that are owned by this module. - See declarations in objfile.h for more info. */ + See declarations in objfile.h for more info. */ struct objfile *current_objfile; /* For symbol file being read in */ struct objfile *rt_common_objfile; /* For runtime common symbols */ @@ -110,14 +111,14 @@ get_objfile_pspace_data (struct program_space *pspace) /* Records whether any objfiles appeared or disappeared since we last updated address to obj section map. */ -/* Locate all mappable sections of a BFD file. +/* Locate all mappable sections of a BFD file. objfile_p_char is a char * to get it through bfd_map_over_sections; we cast it back to its proper type. */ /* Called via bfd_map_over_sections to build up the section table that the objfile references. The objfile contains pointers to the start of the table (objfile->sections) and to the first location after - the end of the table (objfile->sections_end). */ + the end of the table (objfile->sections_end). */ static void add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect, @@ -137,7 +138,8 @@ add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect, section.objfile = objfile; section.the_bfd_section = asect; section.ovly_mapped = 0; - obstack_grow (&objfile->objfile_obstack, (char *) §ion, sizeof (section)); + obstack_grow (&objfile->objfile_obstack, + (char *) §ion, sizeof (section)); objfile->sections_end = (struct obj_section *) (((size_t) objfile->sections_end) + 1); } @@ -156,7 +158,7 @@ add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect, are initialized to zero. Also note that if anything else writes to the psymbol obstack while - we are building the table, we're pretty much hosed. */ + we are building the table, we're pretty much hosed. */ int build_objfile_section_table (struct objfile *objfile) @@ -182,7 +184,7 @@ build_objfile_section_table (struct objfile *objfile) The FLAGS word contains various bits (OBJF_*) that can be taken as requests for specific operations. Other bits like OBJF_SHARED are - simply copied through to the new objfile flags member. */ + simply copied through to the new objfile flags member. */ /* NOTE: carlton/2003-02-04: This function is called with args NULL, 0 by jv-lang.c, to create an artificial objfile used to hold @@ -199,9 +201,9 @@ allocate_objfile (bfd *abfd, int flags) struct objfile *objfile; objfile = (struct objfile *) xzalloc (sizeof (struct objfile)); - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_cache = bcache_xmalloc (); - objfile->filename_cache = bcache_xmalloc (); + objfile->psymbol_cache = psymbol_bcache_init (); + objfile->macro_cache = bcache_xmalloc (NULL, NULL); + objfile->filename_cache = bcache_xmalloc (NULL, NULL); /* We could use obstack_specify_allocation here instead, but gdb_obstack.h specifies the alloc/dealloc functions. */ obstack_init (&objfile->objfile_obstack); @@ -211,13 +213,9 @@ allocate_objfile (bfd *abfd, int flags) /* Update the per-objfile information that comes from the bfd, ensuring that any data that is reference is saved in the per-objfile data - region. */ + region. */ objfile->obfd = gdb_bfd_ref (abfd); - if (objfile->name != NULL) - { - xfree (objfile->name); - } if (abfd != NULL) { /* Look up the gdbarch associated with the BFD. */ @@ -242,7 +240,7 @@ allocate_objfile (bfd *abfd, int flags) objfile->pspace = current_program_space; /* Initialize the section indexes for this objfile, so that we can - later detect if they are used w/o being properly assigned to. */ + later detect if they are used w/o being properly assigned to. */ objfile->sect_index_text = -1; objfile->sect_index_data = -1; @@ -253,7 +251,7 @@ allocate_objfile (bfd *abfd, int flags) objfile->cp_namespace_symtab = NULL; - /* Add this file onto the tail of the linked list of other such files. */ + /* Add this file onto the tail of the linked list of other such files. */ objfile->next = NULL; if (object_files == NULL) @@ -268,7 +266,7 @@ allocate_objfile (bfd *abfd, int flags) last_one->next = objfile; } - /* Save passed in flag bits. */ + /* Save passed in flag bits. */ objfile->flags |= flags; /* Rebuild section map next time we need it. */ @@ -284,7 +282,7 @@ get_objfile_arch (struct objfile *objfile) return objfile->gdbarch; } -/* Initialize entry point information for this objfile. */ +/* Initialize entry point information for this objfile. */ void init_entry_point_info (struct objfile *objfile) @@ -376,7 +374,7 @@ terminate_minimal_symbol_table (struct objfile *objfile) memset (m, 0, sizeof (*m)); /* Don't rely on these enumeration values being 0's. */ MSYMBOL_TYPE (m) = mst_unknown; - SYMBOL_INIT_LANGUAGE_SPECIFIC (m, language_unknown); + SYMBOL_SET_LANGUAGE (m, language_unknown); } } @@ -422,7 +420,7 @@ objfile_separate_debug_iterate (const struct objfile *parent, /* Put one object file before a specified on in the global list. This can be used to make sure an object file is destroyed before - another when using ALL_OBJFILES_SAFE to free all objfiles. */ + another when using ALL_OBJFILES_SAFE to free all objfiles. */ void put_objfile_before (struct objfile *objfile, struct objfile *before_this) { @@ -475,7 +473,7 @@ objfile_to_front (struct objfile *objfile) If OBJFILE turns out to be in the list, we zap it's NEXT pointer after unlinking it, just to ensure that we have completely severed any linkages - between the OBJFILE and the list. */ + between the OBJFILE and the list. */ void unlink_objfile (struct objfile *objfile) @@ -512,7 +510,7 @@ add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent) parent->separate_debug_objfile = objfile; /* Put the separate debug object before the normal one, this is so that - usage of the ALL_OBJFILES_SAFE macro will stay safe. */ + usage of the ALL_OBJFILES_SAFE macro will stay safe. */ put_objfile_before (objfile, parent); } @@ -546,7 +544,7 @@ free_objfile_separate_debug (struct objfile *objfile) may be using the symbol information at the same time (when mmalloc is extended to support cooperative locking). When more than one process is using the mapped symbol info, we need to be more careful about when - we free objects in the reusable area. */ + we free objects in the reusable area. */ void free_objfile (struct objfile *objfile) @@ -594,7 +592,7 @@ free_objfile (struct objfile *objfile) is using reusable symbol information (via mmalloc) then each of these routines is responsible for doing the correct thing, either freeing things which are valid only during this particular gdb - execution, or leaving them to be reused during the next one. */ + execution, or leaving them to be reused during the next one. */ if (objfile->sf != NULL) { @@ -606,7 +604,7 @@ free_objfile (struct objfile *objfile) gdb_bfd_unref (objfile->obfd); - /* Remove it from the chain of all objfiles. */ + /* Remove it from the chain of all objfiles. */ unlink_objfile (objfile); @@ -621,7 +619,7 @@ free_objfile (struct objfile *objfile) linkage unit, gdb used to do these things whenever the monolithic symbol table was blown away. How much still needs to be done is unknown, but we play it safe for now and keep each action until - it is shown to be no longer needed. */ + it is shown to be no longer needed. */ /* Not all our callers call clear_symtab_users (objfile_purge_solibs, for example), so we need to call this here. */ @@ -634,7 +632,7 @@ free_objfile (struct objfile *objfile) innermost_block = NULL; /* Check to see if the current_source_symtab belongs to this objfile, - and if so, call clear_current_source_symtab_and_line. */ + and if so, call clear_current_source_symtab_and_line. */ { struct symtab_and_line cursal = get_current_source_symtab_and_line (); @@ -647,18 +645,15 @@ free_objfile (struct objfile *objfile) } } - /* The last thing we do is free the objfile struct itself. */ + /* The last thing we do is free the objfile struct itself. */ - if (objfile->name != NULL) - { - xfree (objfile->name); - } + xfree (objfile->name); if (objfile->global_psymbols.list) xfree (objfile->global_psymbols.list); if (objfile->static_psymbols.list) xfree (objfile->static_psymbols.list); - /* Free the obstacks for non-reusable objfiles */ - bcache_xfree (objfile->psymbol_cache); + /* Free the obstacks for non-reusable objfiles. */ + psymbol_bcache_free (objfile->psymbol_cache); bcache_xfree (objfile->macro_cache); bcache_xfree (objfile->filename_cache); if (objfile->demangled_names_hash) @@ -699,9 +694,30 @@ free_all_objfiles (void) { free_objfile (objfile); } - clear_symtab_users (); + clear_symtab_users (0); } +/* A helper function for objfile_relocate1 that relocates a single + symbol. */ + +static void +relocate_one_symbol (struct symbol *sym, struct objfile *objfile, + struct section_offsets *delta) +{ + fixup_symbol_section (sym, objfile); + + /* The RS6000 code from which this was taken skipped + any symbols in STRUCT_DOMAIN or UNDEF_DOMAIN. + But I'm leaving out that test, on the theory that + they can't possibly pass the tests below. */ + if ((SYMBOL_CLASS (sym) == LOC_LABEL + || SYMBOL_CLASS (sym) == LOC_STATIC) + && SYMBOL_SECTION (sym) >= 0) + { + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (delta, SYMBOL_SECTION (sym)); + } +} + /* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS entries in new_offsets. SEPARATE_DEBUG_OBJFILE is not touched here. Return non-zero iff any change happened. */ @@ -767,24 +783,20 @@ objfile_relocate1 (struct objfile *objfile, ALL_BLOCK_SYMBOLS (b, iter, sym) { - fixup_symbol_section (sym, objfile); - - /* The RS6000 code from which this was taken skipped - any symbols in STRUCT_DOMAIN or UNDEF_DOMAIN. - But I'm leaving out that test, on the theory that - they can't possibly pass the tests below. */ - if ((SYMBOL_CLASS (sym) == LOC_LABEL - || SYMBOL_CLASS (sym) == LOC_STATIC) - && SYMBOL_SECTION (sym) >= 0) - { - SYMBOL_VALUE_ADDRESS (sym) += - ANOFFSET (delta, SYMBOL_SECTION (sym)); - } + relocate_one_symbol (sym, objfile, delta); } } } } + /* Relocate isolated symbols. */ + { + struct symbol *iter; + + for (iter = objfile->template_symbols; iter; iter = iter->hash_next) + relocate_one_symbol (iter, objfile, delta); + } + if (objfile->psymtabs_addrmap) addrmap_relocate (objfile->psymtabs_addrmap, ANOFFSET (delta, SECT_OFF_TEXT (objfile))); @@ -885,7 +897,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) do_cleanups (my_cleanups); } - /* Relocate breakpoints as necessary, after things are relocated. */ + /* Relocate breakpoints as necessary, after things are relocated. */ if (changed) breakpoint_re_set (); } @@ -895,7 +907,18 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) int objfile_has_partial_symbols (struct objfile *objfile) { - return objfile->sf ? objfile->sf->qf->has_symbols (objfile) : 0; + if (!objfile->sf) + return 0; + + /* If we have not read psymbols, but we have a function capable of reading + them, then that is an indication that they are in fact available. Without + this function the symbols may have been already read in but they also may + not be present in this objfile. */ + if ((objfile->flags & OBJF_PSYMTABS_READ) == 0 + && objfile->sf->sym_read_psymbols != NULL) + return 1; + + return objfile->sf->qf->has_symbols (objfile); } /* Return non-zero if OBJFILE has full symbols. */ @@ -923,7 +946,7 @@ objfile_has_symbols (struct objfile *objfile) /* Many places in gdb want to test just to see if we have any partial symbols available. This function returns zero if none are currently - available, nonzero otherwise. */ + available, nonzero otherwise. */ int have_partial_symbols (void) @@ -940,7 +963,7 @@ have_partial_symbols (void) /* Many places in gdb want to test just to see if we have any full symbols available. This function returns zero if none are currently - available, nonzero otherwise. */ + available, nonzero otherwise. */ int have_full_symbols (void) @@ -958,8 +981,8 @@ have_full_symbols (void) /* This operations deletes all objfile entries that represent solibs that weren't explicitly loaded by the user, via e.g., the add-symbol-file - command. - */ + command. */ + void objfile_purge_solibs (void) { @@ -969,8 +992,8 @@ objfile_purge_solibs (void) ALL_OBJFILES_SAFE (objf, temp) { /* We assume that the solib package has been purged already, or will - be soon. - */ + be soon. */ + if (!(objf->flags & OBJF_USERLOADED) && (objf->flags & OBJF_SHARED)) free_objfile (objf); } @@ -979,7 +1002,7 @@ objfile_purge_solibs (void) /* Many places in gdb want to test just to see if we have any minimal symbols available. This function returns zero if none are currently - available, nonzero otherwise. */ + available, nonzero otherwise. */ int have_minimal_symbols (void) @@ -1015,7 +1038,7 @@ qsort_cmp (const void *a, const void *b) /* Sections are at the same address. This could happen if A) we have an objfile and a separate debuginfo. B) we are confused, and have added sections without proper relocation, - or something like that. */ + or something like that. */ const struct objfile *const objfile1 = sect1->objfile; const struct objfile *const objfile2 = sect2->objfile; @@ -1051,7 +1074,7 @@ qsort_cmp (const void *a, const void *b) return 1; /* We should have found one of the sections before getting here. */ - gdb_assert (0); + gdb_assert_not_reached ("section not found"); } else { @@ -1066,12 +1089,12 @@ qsort_cmp (const void *a, const void *b) return 1; /* We should have found one of the objfiles before getting here. */ - gdb_assert (0); + gdb_assert_not_reached ("objfile not found"); } } /* Unreachable. */ - gdb_assert (0); + gdb_assert_not_reached ("unexpected code path"); return 0; } @@ -1280,7 +1303,7 @@ update_section_map (struct program_space *pspace, *pmap_size = map_size; } -/* Bsearch comparison function. */ +/* Bsearch comparison function. */ static int bsearch_cmp (const void *key, const void *elt) diff --git a/contrib/gdb-7/gdb/objfiles.h b/contrib/gdb-7/gdb/objfiles.h index 76410fd447..275c2ac39f 100644 --- a/contrib/gdb-7/gdb/objfiles.h +++ b/contrib/gdb-7/gdb/objfiles.h @@ -1,7 +1,8 @@ /* Definitions for symbol file management in GDB. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -22,7 +23,7 @@ #define OBJFILES_H #include "gdb_obstack.h" /* For obstack internals. */ -#include "symfile.h" /* For struct psymbol_allocation_list */ +#include "symfile.h" /* For struct psymbol_allocation_list. */ #include "progspace.h" struct bcache; @@ -48,7 +49,7 @@ struct objfile_data; the debugging information, where these values are the starting address (inclusive) and ending address (exclusive) of the instruction space in the executable which correspond to the - "startup file", I.E. crt0.o in most cases. This file is assumed to + "startup file", i.e. crt0.o in most cases. This file is assumed to be a startup file and frames with pc's inside it are treated as nonexistent. Setting these variables is necessary so that backtraces do not fly off the bottom of the stack. @@ -56,7 +57,7 @@ struct objfile_data; NOTE: cagney/2003-09-09: It turns out that this "traditional" method doesn't work. Corinna writes: ``It turns out that the call to test for "inside entry file" destroys a meaningful backtrace - under some conditions. E. g. the backtrace tests in the asm-source + under some conditions. E.g. the backtrace tests in the asm-source testcase are broken for some targets. In this test the functions are all implemented as part of one file and the testcase is not necessarily linked with a start file (depending on the target). @@ -117,7 +118,7 @@ struct obj_section /* Objfile this section is part of. */ struct objfile *objfile; - /* True if this "overlay section" is mapped into an "overlay region". */ + /* True if this "overlay section" is mapped into an "overlay region". */ int ovly_mapped; }; @@ -140,7 +141,7 @@ struct obj_section /* The "objstats" structure provides a place for gdb to record some interesting information about its internal state at runtime, on a per objfile basis, such as information about the number of symbols - read, size of string table (if any), etc. */ + read, size of string table (if any), etc. */ struct objstats { @@ -184,16 +185,18 @@ struct objfile struct list {struct list *next; struct objfile *objfile}; where the list structure is completely maintained separately within - each gdb process. */ + each gdb process. */ struct objfile *next; - /* The object file's name, tilde-expanded and absolute. - Malloc'd; free it if you free this struct. */ + /* The object file's name, tilde-expanded and absolute. Malloc'd; free it + if you free this struct. This pointer is never NULL. */ char *name; - /* Some flag bits for this objfile. */ + CORE_ADDR addr_low; + + /* Some flag bits for this objfile. */ unsigned short flags; @@ -203,13 +206,13 @@ struct objfile /* Each objfile points to a linked list of symtabs derived from this file, one symtab structure for each compilation unit (source file). Each link - in the symtab list contains a backpointer to this objfile. */ + in the symtab list contains a backpointer to this objfile. */ struct symtab *symtabs; /* Each objfile points to a linked list of partial symtabs derived from this file, one partial symtab structure for each compilation unit - (source file). */ + (source file). */ struct partial_symtab *psymtabs; @@ -220,7 +223,7 @@ struct objfile struct addrmap *psymtabs_addrmap; - /* List of freed partial symtabs, available for re-use */ + /* List of freed partial symtabs, available for re-use. */ struct partial_symtab *free_psymtabs; @@ -242,16 +245,16 @@ struct objfile long mtime; /* Obstack to hold objects that should be freed when we load a new symbol - table from this object file. */ + table from this object file. */ struct obstack objfile_obstack; /* A byte cache where we can stash arbitrary "chunks" of bytes that - will not change. */ + will not change. */ - struct bcache *psymbol_cache; /* Byte cache for partial syms */ - struct bcache *macro_cache; /* Byte cache for macros */ - struct bcache *filename_cache; /* Byte cache for file names. */ + struct psymbol_bcache *psymbol_cache; /* Byte cache for partial syms. */ + struct bcache *macro_cache; /* Byte cache for macros. */ + struct bcache *filename_cache; /* Byte cache for file names. */ /* Hash table for mapping symbol names to demangled names. Each entry in the hash table is actually two consecutive strings, @@ -261,19 +264,20 @@ struct objfile struct htab *demangled_names_hash; /* Vectors of all partial symbols read in from file. The actual data - is stored in the objfile_obstack. */ + is stored in the objfile_obstack. */ struct psymbol_allocation_list global_psymbols; struct psymbol_allocation_list static_psymbols; /* Each file contains a pointer to an array of minimal symbols for all - global symbols that are defined within the file. The array is terminated - by a "null symbol", one that has a NULL pointer for the name and a zero - value for the address. This makes it easy to walk through the array - when passed a pointer to somewhere in the middle of it. There is also - a count of the number of symbols, which does not include the terminating - null symbol. The array itself, as well as all the data that it points - to, should be allocated on the objfile_obstack for this file. */ + global symbols that are defined within the file. The array is + terminated by a "null symbol", one that has a NULL pointer for the + name and a zero value for the address. This makes it easy to walk + through the array when passed a pointer to somewhere in the middle + of it. There is also a count of the number of symbols, which does + not include the terminating null symbol. The array itself, as well + as all the data that it points to, should be allocated on the + objfile_obstack for this file. */ struct minimal_symbol *msymbols; int minimal_symbol_count; @@ -288,20 +292,20 @@ struct objfile struct minimal_symbol *msymbol_demangled_hash[MINIMAL_SYMBOL_HASH_SIZE]; /* Structure which keeps track of functions that manipulate objfile's - of the same type as this objfile. I.E. the function to read partial + of the same type as this objfile. I.e. the function to read partial symbols for example. Note that this structure is in statically allocated memory, and is shared by all objfiles that use the - object module reader of this type. */ + object module reader of this type. */ - struct sym_fns *sf; + const struct sym_fns *sf; /* The per-objfile information about the entry point, the scope (file/func) - containing the entry point, and the scope of the user's main() func. */ + containing the entry point, and the scope of the user's main() func. */ struct entry_info ei; /* Information about stabs. Will be filled in with a dbx_symfile_info - struct by those readers that need it. */ + struct by those readers that need it. */ /* NOTE: cagney/2004-10-23: This has been replaced by per-objfile data points implemented using "data" and "num_data" below. For an example of how to use this replacement, see "objfile_data" @@ -340,12 +344,12 @@ struct objfile struct section_offsets *section_offsets; int num_sections; - /* Indexes in the section_offsets array. These are initialized by the + /* Indexes in the section_offsets array. These are initialized by the *_symfile_offsets() family of functions (som_symfile_offsets, - xcoff_symfile_offsets, default_symfile_offsets). In theory they + xcoff_symfile_offsets, default_symfile_offsets). In theory they should correspond to the section indexes used by bfd for the - current objfile. The exception to this for the time being is the - SOM version. */ + current objfile. The exception to this for the time being is the + SOM version. */ int sect_index_text; int sect_index_data; @@ -375,14 +379,14 @@ struct objfile struct objfile *separate_debug_objfile; /* If this is a separate debug object, this is used as a link to the - actual executable objfile. */ + actual executable objfile. */ struct objfile *separate_debug_objfile_backlink; /* If this is a separate debug object, this is a link to the next one for the same executable objfile. */ struct objfile *separate_debug_objfile_link; - /* Place to stash various statistics about this objfile */ + /* Place to stash various statistics about this objfile. */ OBJSTATS; /* A symtab that the C++ code uses to stash special symbols @@ -391,9 +395,15 @@ struct objfile /* FIXME/carlton-2003-06-27: Delete this in a few years once "possible namespace symbols" go away. */ struct symtab *cp_namespace_symtab; + + /* A linked list of symbols created when reading template types or + function templates. These symbols are not stored in any symbol + table, so we have to keep them here to relocate them + properly. */ + struct symbol *template_symbols; }; -/* Defines for the objfile flag word. */ +/* Defines for the objfile flag word. */ /* When an object file has its functions reordered (currently Irix-5.2 shared libraries exhibit this behaviour), we will need an expensive @@ -404,7 +414,7 @@ struct objfile #define OBJF_REORDERED (1 << 0) /* Functions are reordered */ /* Distinguish between an objfile for a shared library and a "vanilla" - objfile. (If not set, the objfile may still actually be a solib. + objfile. (If not set, the objfile may still actually be a solib. This can happen if the user created the objfile by using the add-symbol-file command. GDB doesn't in that situation actually check whether the file is a solib. Rather, the target's @@ -413,7 +423,7 @@ struct objfile #define OBJF_SHARED (1 << 1) /* From a shared library */ -/* User requested that this objfile be read in it's entirety. */ +/* User requested that this objfile be read in it's entirety. */ #define OBJF_READNOW (1 << 2) /* Immediate full read */ @@ -422,12 +432,17 @@ struct objfile for run_command to remove old objfile entries which are no longer valid (i.e., are associated with an old inferior), but to preserve ones that the user explicitly loaded via the add-symbol-file - command. */ + command. */ #define OBJF_USERLOADED (1 << 3) /* User loaded */ +/* Set if we have tried to read partial symtabs for this objfile. + This is used to allow lazy reading of partial symtabs. */ + +#define OBJF_PSYMTABS_READ (1 << 4) + /* The object file that contains the runtime common minimal symbols - for SunOS4. Note that this objfile has no associated BFD. */ + for SunOS4. Note that this objfile has no associated BFD. */ extern struct objfile *rt_common_objfile; @@ -442,7 +457,7 @@ extern struct objfile *rt_common_objfile; objfile, and when we are done, we set it back to NULL, to ensure that we never put a type someplace other than where we are expecting to put it. FIXME: Maybe we should review the entire type handling system and - see if there is a better way to avoid this problem. */ + see if there is a better way to avoid this problem. */ extern struct objfile *current_objfile; @@ -497,8 +512,8 @@ extern void objfiles_changed (void); /* This operation deletes all objfile entries that represent solibs that weren't explicitly loaded by the user, via e.g., the add-symbol-file - command. - */ + command. */ + extern void objfile_purge_solibs (void); /* Functions for dealing with the minimal symbol table, really a misc @@ -605,28 +620,65 @@ extern int gdb_bfd_close_or_warn (struct bfd *abfd); #define ALL_OBJFILE_OSECTIONS(objfile, osect) \ for (osect = objfile->sections; osect < objfile->sections_end; osect++) -#define ALL_OBJSECTIONS(objfile, osect) \ - ALL_OBJFILES (objfile) \ - ALL_OBJFILE_OSECTIONS (objfile, osect) +/* Traverse all obj_sections in all objfiles in the current program + space. + + Note that this detects a "break" in the inner loop, and exits + immediately from the outer loop as well, thus, client code doesn't + need to know that this is implemented with a double for. The extra + hair is to make sure that a "break;" stops the outer loop iterating + as well, and both OBJFILE and OSECT are left unmodified: + + - The outer loop learns about the inner loop's end condition, and + stops iterating if it detects the inner loop didn't reach its + end. In other words, the outer loop keeps going only if the + inner loop reached its end cleanly [(osect) == + (objfile)->sections_end]. + + - OSECT is initialized in the outer loop initialization + expressions, such as if the inner loop has reached its end, so + the check mentioned above succeeds the first time. + + - The trick to not clearing OBJFILE on a "break;" is, in the outer + loop's loop expression, advance OBJFILE, but iff the inner loop + reached its end. If not, there was a "break;", so leave OBJFILE + as is; the outer loop's conditional will break immediately as + well (as OSECT will be different from OBJFILE->sections_end). */ + +#define ALL_OBJSECTIONS(objfile, osect) \ + for ((objfile) = current_program_space->objfiles, \ + (objfile) != NULL ? ((osect) = (objfile)->sections_end) : 0; \ + (objfile) != NULL \ + && (osect) == (objfile)->sections_end; \ + ((osect) == (objfile)->sections_end \ + ? ((objfile) = (objfile)->next, \ + (objfile) != NULL ? (osect) = (objfile)->sections_end : 0) \ + : 0)) \ + for ((osect) = (objfile)->sections; \ + (osect) < (objfile)->sections_end; \ + (osect)++) #define SECT_OFF_DATA(objfile) \ ((objfile->sect_index_data == -1) \ - ? (internal_error (__FILE__, __LINE__, _("sect_index_data not initialized")), -1) \ + ? (internal_error (__FILE__, __LINE__, \ + _("sect_index_data not initialized")), -1) \ : objfile->sect_index_data) #define SECT_OFF_RODATA(objfile) \ ((objfile->sect_index_rodata == -1) \ - ? (internal_error (__FILE__, __LINE__, _("sect_index_rodata not initialized")), -1) \ + ? (internal_error (__FILE__, __LINE__, \ + _("sect_index_rodata not initialized")), -1) \ : objfile->sect_index_rodata) #define SECT_OFF_TEXT(objfile) \ ((objfile->sect_index_text == -1) \ - ? (internal_error (__FILE__, __LINE__, _("sect_index_text not initialized")), -1) \ + ? (internal_error (__FILE__, __LINE__, \ + _("sect_index_text not initialized")), -1) \ : objfile->sect_index_text) /* Sometimes the .bss section is missing from the objfile, so we don't - want to die here. Let the users of SECT_OFF_BSS deal with an - uninitialized section index. */ + want to die here. Let the users of SECT_OFF_BSS deal with an + uninitialized section index. */ #define SECT_OFF_BSS(objfile) (objfile)->sect_index_bss /* Answer whether there is more than one object file loaded. */ diff --git a/contrib/gdb-7/gdb/observer.c b/contrib/gdb-7/gdb/observer.c index fb9beb1e96..de59ac67da 100644 --- a/contrib/gdb-7/gdb/observer.c +++ b/contrib/gdb-7/gdb/observer.c @@ -1,6 +1,6 @@ /* GDB Notifications to Observers. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -19,9 +19,9 @@ along with this program. If not, see . */ /* An observer is an entity who is interested in being notified when GDB - reaches certain states, or certain events occur in GDB. The entity being - observed is called the Subject. To receive notifications, the observer - attaches a callback to the subject. One subject can have several + reaches certain states, or certain events occur in GDB. The entity being + observed is called the Subject. To receive notifications, the observer + attaches a callback to the subject. One subject can have several observers. This file implements an internal generic low-level event notification @@ -31,15 +31,15 @@ for all possible notifications. The current implementation of the generic observer provides support - for contextual data. This contextual data is given to the subject - when attaching the callback. In return, the subject will provide + for contextual data. This contextual data is given to the subject + when attaching the callback. In return, the subject will provide this contextual data back to the observer as a parameter of the callback. FIXME: The current support for the contextual data is only partial, as it lacks a mechanism that would deallocate this data when the - callback is detached. This is not a problem so far, as this contextual - data is only used internally to hold a function pointer. Later on, + callback is detached. This is not a problem so far, as this contextual + data is only used internally to hold a function pointer. Later on, if a certain observer needs to provide support for user-level contextual data, then the generic notification mechanism will need need to be enhanced to allow the observer to provide a routine to diff --git a/contrib/gdb-7/gdb/observer.sh b/contrib/gdb-7/gdb/observer.sh index 2bb1c2dacb..ba8ba4e192 100755 --- a/contrib/gdb-7/gdb/observer.sh +++ b/contrib/gdb-7/gdb/observer.sh @@ -29,7 +29,7 @@ rm -f ${otmp} cat <>${otmp} /* GDB Notifications to Observers. - Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/opencl-lang.c b/contrib/gdb-7/gdb/opencl-lang.c new file mode 100644 index 0000000000..22d16112ab --- /dev/null +++ b/contrib/gdb-7/gdb/opencl-lang.c @@ -0,0 +1,1121 @@ +/* OpenCL language support for GDB, the GNU debugger. + Copyright (C) 2010, 2011 Free Software Foundation, Inc. + + Contributed by Ken Werner . + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "gdb_string.h" +#include "gdbtypes.h" +#include "symtab.h" +#include "expression.h" +#include "parser-defs.h" +#include "symtab.h" +#include "language.h" +#include "c-lang.h" +#include "gdb_assert.h" + +extern void _initialize_opencl_language (void); + +/* This macro generates enum values from a given type. */ + +#define OCL_P_TYPE(TYPE)\ + opencl_primitive_type_##TYPE,\ + opencl_primitive_type_##TYPE##2,\ + opencl_primitive_type_##TYPE##3,\ + opencl_primitive_type_##TYPE##4,\ + opencl_primitive_type_##TYPE##8,\ + opencl_primitive_type_##TYPE##16 + +enum opencl_primitive_types { + OCL_P_TYPE (char), + OCL_P_TYPE (uchar), + OCL_P_TYPE (short), + OCL_P_TYPE (ushort), + OCL_P_TYPE (int), + OCL_P_TYPE (uint), + OCL_P_TYPE (long), + OCL_P_TYPE (ulong), + OCL_P_TYPE (half), + OCL_P_TYPE (float), + OCL_P_TYPE (double), + opencl_primitive_type_bool, + opencl_primitive_type_unsigned_char, + opencl_primitive_type_unsigned_short, + opencl_primitive_type_unsigned_int, + opencl_primitive_type_unsigned_long, + opencl_primitive_type_size_t, + opencl_primitive_type_ptrdiff_t, + opencl_primitive_type_intptr_t, + opencl_primitive_type_uintptr_t, + opencl_primitive_type_void, + nr_opencl_primitive_types +}; + +static struct gdbarch_data *opencl_type_data; + +struct type ** +builtin_opencl_type (struct gdbarch *gdbarch) +{ + return gdbarch_data (gdbarch, opencl_type_data); +} + +/* Returns the corresponding OpenCL vector type from the given type code, + the length of the element type, the unsigned flag and the amount of + elements (N). */ + +static struct type * +lookup_opencl_vector_type (struct gdbarch *gdbarch, enum type_code code, + unsigned int el_length, unsigned int flag_unsigned, + int n) +{ + int i; + unsigned int length; + struct type *type = NULL; + struct type **types = builtin_opencl_type (gdbarch); + + /* Check if n describes a valid OpenCL vector size (2, 3, 4, 8, 16). */ + if (n != 2 && n != 3 && n != 4 && n != 8 && n != 16) + error (_("Invalid OpenCL vector size: %d"), n); + + /* Triple vectors have the size of a quad vector. */ + length = (n == 3) ? el_length * 4 : el_length * n; + + for (i = 0; i < nr_opencl_primitive_types; i++) + { + LONGEST lowb, highb; + + if (TYPE_CODE (types[i]) == TYPE_CODE_ARRAY && TYPE_VECTOR (types[i]) + && get_array_bounds (types[i], &lowb, &highb) + && TYPE_CODE (TYPE_TARGET_TYPE (types[i])) == code + && TYPE_UNSIGNED (TYPE_TARGET_TYPE (types[i])) == flag_unsigned + && TYPE_LENGTH (TYPE_TARGET_TYPE (types[i])) == el_length + && TYPE_LENGTH (types[i]) == length + && highb - lowb + 1 == n) + { + type = types[i]; + break; + } + } + + return type; +} + +/* Returns nonzero if the array ARR contains duplicates within + the first N elements. */ + +static int +array_has_dups (int *arr, int n) +{ + int i, j; + + for (i = 0; i < n; i++) + { + for (j = i + 1; j < n; j++) + { + if (arr[i] == arr[j]) + return 1; + } + } + + return 0; +} + +/* The OpenCL component access syntax allows to create lvalues referring to + selected elements of an original OpenCL vector in arbitrary order. This + structure holds the information to describe such lvalues. */ + +struct lval_closure +{ + /* Reference count. */ + int refc; + /* The number of indices. */ + int n; + /* The element indices themselves. */ + int *indices; + /* A pointer to the original value. */ + struct value *val; +}; + +/* Allocates an instance of struct lval_closure. */ + +static struct lval_closure * +allocate_lval_closure (int *indices, int n, struct value *val) +{ + struct lval_closure *c = XZALLOC (struct lval_closure); + + c->refc = 1; + c->n = n; + c->indices = XCALLOC (n, int); + memcpy (c->indices, indices, n * sizeof (int)); + value_incref (val); /* Increment the reference counter of the value. */ + c->val = val; + + return c; +} + +static void +lval_func_read (struct value *v) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + struct type *type = check_typedef (value_type (v)); + struct type *eltype = TYPE_TARGET_TYPE (check_typedef (value_type (c->val))); + int offset = value_offset (v); + int elsize = TYPE_LENGTH (eltype); + int n, i, j = 0; + LONGEST lowb = 0; + LONGEST highb = 0; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && !get_array_bounds (type, &lowb, &highb)) + error (_("Could not determine the vector bounds")); + + /* Assume elsize aligned offset. */ + gdb_assert (offset % elsize == 0); + offset /= elsize; + n = offset + highb - lowb + 1; + gdb_assert (n <= c->n); + + for (i = offset; i < n; i++) + memcpy (value_contents_raw (v) + j++ * elsize, + value_contents (c->val) + c->indices[i] * elsize, + elsize); +} + +static void +lval_func_write (struct value *v, struct value *fromval) +{ + struct value *mark = value_mark (); + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + struct type *type = check_typedef (value_type (v)); + struct type *eltype = TYPE_TARGET_TYPE (check_typedef (value_type (c->val))); + int offset = value_offset (v); + int elsize = TYPE_LENGTH (eltype); + int n, i, j = 0; + LONGEST lowb = 0; + LONGEST highb = 0; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && !get_array_bounds (type, &lowb, &highb)) + error (_("Could not determine the vector bounds")); + + /* Assume elsize aligned offset. */ + gdb_assert (offset % elsize == 0); + offset /= elsize; + n = offset + highb - lowb + 1; + + /* Since accesses to the fourth component of a triple vector is undefined we + just skip writes to the fourth element. Imagine something like this: + int3 i3 = (int3)(0, 1, 2); + i3.hi.hi = 5; + In this case n would be 4 (offset=12/4 + 1) while c->n would be 3. */ + if (n > c->n) + n = c->n; + + for (i = offset; i < n; i++) + { + struct value *from_elm_val = allocate_value (eltype); + struct value *to_elm_val = value_subscript (c->val, c->indices[i]); + + memcpy (value_contents_writeable (from_elm_val), + value_contents (fromval) + j++ * elsize, + elsize); + value_assign (to_elm_val, from_elm_val); + } + + value_free_to_mark (mark); +} + +/* Return nonzero if all bits in V within OFFSET and LENGTH are valid. */ + +static int +lval_func_check_validity (const struct value *v, int offset, int length) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + /* Size of the target type in bits. */ + int elsize = + TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8; + int startrest = offset % elsize; + int start = offset / elsize; + int endrest = (offset + length) % elsize; + int end = (offset + length) / elsize; + int i; + + if (endrest) + end++; + + if (end > c->n) + return 0; + + for (i = start; i < end; i++) + { + int comp_offset = (i == start) ? startrest : 0; + int comp_length = (i == end) ? endrest : elsize; + + if (!value_bits_valid (c->val, c->indices[i] * elsize + comp_offset, + comp_length)) + return 0; + } + + return 1; +} + +/* Return nonzero if any bit in V is valid. */ + +static int +lval_func_check_any_valid (const struct value *v) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + /* Size of the target type in bits. */ + int elsize = + TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8; + int i; + + for (i = 0; i < c->n; i++) + if (value_bits_valid (c->val, c->indices[i] * elsize, elsize)) + return 1; + + return 0; +} + +/* Return nonzero if bits in V from OFFSET and LENGTH represent a + synthetic pointer. */ + +static int +lval_func_check_synthetic_pointer (const struct value *v, + int offset, int length) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + /* Size of the target type in bits. */ + int elsize = + TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8; + int startrest = offset % elsize; + int start = offset / elsize; + int endrest = (offset + length) % elsize; + int end = (offset + length) / elsize; + int i; + + if (endrest) + end++; + + if (end > c->n) + return 0; + + for (i = start; i < end; i++) + { + int comp_offset = (i == start) ? startrest : 0; + int comp_length = (i == end) ? endrest : elsize; + + if (!value_bits_synthetic_pointer (c->val, + c->indices[i] * elsize + comp_offset, + comp_length)) + return 0; + } + + return 1; +} + +static void * +lval_func_copy_closure (const struct value *v) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + + ++c->refc; + + return c; +} + +static void +lval_func_free_closure (struct value *v) +{ + struct lval_closure *c = (struct lval_closure *) value_computed_closure (v); + + --c->refc; + + if (c->refc == 0) + { + value_free (c->val); /* Decrement the reference counter of the value. */ + xfree (c->indices); + xfree (c); + } +} + +static struct lval_funcs opencl_value_funcs = + { + lval_func_read, + lval_func_write, + lval_func_check_validity, + lval_func_check_any_valid, + NULL, + lval_func_check_synthetic_pointer, + lval_func_copy_closure, + lval_func_free_closure + }; + +/* Creates a sub-vector from VAL. The elements are selected by the indices of + an array with the length of N. Supported values for NOSIDE are + EVAL_NORMAL and EVAL_AVOID_SIDE_EFFECTS. */ + +static struct value * +create_value (struct gdbarch *gdbarch, struct value *val, enum noside noside, + int *indices, int n) +{ + struct type *type = check_typedef (value_type (val)); + struct type *elm_type = TYPE_TARGET_TYPE (type); + struct value *ret; + + /* Check if a single component of a vector is requested which means + the resulting type is a (primitive) scalar type. */ + if (n == 1) + { + if (noside == EVAL_AVOID_SIDE_EFFECTS) + ret = value_zero (elm_type, not_lval); + else + ret = value_subscript (val, indices[0]); + } + else + { + /* Multiple components of the vector are requested which means the + resulting type is a vector as well. */ + struct type *dst_type = + lookup_opencl_vector_type (gdbarch, TYPE_CODE (elm_type), + TYPE_LENGTH (elm_type), + TYPE_UNSIGNED (elm_type), n); + + if (dst_type == NULL) + dst_type = init_vector_type (elm_type, n); + + make_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type), dst_type, NULL); + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + ret = allocate_value (dst_type); + else + { + /* Check whether to create a lvalue or not. */ + if (VALUE_LVAL (val) != not_lval && !array_has_dups (indices, n)) + { + struct lval_closure *c = allocate_lval_closure (indices, n, val); + ret = allocate_computed_value (dst_type, &opencl_value_funcs, c); + } + else + { + int i; + + ret = allocate_value (dst_type); + + /* Copy src val contents into the destination value. */ + for (i = 0; i < n; i++) + memcpy (value_contents_writeable (ret) + + (i * TYPE_LENGTH (elm_type)), + value_contents (val) + + (indices[i] * TYPE_LENGTH (elm_type)), + TYPE_LENGTH (elm_type)); + } + } + } + return ret; +} + +/* OpenCL vector component access. */ + +static struct value * +opencl_component_ref (struct expression *exp, struct value *val, char *comps, + enum noside noside) +{ + LONGEST lowb, highb; + int src_len; + struct value *v; + int indices[16], i; + int dst_len; + + if (!get_array_bounds (check_typedef (value_type (val)), &lowb, &highb)) + error (_("Could not determine the vector bounds")); + + src_len = highb - lowb + 1; + + /* Throw an error if the amount of array elements does not fit a + valid OpenCL vector size (2, 3, 4, 8, 16). */ + if (src_len != 2 && src_len != 3 && src_len != 4 && src_len != 8 + && src_len != 16) + error (_("Invalid OpenCL vector size")); + + if (strcmp (comps, "lo") == 0 ) + { + dst_len = (src_len == 3) ? 2 : src_len / 2; + + for (i = 0; i < dst_len; i++) + indices[i] = i; + } + else if (strcmp (comps, "hi") == 0) + { + dst_len = (src_len == 3) ? 2 : src_len / 2; + + for (i = 0; i < dst_len; i++) + indices[i] = dst_len + i; + } + else if (strcmp (comps, "even") == 0) + { + dst_len = (src_len == 3) ? 2 : src_len / 2; + + for (i = 0; i < dst_len; i++) + indices[i] = i*2; + } + else if (strcmp (comps, "odd") == 0) + { + dst_len = (src_len == 3) ? 2 : src_len / 2; + + for (i = 0; i < dst_len; i++) + indices[i] = i*2+1; + } + else if (strncasecmp (comps, "s", 1) == 0) + { +#define HEXCHAR_TO_INT(C) ((C >= '0' && C <= '9') ? \ + C-'0' : ((C >= 'A' && C <= 'F') ? \ + C-'A'+10 : ((C >= 'a' && C <= 'f') ? \ + C-'a'+10 : -1))) + + dst_len = strlen (comps); + /* Skip the s/S-prefix. */ + dst_len--; + + for (i = 0; i < dst_len; i++) + { + indices[i] = HEXCHAR_TO_INT(comps[i+1]); + /* Check if the requested component is invalid or exceeds + the vector. */ + if (indices[i] < 0 || indices[i] >= src_len) + error (_("Invalid OpenCL vector component accessor %s"), comps); + } + } + else + { + dst_len = strlen (comps); + + for (i = 0; i < dst_len; i++) + { + /* x, y, z, w */ + switch (comps[i]) + { + case 'x': + indices[i] = 0; + break; + case 'y': + indices[i] = 1; + break; + case 'z': + if (src_len < 3) + error (_("Invalid OpenCL vector component accessor %s"), comps); + indices[i] = 2; + break; + case 'w': + if (src_len < 4) + error (_("Invalid OpenCL vector component accessor %s"), comps); + indices[i] = 3; + break; + default: + error (_("Invalid OpenCL vector component accessor %s"), comps); + break; + } + } + } + + /* Throw an error if the amount of requested components does not + result in a valid length (1, 2, 3, 4, 8, 16). */ + if (dst_len != 1 && dst_len != 2 && dst_len != 3 && dst_len != 4 + && dst_len != 8 && dst_len != 16) + error (_("Invalid OpenCL vector component accessor %s"), comps); + + v = create_value (exp->gdbarch, val, noside, indices, dst_len); + + return v; +} + +/* Perform the unary logical not (!) operation. */ + +static struct value * +opencl_logical_not (struct expression *exp, struct value *arg) +{ + struct type *type = check_typedef (value_type (arg)); + struct type *rettype; + struct value *ret; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)) + { + struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); + LONGEST lowb, highb; + int i; + + if (!get_array_bounds (type, &lowb, &highb)) + error (_("Could not determine the vector bounds")); + + /* Determine the resulting type of the operation and allocate the + value. */ + rettype = lookup_opencl_vector_type (exp->gdbarch, TYPE_CODE_INT, + TYPE_LENGTH (eltype), 0, + highb - lowb + 1); + ret = allocate_value (rettype); + + for (i = 0; i < highb - lowb + 1; i++) + { + /* For vector types, the unary operator shall return a 0 if the + value of its operand compares unequal to 0, and -1 (i.e. all bits + set) if the value of its operand compares equal to 0. */ + int tmp = value_logical_not (value_subscript (arg, i)) ? -1 : 0; + memset (value_contents_writeable (ret) + i * TYPE_LENGTH (eltype), + tmp, TYPE_LENGTH (eltype)); + } + } + else + { + rettype = language_bool_type (exp->language_defn, exp->gdbarch); + ret = value_from_longest (rettype, value_logical_not (arg)); + } + + return ret; +} + +/* Perform a relational operation on two scalar operands. */ + +static int +scalar_relop (struct value *val1, struct value *val2, enum exp_opcode op) +{ + int ret; + + switch (op) + { + case BINOP_EQUAL: + ret = value_equal (val1, val2); + break; + case BINOP_NOTEQUAL: + ret = !value_equal (val1, val2); + break; + case BINOP_LESS: + ret = value_less (val1, val2); + break; + case BINOP_GTR: + ret = value_less (val2, val1); + break; + case BINOP_GEQ: + ret = value_less (val2, val1) || value_equal (val1, val2); + break; + case BINOP_LEQ: + ret = value_less (val1, val2) || value_equal (val1, val2); + break; + case BINOP_LOGICAL_AND: + ret = !value_logical_not (val1) && !value_logical_not (val2); + break; + case BINOP_LOGICAL_OR: + ret = !value_logical_not (val1) || !value_logical_not (val2); + break; + default: + error (_("Attempt to perform an unsupported operation")); + break; + } + return ret; +} + +/* Perform a relational operation on two vector operands. */ + +static struct value * +vector_relop (struct expression *exp, struct value *val1, struct value *val2, + enum exp_opcode op) +{ + struct value *ret; + struct type *type1, *type2, *eltype1, *eltype2, *rettype; + int t1_is_vec, t2_is_vec, i; + LONGEST lowb1, lowb2, highb1, highb2; + + type1 = check_typedef (value_type (val1)); + type2 = check_typedef (value_type (val2)); + + t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1)); + t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)); + + if (!t1_is_vec || !t2_is_vec) + error (_("Vector operations are not supported on scalar types")); + + eltype1 = check_typedef (TYPE_TARGET_TYPE (type1)); + eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)); + + if (!get_array_bounds (type1,&lowb1, &highb1) + || !get_array_bounds (type2, &lowb2, &highb2)) + error (_("Could not determine the vector bounds")); + + /* Check whether the vector types are compatible. */ + if (TYPE_CODE (eltype1) != TYPE_CODE (eltype2) + || TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2) + || TYPE_UNSIGNED (eltype1) != TYPE_UNSIGNED (eltype2) + || lowb1 != lowb2 || highb1 != highb2) + error (_("Cannot perform operation on vectors with different types")); + + /* Determine the resulting type of the operation and allocate the value. */ + rettype = lookup_opencl_vector_type (exp->gdbarch, TYPE_CODE_INT, + TYPE_LENGTH (eltype1), 0, + highb1 - lowb1 + 1); + ret = allocate_value (rettype); + + for (i = 0; i < highb1 - lowb1 + 1; i++) + { + /* For vector types, the relational, equality and logical operators shall + return 0 if the specified relation is false and -1 (i.e. all bits set) + if the specified relation is true. */ + int tmp = scalar_relop (value_subscript (val1, i), + value_subscript (val2, i), op) ? -1 : 0; + memset (value_contents_writeable (ret) + i * TYPE_LENGTH (eltype1), + tmp, TYPE_LENGTH (eltype1)); + } + + return ret; +} + +/* Perform a relational operation on two operands. */ + +static struct value * +opencl_relop (struct expression *exp, struct value *arg1, struct value *arg2, + enum exp_opcode op) +{ + struct value *val; + struct type *type1 = check_typedef (value_type (arg1)); + struct type *type2 = check_typedef (value_type (arg2)); + int t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY + && TYPE_VECTOR (type1)); + int t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY + && TYPE_VECTOR (type2)); + + if (!t1_is_vec && !t2_is_vec) + { + int tmp = scalar_relop (arg1, arg2, op); + struct type *type = + language_bool_type (exp->language_defn, exp->gdbarch); + + val = value_from_longest (type, tmp); + } + else if (t1_is_vec && t2_is_vec) + { + val = vector_relop (exp, arg1, arg2, op); + } + else + { + /* Widen the scalar operand to a vector. */ + struct value **v = t1_is_vec ? &arg2 : &arg1; + struct type *t = t1_is_vec ? type2 : type1; + + if (TYPE_CODE (t) != TYPE_CODE_FLT && !is_integral_type (t)) + error (_("Argument to operation not a number or boolean.")); + + *v = value_cast (t1_is_vec ? type1 : type2, *v); + val = vector_relop (exp, arg1, arg2, op); + } + + return val; +} + +/* Expression evaluator for the OpenCL. Most operations are delegated to + evaluate_subexp_standard; see that function for a description of the + arguments. */ + +static struct value * +evaluate_subexp_opencl (struct type *expect_type, struct expression *exp, + int *pos, enum noside noside) +{ + enum exp_opcode op = exp->elts[*pos].opcode; + struct value *arg1 = NULL; + struct value *arg2 = NULL; + struct type *type1, *type2; + + switch (op) + { + /* Handle binary relational and equality operators that are either not + or differently defined for GNU vectors. */ + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_GEQ: + case BINOP_LEQ: + (*pos)++; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); + + if (noside == EVAL_SKIP) + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + + return opencl_relop (exp, arg1, arg2, op); + + /* Handle the logical unary operator not(!). */ + case UNOP_LOGICAL_NOT: + (*pos)++; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + if (noside == EVAL_SKIP) + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + + return opencl_logical_not (exp, arg1); + + /* Handle the logical operator and(&&) and or(||). */ + case BINOP_LOGICAL_AND: + case BINOP_LOGICAL_OR: + (*pos)++; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + if (noside == EVAL_SKIP) + { + evaluate_subexp (NULL_TYPE, exp, pos, noside); + + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + } + else + { + /* For scalar operations we need to avoid evaluating operands + unecessarily. However, for vector operations we always need to + evaluate both operands. Unfortunately we only know which of the + two cases apply after we know the type of the second operand. + Therefore we evaluate it once using EVAL_AVOID_SIDE_EFFECTS. */ + int oldpos = *pos; + + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, + EVAL_AVOID_SIDE_EFFECTS); + *pos = oldpos; + type1 = check_typedef (value_type (arg1)); + type2 = check_typedef (value_type (arg2)); + + if ((TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1)) + || (TYPE_CODE (type2) == TYPE_CODE_ARRAY && TYPE_VECTOR (type2))) + { + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + return opencl_relop (exp, arg1, arg2, op); + } + else + { + /* For scalar built-in types, only evaluate the right + hand operand if the left hand operand compares + unequal(&&)/equal(||) to 0. */ + int res; + int tmp = value_logical_not (arg1); + + if (op == BINOP_LOGICAL_OR) + tmp = !tmp; + + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, + tmp ? EVAL_SKIP : noside); + type1 = language_bool_type (exp->language_defn, exp->gdbarch); + + if (op == BINOP_LOGICAL_AND) + res = !tmp && !value_logical_not (arg2); + else /* BINOP_LOGICAL_OR */ + res = tmp || !value_logical_not (arg2); + + return value_from_longest (type1, res); + } + } + + /* Handle the ternary selection operator. */ + case TERNOP_COND: + (*pos)++; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type1 = check_typedef (value_type (arg1)); + if (TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1)) + { + struct value *arg3, *tmp, *ret; + struct type *eltype2, *type3, *eltype3; + int t2_is_vec, t3_is_vec, i; + LONGEST lowb1, lowb2, lowb3, highb1, highb2, highb3; + + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg3 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type2 = check_typedef (value_type (arg2)); + type3 = check_typedef (value_type (arg3)); + t2_is_vec + = TYPE_CODE (type2) == TYPE_CODE_ARRAY && TYPE_VECTOR (type2); + t3_is_vec + = TYPE_CODE (type3) == TYPE_CODE_ARRAY && TYPE_VECTOR (type3); + + /* Widen the scalar operand to a vector if necessary. */ + if (t2_is_vec || !t3_is_vec) + { + arg3 = value_cast (type2, arg3); + type3 = value_type (arg3); + } + else if (!t2_is_vec || t3_is_vec) + { + arg2 = value_cast (type3, arg2); + type2 = value_type (arg2); + } + else if (!t2_is_vec || !t3_is_vec) + { + /* Throw an error if arg2 or arg3 aren't vectors. */ + error (_("\ +Cannot perform conditional operation on incompatible types")); + } + + eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)); + eltype3 = check_typedef (TYPE_TARGET_TYPE (type3)); + + if (!get_array_bounds (type1, &lowb1, &highb1) + || !get_array_bounds (type2, &lowb2, &highb2) + || !get_array_bounds (type3, &lowb3, &highb3)) + error (_("Could not determine the vector bounds")); + + /* Throw an error if the types of arg2 or arg3 are incompatible. */ + if (TYPE_CODE (eltype2) != TYPE_CODE (eltype3) + || TYPE_LENGTH (eltype2) != TYPE_LENGTH (eltype3) + || TYPE_UNSIGNED (eltype2) != TYPE_UNSIGNED (eltype3) + || lowb2 != lowb3 || highb2 != highb3) + error (_("\ +Cannot perform operation on vectors with different types")); + + /* Throw an error if the sizes of arg1 and arg2/arg3 differ. */ + if (lowb1 != lowb2 || lowb1 != lowb3 + || highb1 != highb2 || highb1 != highb3) + error (_("\ +Cannot perform conditional operation on vectors with different sizes")); + + ret = allocate_value (type2); + + for (i = 0; i < highb1 - lowb1 + 1; i++) + { + tmp = value_logical_not (value_subscript (arg1, i)) ? + value_subscript (arg3, i) : value_subscript (arg2, i); + memcpy (value_contents_writeable (ret) + + i * TYPE_LENGTH (eltype2), value_contents_all (tmp), + TYPE_LENGTH (eltype2)); + } + + return ret; + } + else + { + if (value_logical_not (arg1)) + { + /* Skip the second operand. */ + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + + return evaluate_subexp (NULL_TYPE, exp, pos, noside); + } + else + { + /* Skip the third operand. */ + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + + return arg2; + } + } + + /* Handle STRUCTOP_STRUCT to allow component access on OpenCL vectors. */ + case STRUCTOP_STRUCT: + { + int pc = (*pos)++; + int tem = longest_to_int (exp->elts[pc + 1].longconst); + + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type1 = check_typedef (value_type (arg1)); + + if (noside == EVAL_SKIP) + { + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + } + else if (TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1)) + { + return opencl_component_ref (exp, arg1, &exp->elts[pc + 2].string, + noside); + } + else + { + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return + value_zero (lookup_struct_elt_type + (value_type (arg1),&exp->elts[pc + 2].string, 0), + lval_memory); + else + return value_struct_elt (&arg1, NULL, + &exp->elts[pc + 2].string, NULL, + "structure"); + } + } + default: + break; + } + + return evaluate_subexp_c (expect_type, exp, pos, noside); +} + +void +opencl_language_arch_info (struct gdbarch *gdbarch, + struct language_arch_info *lai) +{ + struct type **types = builtin_opencl_type (gdbarch); + + /* Copy primitive types vector from gdbarch. */ + lai->primitive_type_vector = types; + + /* Type of elements of strings. */ + lai->string_char_type = types [opencl_primitive_type_char]; + + /* Specifies the return type of logical and relational operations. */ + lai->bool_type_symbol = "int"; + lai->bool_type_default = types [opencl_primitive_type_int]; +} + +const struct exp_descriptor exp_descriptor_opencl = +{ + print_subexp_standard, + operator_length_standard, + operator_check_standard, + op_name_standard, + dump_subexp_body_standard, + evaluate_subexp_opencl +}; + +const struct language_defn opencl_language_defn = +{ + "opencl", /* Language name */ + language_opencl, + range_check_off, + type_check_off, + case_sensitive_on, + array_row_major, + macro_expansion_c, + &exp_descriptor_opencl, + c_parse, + c_error, + null_post_parser, + c_printchar, /* Print a character constant */ + c_printstr, /* Function to print string constant */ + c_emit_char, /* Print a single char */ + c_print_type, /* Print a type using appropriate syntax */ + c_print_typedef, /* Print a typedef using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + NULL, /* Language specific skip_trampoline */ + NULL, /* name_of_this */ + basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ + basic_lookup_transparent_type,/* lookup_transparent_type */ + NULL, /* Language specific symbol demangler */ + NULL, /* Language specific + class_name_from_physname */ + c_op_print_tab, /* expression operators for printing */ + 1, /* c-style arrays */ + 0, /* String lower bound */ + default_word_break_characters, + default_make_symbol_completion_list, + opencl_language_arch_info, + default_print_array_index, + default_pass_by_reference, + c_get_string, + LANG_MAGIC +}; + +static void * +build_opencl_types (struct gdbarch *gdbarch) +{ + struct type **types + = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_opencl_primitive_types + 1, + struct type *); + +/* Helper macro to create strings. */ +#define OCL_STRING(S) #S +/* This macro allocates and assigns the type struct pointers + for the vector types. */ +#define BUILD_OCL_VTYPES(TYPE)\ + types[opencl_primitive_type_##TYPE##2] \ + = init_vector_type (types[opencl_primitive_type_##TYPE], 2); \ + TYPE_NAME (types[opencl_primitive_type_##TYPE##2]) = OCL_STRING(TYPE ## 2); \ + types[opencl_primitive_type_##TYPE##3] \ + = init_vector_type (types[opencl_primitive_type_##TYPE], 3); \ + TYPE_NAME (types[opencl_primitive_type_##TYPE##3]) = OCL_STRING(TYPE ## 3); \ + TYPE_LENGTH (types[opencl_primitive_type_##TYPE##3]) \ + = 4 * TYPE_LENGTH (types[opencl_primitive_type_##TYPE]); \ + types[opencl_primitive_type_##TYPE##4] \ + = init_vector_type (types[opencl_primitive_type_##TYPE], 4); \ + TYPE_NAME (types[opencl_primitive_type_##TYPE##4]) = OCL_STRING(TYPE ## 4); \ + types[opencl_primitive_type_##TYPE##8] \ + = init_vector_type (types[opencl_primitive_type_##TYPE], 8); \ + TYPE_NAME (types[opencl_primitive_type_##TYPE##8]) = OCL_STRING(TYPE ## 8); \ + types[opencl_primitive_type_##TYPE##16] \ + = init_vector_type (types[opencl_primitive_type_##TYPE], 16); \ + TYPE_NAME (types[opencl_primitive_type_##TYPE##16]) = OCL_STRING(TYPE ## 16) + + types[opencl_primitive_type_char] + = arch_integer_type (gdbarch, 8, 0, "char"); + BUILD_OCL_VTYPES (char); + types[opencl_primitive_type_uchar] + = arch_integer_type (gdbarch, 8, 1, "uchar"); + BUILD_OCL_VTYPES (uchar); + types[opencl_primitive_type_short] + = arch_integer_type (gdbarch, 16, 0, "short"); + BUILD_OCL_VTYPES (short); + types[opencl_primitive_type_ushort] + = arch_integer_type (gdbarch, 16, 1, "ushort"); + BUILD_OCL_VTYPES (ushort); + types[opencl_primitive_type_int] + = arch_integer_type (gdbarch, 32, 0, "int"); + BUILD_OCL_VTYPES (int); + types[opencl_primitive_type_uint] + = arch_integer_type (gdbarch, 32, 1, "uint"); + BUILD_OCL_VTYPES (uint); + types[opencl_primitive_type_long] + = arch_integer_type (gdbarch, 64, 0, "long"); + BUILD_OCL_VTYPES (long); + types[opencl_primitive_type_ulong] + = arch_integer_type (gdbarch, 64, 1, "ulong"); + BUILD_OCL_VTYPES (ulong); + types[opencl_primitive_type_half] + = arch_float_type (gdbarch, 16, "half", floatformats_ieee_half); + BUILD_OCL_VTYPES (half); + types[opencl_primitive_type_float] + = arch_float_type (gdbarch, 32, "float", floatformats_ieee_single); + BUILD_OCL_VTYPES (float); + types[opencl_primitive_type_double] + = arch_float_type (gdbarch, 64, "double", floatformats_ieee_double); + BUILD_OCL_VTYPES (double); + types[opencl_primitive_type_bool] + = arch_boolean_type (gdbarch, 8, 1, "bool"); + types[opencl_primitive_type_unsigned_char] + = arch_integer_type (gdbarch, 8, 1, "unsigned char"); + types[opencl_primitive_type_unsigned_short] + = arch_integer_type (gdbarch, 16, 1, "unsigned short"); + types[opencl_primitive_type_unsigned_int] + = arch_integer_type (gdbarch, 32, 1, "unsigned int"); + types[opencl_primitive_type_unsigned_long] + = arch_integer_type (gdbarch, 64, 1, "unsigned long"); + types[opencl_primitive_type_size_t] + = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "size_t"); + types[opencl_primitive_type_ptrdiff_t] + = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "ptrdiff_t"); + types[opencl_primitive_type_intptr_t] + = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "intptr_t"); + types[opencl_primitive_type_uintptr_t] + = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "uintptr_t"); + types[opencl_primitive_type_void] + = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void"); + + return types; +} + +void +_initialize_opencl_language (void) +{ + opencl_type_data = gdbarch_data_register_post_init (build_opencl_types); + add_language (&opencl_language_defn); +} diff --git a/contrib/gdb-7/gdb/osabi.c b/contrib/gdb-7/gdb/osabi.c index 0fced7b831..a264924fe8 100644 --- a/contrib/gdb-7/gdb/osabi.c +++ b/contrib/gdb-7/gdb/osabi.c @@ -1,6 +1,6 @@ /* OS ABI variant handling for GDB. - Copyright (C) 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -184,7 +184,7 @@ gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine, } -/* Sniffer to find the OS ABI for a given file's architecture and flavour. +/* Sniffer to find the OS ABI for a given file's architecture and flavour. It is legal to have multiple sniffers for each arch/flavour pair, to disambiguate one OS's a.out from another, for example. The first sniffer to return something other than GDB_OSABI_UNKNOWN wins, so a sniffer should @@ -458,8 +458,9 @@ generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj) break; default: - internal_error (__FILE__, __LINE__, _("\ -generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d"), + internal_error (__FILE__, __LINE__, + _("generic_elf_osabi_sniff_abi_tag_sections: " + "unknown OS number %d"), abi_tag); } return; @@ -615,7 +616,8 @@ show_osabi (struct ui_file *file, int from_tty, struct cmd_list_element *c, { if (user_osabi_state == osabi_auto) fprintf_filtered (file, - _("The current OS ABI is \"auto\" (currently \"%s\").\n"), + _("The current OS ABI is \"auto\" " + "(currently \"%s\").\n"), gdbarch_osabi_name (gdbarch_osabi (get_current_arch ()))); else fprintf_filtered (file, _("The current OS ABI is \"%s\".\n"), @@ -643,11 +645,10 @@ _initialize_gdb_osabi (void) /* Register the "set osabi" command. */ add_setshow_enum_cmd ("osabi", class_support, gdb_osabi_available_names, - &set_osabi_string, _("\ -Set OS ABI of target."), _("\ -Show OS ABI of target."), NULL, - set_osabi, - show_osabi, + &set_osabi_string, + _("Set OS ABI of target."), + _("Show OS ABI of target."), + NULL, set_osabi, show_osabi, &setlist, &showlist); user_osabi_state = osabi_auto; } diff --git a/contrib/gdb-7/gdb/osabi.h b/contrib/gdb-7/gdb/osabi.h index 2fb278be63..0c25da3561 100644 --- a/contrib/gdb-7/gdb/osabi.h +++ b/contrib/gdb-7/gdb/osabi.h @@ -1,5 +1,5 @@ /* OS ABI variant handling for GDB. - Copyright (C) 2001, 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/osdata.c b/contrib/gdb-7/gdb/osdata.c index 76143bf8ed..024d8f4131 100644 --- a/contrib/gdb-7/gdb/osdata.c +++ b/contrib/gdb-7/gdb/osdata.c @@ -1,6 +1,6 @@ /* Routines for handling XML generic OS data provided by target. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -68,7 +68,7 @@ osdata_start_osdata (struct gdb_xml_parser *parser, if (data->osdata) gdb_xml_error (parser, _("Seen more than on osdata element")); - type = VEC_index (gdb_xml_value_s, attributes, 0)->value; + type = xml_find_attribute (attributes, "type")->value; osdata = XZALLOC (struct osdata); osdata->type = xstrdup (type); data->osdata = osdata; @@ -95,7 +95,7 @@ osdata_start_column (struct gdb_xml_parser *parser, void *user_data, VEC(gdb_xml_value_s) *attributes) { struct osdata_parsing_data *data = user_data; - const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value; + const char *name = xml_find_attribute (attributes, "name")->value; data->property_name = xstrdup (name); } @@ -168,23 +168,21 @@ const struct gdb_xml_element osdata_elements[] = { struct osdata * osdata_parse (const char *xml) { - struct gdb_xml_parser *parser; - struct cleanup *before_deleting_result, *back_to; + struct cleanup *back_to; struct osdata_parsing_data data = { NULL }; - back_to = make_cleanup (null_cleanup, NULL); - parser = gdb_xml_create_parser_and_cleanup (_("osdata"), - osdata_elements, &data); - gdb_xml_use_dtd (parser, "osdata.dtd"); + back_to = make_cleanup (clear_parsing_data, &data); - before_deleting_result = make_cleanup (clear_parsing_data, &data); - - if (gdb_xml_parse (parser, xml) == 0) - /* Parsed successfully, don't need to delete the result. */ - discard_cleanups (before_deleting_result); + if (gdb_xml_parse_quick (_("osdata"), "osdata.dtd", + osdata_elements, xml, &data) == 0) + { + /* Parsed successfully, don't need to delete the result. */ + discard_cleanups (back_to); + return data.osdata; + } do_cleanups (back_to); - return data.osdata; + return NULL; } #endif @@ -269,7 +267,7 @@ get_osdata (const char *type) } if (!osdata) - error (_("Can not fetch data now.\n")); + error (_("Can not fetch data now.")); return osdata; } diff --git a/contrib/gdb-7/gdb/osdata.h b/contrib/gdb-7/gdb/osdata.h index 105c62c4fc..d849976fef 100644 --- a/contrib/gdb-7/gdb/osdata.h +++ b/contrib/gdb-7/gdb/osdata.h @@ -1,6 +1,6 @@ /* Routines for handling XML generic OS data provided by target. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/p-exp.y b/contrib/gdb-7/gdb/p-exp.y index 2aec487463..32c7aca657 100644 --- a/contrib/gdb-7/gdb/p-exp.y +++ b/contrib/gdb-7/gdb/p-exp.y @@ -1,5 +1,5 @@ /* YACC parser for Pascal expressions, for GDB. - Copyright (C) 2000, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -41,7 +41,7 @@ - there are some problems with boolean types. - Pascal type hexadecimal constants are not supported because they conflict with the internal variables format. - Probably also lots of other problems, less well defined PM */ + Probably also lots of other problems, less well defined PM. */ %{ #include "defs.h" @@ -54,7 +54,7 @@ #include "p-lang.h" #include "bfd.h" /* Required by objfiles.h. */ #include "symfile.h" /* Required by objfiles.h. */ -#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ +#include "objfiles.h" /* For have_full_symbols and have_partial_symbols. */ #include "block.h" #define parse_type builtin_type (parse_gdbarch) @@ -64,7 +64,7 @@ yacc generated parsers in gdb. Note that these are only the variables produced by yacc. If other parser generators (bison, byacc, etc) produce additional global names that conflict at link time, then those parser - generators need to be fixed instead of adding those names to this list. */ + generators need to be fixed instead of adding those names to this list. */ #define yymaxdepth pascal_maxdepth #define yyparse pascal_parse @@ -73,12 +73,12 @@ #define yylval pascal_lval #define yychar pascal_char #define yydebug pascal_debug -#define yypact pascal_pact -#define yyr1 pascal_r1 -#define yyr2 pascal_r2 -#define yydef pascal_def -#define yychk pascal_chk -#define yypgo pascal_pgo +#define yypact pascal_pact +#define yyr1 pascal_r1 +#define yyr2 pascal_r2 +#define yydef pascal_def +#define yychk pascal_chk +#define yypgo pascal_pgo #define yyact pascal_act #define yyexca pascal_exca #define yyerrflag pascal_errflag @@ -117,8 +117,7 @@ int yyparse (void); static int yylex (void); -void -yyerror (char *); +void yyerror (char *); static char * uptok (char *, int); %} @@ -154,10 +153,10 @@ static char * uptok (char *, int); %{ /* YYSTYPE gets defined by %union */ -static int -parse_number (char *, int, int, YYSTYPE *); +static int parse_number (char *, int, int, YYSTYPE *); static struct type *current_type; +static struct internalvar *intvar; static int leftdiv_is_integer; static void push_current_type (void); static void pop_current_type (void); @@ -182,9 +181,10 @@ static int search_field; Contexts where this distinction is not important can use the nonterminal "name", which matches either NAME or TYPENAME. */ -%token STRING +%token STRING %token FIELDNAME -%token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token COMPLETE +%token NAME /* BLOCKNAME defined below to give it higher precedence. */ %token TYPENAME %type name %type name_not_typename @@ -233,6 +233,7 @@ static int search_field; %% start : { current_type = NULL; + intvar = NULL; search_field = 0; leftdiv_is_integer = 0; } @@ -259,12 +260,12 @@ exp1 : exp /* Expressions, not including the comma operator. */ exp : exp '^' %prec UNARY { write_exp_elt_opcode (UNOP_IND); - if (current_type) + if (current_type) current_type = TYPE_TARGET_TYPE (current_type); } ; exp : '@' exp %prec UNARY - { write_exp_elt_opcode (UNOP_ADDR); + { write_exp_elt_opcode (UNOP_ADDR); if (current_type) current_type = TYPE_POINTER_TYPE (current_type); } ; @@ -285,36 +286,74 @@ exp : DECREMENT '(' exp ')' %prec UNARY { write_exp_elt_opcode (UNOP_PREDECREMENT); } ; -exp : exp '.' { search_field = 1; } - FIELDNAME - /* name */ + +field_exp : exp '.' %prec UNARY + { search_field = 1; } + ; + +exp : field_exp FIELDNAME { write_exp_elt_opcode (STRUCTOP_STRUCT); - write_exp_string ($4); + write_exp_string ($2); write_exp_elt_opcode (STRUCTOP_STRUCT); - search_field = 0; + search_field = 0; if (current_type) - { while (TYPE_CODE (current_type) == TYPE_CODE_PTR) - current_type = TYPE_TARGET_TYPE (current_type); + { + while (TYPE_CODE (current_type) + == TYPE_CODE_PTR) + current_type = + TYPE_TARGET_TYPE (current_type); current_type = lookup_struct_elt_type ( - current_type, $4.ptr, 0); }; - } ; + current_type, $2.ptr, 0); + } + } + ; + + +exp : field_exp name + { mark_struct_expression (); + write_exp_elt_opcode (STRUCTOP_STRUCT); + write_exp_string ($2); + write_exp_elt_opcode (STRUCTOP_STRUCT); + search_field = 0; + if (current_type) + { + while (TYPE_CODE (current_type) + == TYPE_CODE_PTR) + current_type = + TYPE_TARGET_TYPE (current_type); + current_type = lookup_struct_elt_type ( + current_type, $2.ptr, 0); + } + } + ; + +exp : field_exp COMPLETE + { struct stoken s; + mark_struct_expression (); + write_exp_elt_opcode (STRUCTOP_STRUCT); + s.ptr = ""; + s.length = 0; + write_exp_string (s); + write_exp_elt_opcode (STRUCTOP_STRUCT); } + ; + exp : exp '[' - /* We need to save the current_type value */ - { char *arrayname; + /* We need to save the current_type value. */ + { char *arrayname; int arrayfieldindex; arrayfieldindex = is_pascal_string_type ( current_type, NULL, NULL, - NULL, NULL, &arrayname); - if (arrayfieldindex) + NULL, NULL, &arrayname); + if (arrayfieldindex) { struct stoken stringsval; stringsval.ptr = alloca (strlen (arrayname) + 1); stringsval.length = strlen (arrayname); strcpy (stringsval.ptr, arrayname); current_type = TYPE_FIELD_TYPE (current_type, - arrayfieldindex - 1); + arrayfieldindex - 1); write_exp_elt_opcode (STRUCTOP_STRUCT); - write_exp_string (stringsval); + write_exp_string (stringsval); write_exp_elt_opcode (STRUCTOP_STRUCT); } push_current_type (); } @@ -333,7 +372,7 @@ exp : exp '(' arglist ')' %prec ARROW { write_exp_elt_opcode (OP_FUNCALL); write_exp_elt_longcst ((LONGEST) end_arglist ()); - write_exp_elt_opcode (OP_FUNCALL); + write_exp_elt_opcode (OP_FUNCALL); pop_current_type (); if (current_type) current_type = TYPE_TARGET_TYPE (current_type); @@ -358,7 +397,7 @@ exp : type '(' exp ')' %prec UNARY } write_exp_elt_opcode (UNOP_CAST); write_exp_elt_type ($1); - write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_opcode (UNOP_CAST); current_type = $1; } ; @@ -375,9 +414,9 @@ exp : exp '*' exp exp : exp '/' { if (current_type && is_integral_type (current_type)) leftdiv_is_integer = 1; - } + } exp - { + { if (leftdiv_is_integer && current_type && is_integral_type (current_type)) { @@ -388,7 +427,7 @@ exp : exp '/' { leftdiv_is_integer = 0; } - write_exp_elt_opcode (BINOP_DIV); + write_exp_elt_opcode (BINOP_DIV); } ; @@ -417,37 +456,37 @@ exp : exp RSH exp ; exp : exp '=' exp - { write_exp_elt_opcode (BINOP_EQUAL); + { write_exp_elt_opcode (BINOP_EQUAL); current_type = parse_type->builtin_bool; } ; exp : exp NOTEQUAL exp - { write_exp_elt_opcode (BINOP_NOTEQUAL); + { write_exp_elt_opcode (BINOP_NOTEQUAL); current_type = parse_type->builtin_bool; } ; exp : exp LEQ exp - { write_exp_elt_opcode (BINOP_LEQ); + { write_exp_elt_opcode (BINOP_LEQ); current_type = parse_type->builtin_bool; } ; exp : exp GEQ exp - { write_exp_elt_opcode (BINOP_GEQ); + { write_exp_elt_opcode (BINOP_GEQ); current_type = parse_type->builtin_bool; } ; exp : exp '<' exp - { write_exp_elt_opcode (BINOP_LESS); + { write_exp_elt_opcode (BINOP_LESS); current_type = parse_type->builtin_bool; } ; exp : exp '>' exp - { write_exp_elt_opcode (BINOP_GTR); + { write_exp_elt_opcode (BINOP_GTR); current_type = parse_type->builtin_bool; } ; @@ -492,11 +531,13 @@ exp : INT exp : NAME_OR_INT { YYSTYPE val; - parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); + parse_number ($1.stoken.ptr, + $1.stoken.length, 0, &val); write_exp_elt_opcode (OP_LONG); write_exp_elt_type (val.typed_val_int.type); current_type = val.typed_val_int.type; - write_exp_elt_longcst ((LONGEST)val.typed_val_int.val); + write_exp_elt_longcst ((LONGEST) + val.typed_val_int.val); write_exp_elt_opcode (OP_LONG); } ; @@ -514,8 +555,19 @@ exp : variable ; exp : VARIABLE - /* Already written by write_dollar_variable. */ - ; + /* Already written by write_dollar_variable. + Handle current_type. */ + { if (intvar) { + struct value * val, * mark; + + mark = value_mark (); + val = value_of_internalvar (parse_gdbarch, + intvar); + current_type = value_type (val); + value_release_to_mark (mark); + } + } + ; exp : SIZEOF '(' type ')' %prec UNARY { write_exp_elt_opcode (OP_LONG); @@ -527,13 +579,13 @@ exp : SIZEOF '(' type ')' %prec UNARY exp : SIZEOF '(' exp ')' %prec UNARY { write_exp_elt_opcode (UNOP_SIZEOF); } - + exp : STRING { /* C strings are converted into array constants with an explicit null byte added at the end. Thus the array upper bound is the string length. There is no such thing in C as a completely empty - string. */ + string. */ char *sp = $1.ptr; int count = $1.length; while (count-- > 0) { @@ -554,13 +606,13 @@ exp : STRING /* Object pascal */ exp : THIS - { + { struct value * this_val; struct type * this_type; write_exp_elt_opcode (OP_THIS); - write_exp_elt_opcode (OP_THIS); - /* we need type of this */ - this_val = value_of_this (0); + write_exp_elt_opcode (OP_THIS); + /* We need type of this. */ + this_val = value_of_this (0); if (this_val) this_type = value_type (this_val); else @@ -573,7 +625,7 @@ exp : THIS write_exp_elt_opcode (UNOP_IND); } } - + current_type = this_type; } ; @@ -589,9 +641,10 @@ block : BLOCKNAME struct symtab *tem = lookup_symtab (copy_name ($1.stoken)); if (tem) - $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK); + $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), + STATIC_BLOCK); else - error ("No file or function \"%s\".", + error (_("No file or function \"%s\"."), copy_name ($1.stoken)); } } @@ -602,7 +655,7 @@ block : block COLONCOLON name = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) - error ("No function \"%s\" in specified context.", + error (_("No function \"%s\" in specified context."), copy_name ($3)); $$ = SYMBOL_BLOCK_VALUE (tem); } ; @@ -612,7 +665,7 @@ variable: block COLONCOLON name sym = lookup_symbol (copy_name ($3), $1, VAR_DOMAIN, (int *) NULL); if (sym == 0) - error ("No symbol \"%s\" in specified context.", + error (_("No symbol \"%s\" in specified context."), copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); @@ -627,7 +680,7 @@ qualified_name: typebase COLONCOLON name struct type *type = $1; if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) - error ("`%s' is not defined as an aggregate type.", + error (_("`%s' is not defined as an aggregate type."), TYPE_NAME (type)); write_exp_elt_opcode (OP_SCOPE); @@ -659,10 +712,13 @@ variable: qualified_name msymbol = lookup_minimal_symbol (name, NULL, NULL); if (msymbol != NULL) write_exp_msymbol (msymbol); - else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + else if (!have_full_symbols () + && !have_partial_symbols ()) + error (_("No symbol table is loaded. " + "Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", name); + error (_("No symbol \"%s\" in current context."), + name); } ; @@ -703,8 +759,8 @@ variable: name_not_typename write_exp_elt_opcode (STRUCTOP_PTR); write_exp_string ($1.stoken); write_exp_elt_opcode (STRUCTOP_PTR); - /* we need type of this */ - this_val = value_of_this (0); + /* We need type of this. */ + this_val = value_of_this (0); if (this_val) this_type = value_type (this_val); else @@ -714,7 +770,7 @@ variable: name_not_typename this_type, copy_name ($1.stoken), 0); else - current_type = NULL; + current_type = NULL; } else { @@ -725,10 +781,12 @@ variable: name_not_typename lookup_minimal_symbol (arg, NULL, NULL); if (msymbol != NULL) write_exp_msymbol (msymbol); - else if (!have_full_symbols () && !have_partial_symbols ()) - error ("No symbol table is loaded. Use the \"file\" command."); + else if (!have_full_symbols () + && !have_partial_symbols ()) + error (_("No symbol table is loaded. " + "Use the \"file\" command.")); else - error ("No symbol \"%s\" in current context.", + error (_("No symbol \"%s\" in current context."), copy_name ($1.stoken)); } } @@ -791,11 +849,7 @@ name_not_typename : NAME /*** Needs some error checking for the float case ***/ static int -parse_number (p, len, parsed_float, putithere) - char *p; - int len; - int parsed_float; - YYSTYPE *putithere; +parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere) { /* FIXME: Shouldn't these be unsigned? We don't deal with negative values here, and we do kind of silly things like cast to unsigned. */ @@ -820,34 +874,14 @@ parse_number (p, len, parsed_float, putithere) if (parsed_float) { - /* It's a float since it contains a point or an exponent. */ - char c; - int num = 0; /* number of tokens scanned by scanf */ - char saved_char = p[len]; - - p[len] = 0; /* null-terminate the token */ - num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c", - &putithere->typed_val_float.dval, &c); - p[len] = saved_char; /* restore the input stream */ - if (num != 1) /* check scanf found ONLY a float ... */ - return ERROR; - /* See if it has `f' or `l' suffix (float or long double). */ - - c = tolower (p[len - 1]); - - if (c == 'f') - putithere->typed_val_float.type = parse_type->builtin_float; - else if (c == 'l') - putithere->typed_val_float.type = parse_type->builtin_long_double; - else if (isdigit (c) || c == '.') - putithere->typed_val_float.type = parse_type->builtin_double; - else + if (! parse_c_float (parse_gdbarch, p, len, + &putithere->typed_val_float.dval, + &putithere->typed_val_float.type)) return ERROR; - return FLOAT; } - /* Handle base-switching prefixes 0x, 0t, 0d, 0 */ + /* Handle base-switching prefixes 0x, 0t, 0d, 0. */ if (p[0] == '0') switch (p[1]) { @@ -913,21 +947,21 @@ parse_number (p, len, parsed_float, putithere) return ERROR; /* Char not a digit */ } if (i >= base) - return ERROR; /* Invalid digit in this base */ + return ERROR; /* Invalid digit in this base. */ /* Portably test for overflow (only works for nonzero values, so make a second check for zero). FIXME: Can't we just make n and prevn unsigned and avoid this? */ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0) - unsigned_p = 1; /* Try something unsigned */ + unsigned_p = 1; /* Try something unsigned. */ /* Portably test for unsigned overflow. FIXME: This check is wrong; for example it doesn't find overflow on 0x123456789 when LONGEST is 32 bits. */ if (c != 'l' && c != 'u' && n != 0) - { + { if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n)) - error ("Numeric constant too large."); + error (_("Numeric constant too large.")); } prevn = n; } @@ -983,7 +1017,7 @@ parse_number (p, len, parsed_float, putithere) putithere->typed_val_int.val = n; /* If the high bit of the worked out type is set then this number - has to be unsigned. */ + has to be unsigned. */ if (unsigned_p || (n & high_bit)) { @@ -1014,7 +1048,7 @@ push_current_type (void) tpnew->next = tp_top; tpnew->stored = current_type; current_type = NULL; - tp_top = tpnew; + tp_top = tpnew; } static void @@ -1058,8 +1092,8 @@ static const struct token tokentab2[] = {":=", ASSIGN, BINOP_END}, {"::", COLONCOLON, BINOP_END} }; -/* Allocate uppercased var */ -/* make an uppercased copy of tokstart */ +/* Allocate uppercased var: */ +/* make an uppercased copy of tokstart. */ static char * uptok (tokstart, namelen) char *tokstart; int namelen; @@ -1076,11 +1110,16 @@ static char * uptok (tokstart, namelen) uptokstart[namelen]='\0'; return uptokstart; } -/* Read one token, getting characters through lexptr. */ +/* This is set if the previously-returned token was a structure + operator '.'. This is used only when parsing to + do field name completion. */ +static int last_was_structop; + +/* Read one token, getting characters through lexptr. */ static int -yylex () +yylex (void) { int c; int namelen; @@ -1091,7 +1130,9 @@ yylex () int explen, tempbufindex; static char *tempbuf; static int tempbufsize; + int saw_structop = last_was_structop; + last_was_structop = 0; retry: prev_lexptr = lexptr; @@ -1103,7 +1144,8 @@ yylex () for (i = 0; i < sizeof (tokentab3) / sizeof (tokentab3[0]); i++) if (strncasecmp (tokstart, tokentab3[i].operator, 3) == 0 && (!isalpha (tokentab3[i].operator[0]) || explen == 3 - || (!isalpha (tokstart[3]) && !isdigit (tokstart[3]) && tokstart[3] != '_'))) + || (!isalpha (tokstart[3]) + && !isdigit (tokstart[3]) && tokstart[3] != '_'))) { lexptr += 3; yylval.opcode = tokentab3[i].opcode; @@ -1115,7 +1157,8 @@ yylex () for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++) if (strncasecmp (tokstart, tokentab2[i].operator, 2) == 0 && (!isalpha (tokentab2[i].operator[0]) || explen == 2 - || (!isalpha (tokstart[2]) && !isdigit (tokstart[2]) && tokstart[2] != '_'))) + || (!isalpha (tokstart[2]) + && !isdigit (tokstart[2]) && tokstart[2] != '_'))) { lexptr += 2; yylval.opcode = tokentab2[i].opcode; @@ -1125,7 +1168,10 @@ yylex () switch (c = *tokstart) { case 0: - return 0; + if (saw_structop && search_field) + return COMPLETE; + else + return 0; case ' ': case '\t': @@ -1136,13 +1182,13 @@ yylex () case '\'': /* We either have a character constant ('0' or '\177' for example) or we have a quoted symbol reference ('foo(int,int)' in object pascal - for example). */ + for example). */ lexptr++; c = *lexptr++; if (c == '\\') c = parse_escape (parse_gdbarch, &lexptr); else if (c == '\'') - error ("Empty character constant."); + error (_("Empty character constant.")); yylval.typed_val_int.val = c; yylval.typed_val_int.type = parse_type->builtin_char; @@ -1155,13 +1201,13 @@ yylex () { lexptr = tokstart + namelen; if (lexptr[-1] != '\'') - error ("Unmatched single quote."); + error (_("Unmatched single quote.")); namelen -= 2; tokstart++; uptokstart = uptok(tokstart,namelen); goto tryname; } - error ("Invalid character constant."); + error (_("Invalid character constant.")); } return INT; @@ -1186,7 +1232,12 @@ yylex () case '.': /* Might be a floating point number. */ if (lexptr[1] < '0' || lexptr[1] > '9') - goto symbol; /* Nope, must be a symbol. */ + { + if (in_parse_field) + last_was_structop = 1; + goto symbol; /* Nope, must be a symbol. */ + } + /* FALL THRU into number case. */ case '0': @@ -1210,7 +1261,8 @@ yylex () p += 2; hex = 1; } - else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) + else if (c == '0' && (p[1]=='t' || p[1]=='T' + || p[1]=='d' || p[1]=='D')) { p += 2; hex = 0; @@ -1239,14 +1291,15 @@ yylex () && (*p < 'A' || *p > 'Z'))) break; } - toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval); + toktype = parse_number (tokstart, + p - tokstart, got_dot | got_e, &yylval); if (toktype == ERROR) { char *err_copy = (char *) alloca (p - tokstart + 1); memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - error ("Invalid number \"%s\".", err_copy); + error (_("Invalid number \"%s\"."), err_copy); } lexptr = p; return toktype; @@ -1284,14 +1337,14 @@ yylex () the buffer contains no embedded nulls. Gdb does not depend upon the buffer being null byte terminated, it uses the length string instead. This allows gdb to handle C strings (as well - as strings in other languages) with embedded null bytes */ + as strings in other languages) with embedded null bytes. */ tokptr = ++tokstart; tempbufindex = 0; do { /* Grow the static temp buffer if necessary, including allocating - the first one on demand. */ + the first one on demand. */ if (tempbufindex + 1 >= tempbufsize) { tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); @@ -1301,7 +1354,7 @@ yylex () { case '\0': case '"': - /* Do nothing, loop will terminate. */ + /* Do nothing, loop will terminate. */ break; case '\\': tokptr++; @@ -1319,9 +1372,9 @@ yylex () } while ((*tokptr != '"') && (*tokptr != '\0')); if (*tokptr++ != '"') { - error ("Unterminated string in expression."); + error (_("Unterminated string in expression.")); } - tempbuf[tempbufindex] = '\0'; /* See note above */ + tempbuf[tempbufindex] = '\0'; /* See note above. */ yylval.sval.ptr = tempbuf; yylval.sval.length = tempbufindex; lexptr = tokptr; @@ -1331,7 +1384,7 @@ yylex () if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ - error ("Invalid character '%c' in expression.", c); + error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; @@ -1361,7 +1414,7 @@ yylex () break; } - /* do NOT uppercase internals because of registers !!! */ + /* do NOT uppercase internals because of registers !!! */ c = tokstart[++namelen]; } @@ -1421,8 +1474,8 @@ yylex () } if (strcmp (uptokstart, "SELF") == 0) { - /* here we search for 'this' like - inserted in FPC stabs debug info */ + /* Here we search for 'this' like + inserted in FPC stabs debug info. */ static const char this_name[] = "this"; if (lookup_symbol (this_name, expression_context_block, @@ -1442,11 +1495,17 @@ yylex () if (*tokstart == '$') { + char c; /* $ is the normal prefix for pascal hexadecimal values but this conflicts with the GDB use for debugger variables so in expression to enter hexadecimal values we still need to use C syntax with 0xff */ write_dollar_variable (yylval.sval); + c = tokstart[namelen]; + tokstart[namelen] = 0; + intvar = lookup_only_internalvar (++tokstart); + --tokstart; + tokstart[namelen] = c; free (uptokstart); return VARIABLE; } @@ -1465,8 +1524,8 @@ yylex () if (search_field && current_type) - is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); - if (is_a_field) + is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); + if (is_a_field || in_parse_field) sym = NULL; else sym = lookup_symbol (tmp, expression_context_block, @@ -1480,8 +1539,8 @@ yylex () tmp[i] -= ('a'-'A'); } if (search_field && current_type) - is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); - if (is_a_field) + is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); + if (is_a_field || in_parse_field) sym = NULL; else sym = lookup_symbol (tmp, expression_context_block, @@ -1508,8 +1567,8 @@ yylex () tmp[i] -= ('A'-'a'); } if (search_field && current_type) - is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); - if (is_a_field) + is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL); + if (is_a_field || in_parse_field) sym = NULL; else sym = lookup_symbol (tmp, expression_context_block, @@ -1533,10 +1592,10 @@ yylex () tempbuf = (char *) realloc (tempbuf, namelen + 1); strncpy (tempbuf, tokstart, namelen); tempbuf [namelen] = 0; yylval.sval.ptr = tempbuf; - yylval.sval.length = namelen; + yylval.sval.length = namelen; free (uptokstart); return FIELDNAME; - } + } /* Call lookup_symtab, not lookup_partial_symtab, in case there are no psymtabs (coff, xcoff, or some future change to blow away the psymtabs once once symbols are read). */ @@ -1666,7 +1725,7 @@ yylex () } free(uptokstart); - /* Any other kind of symbol */ + /* Any other kind of symbol. */ yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; return NAME; @@ -1680,5 +1739,5 @@ yyerror (msg) if (prev_lexptr) lexptr = prev_lexptr; - error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); } diff --git a/contrib/gdb-7/gdb/p-lang.c b/contrib/gdb-7/gdb/p-lang.c index 08738ac280..655279bcfa 100644 --- a/contrib/gdb-7/gdb/p-lang.c +++ b/contrib/gdb-7/gdb/p-lang.c @@ -1,6 +1,6 @@ /* Pascal language support routines for GDB, the GNU debugger. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -31,12 +31,12 @@ #include "valprint.h" #include "value.h" #include - + extern void _initialize_pascal_language (void); /* All GPC versions until now (2007-09-27) also define a symbol called - '_p_initialize'. Check for the presence of this symbol first. */ + '_p_initialize'. Check for the presence of this symbol first. */ static const char GPC_P_INITIALIZE[] = "_p_initialize"; /* The name of the symbol that GPC uses as the name of the main @@ -54,7 +54,7 @@ static const char GPC_MAIN_PROGRAM_NAME_2[] = "pascal_main_program"; so that it finds the even if the program was compiled without debugging information. According to information supplied by Waldeck Hebisch, - this should work for all versions posterior to June 2000. */ + this should work for all versions posterior to June 2000. */ const char * pascal_main_name (void) @@ -105,9 +105,11 @@ is_pascal_string_type (struct type *type,int *length_pos, { /* Old Borland type pascal strings from Free Pascal Compiler. */ /* Two fields: length and st. */ - if (TYPE_NFIELDS (type) == 2 - && strcmp (TYPE_FIELDS (type)[0].name, "length") == 0 - && strcmp (TYPE_FIELDS (type)[1].name, "st") == 0) + if (TYPE_NFIELDS (type) == 2 + && TYPE_FIELD_NAME (type, 0) + && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0 + && TYPE_FIELD_NAME (type, 1) + && strcmp (TYPE_FIELD_NAME (type, 1), "st") == 0) { if (length_pos) *length_pos = TYPE_FIELD_BITPOS (type, 0) / TARGET_CHAR_BIT; @@ -118,14 +120,16 @@ is_pascal_string_type (struct type *type,int *length_pos, if (char_type) *char_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1)); if (arrayname) - *arrayname = TYPE_FIELDS (type)[1].name; + *arrayname = TYPE_FIELD_NAME (type, 1); return 2; }; /* GNU pascal strings. */ /* Three fields: Capacity, length and schema$ or _p_schema. */ if (TYPE_NFIELDS (type) == 3 - && strcmp (TYPE_FIELDS (type)[0].name, "Capacity") == 0 - && strcmp (TYPE_FIELDS (type)[1].name, "length") == 0) + && TYPE_FIELD_NAME (type, 0) + && strcmp (TYPE_FIELD_NAME (type, 0), "Capacity") == 0 + && TYPE_FIELD_NAME (type, 1) + && strcmp (TYPE_FIELD_NAME (type, 1), "length") == 0) { if (length_pos) *length_pos = TYPE_FIELD_BITPOS (type, 1) / TARGET_CHAR_BIT; @@ -133,7 +137,7 @@ is_pascal_string_type (struct type *type,int *length_pos, *length_size = TYPE_LENGTH (TYPE_FIELD_TYPE (type, 1)); if (string_pos) *string_pos = TYPE_FIELD_BITPOS (type, 2) / TARGET_CHAR_BIT; - /* FIXME: how can I detect wide chars in GPC ?? */ + /* FIXME: how can I detect wide chars in GPC ?? */ if (char_type) { *char_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 2)); @@ -142,7 +146,7 @@ is_pascal_string_type (struct type *type,int *length_pos, *char_type = TYPE_TARGET_TYPE (*char_type); } if (arrayname) - *arrayname = TYPE_FIELDS (type)[2].name; + *arrayname = TYPE_FIELD_NAME (type, 2); return 3; }; } @@ -153,7 +157,7 @@ static void pascal_one_char (int, struct ui_file *, int *); /* Print the character C on STREAM as part of the contents of a literal string. - In_quotes is reset to 0 if a char is written with #4 notation */ + In_quotes is reset to 0 if a char is written with #4 notation. */ static void pascal_one_char (int c, struct ui_file *stream, int *in_quotes) @@ -184,7 +188,7 @@ static void pascal_emit_char (int c, struct type *type, /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. Note that that format for printing - characters and strings is language specific. */ + characters and strings is language specific. */ static void pascal_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) @@ -222,7 +226,11 @@ pascal_printstr (struct ui_file *stream, struct type *type, unsigned int things_printed = 0; int in_quotes = 0; int need_comma = 0; - int width = TYPE_LENGTH (type); + int width; + + /* Preserve TYPE's original type, just set its LENGTH. */ + check_typedef (type); + width = TYPE_LENGTH (type); /* If the string was not truncated due to `set print elements', and the last byte of it is a null, we don't print that, in traditional C @@ -260,7 +268,7 @@ pascal_printstr (struct ui_file *stream, struct type *type, rep1 = i + 1; reps = 1; - while (rep1 < length + while (rep1 < length && extract_unsigned_integer (string + rep1 * width, width, byte_order) == current_char) { diff --git a/contrib/gdb-7/gdb/p-lang.h b/contrib/gdb-7/gdb/p-lang.h index 7e076d5c90..c284c1dfa5 100644 --- a/contrib/gdb-7/gdb/p-lang.h +++ b/contrib/gdb-7/gdb/p-lang.h @@ -1,6 +1,6 @@ /* Pascal language support definitions for GDB, the GNU debugger. - Copyright (C) 2000, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -49,7 +49,7 @@ extern void pascal_type_print_method_args (char *, char *, /* These are in p-lang.c: */ -extern int +extern int is_pascal_string_type (struct type *, int *, int *, int *, struct type **, char **); @@ -70,6 +70,7 @@ extern void pascal_type_print_varspec_prefix (struct type *, struct ui_file *, int, int); extern void pascal_object_print_value_fields (struct type *, const gdb_byte *, + int, CORE_ADDR, struct ui_file *, int, const struct value *, diff --git a/contrib/gdb-7/gdb/p-typeprint.c b/contrib/gdb-7/gdb/p-typeprint.c index c0752b7d78..54a761d464 100644 --- a/contrib/gdb-7/gdb/p-typeprint.c +++ b/contrib/gdb-7/gdb/p-typeprint.c @@ -1,5 +1,5 @@ /* Support for printing Pascal types for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2002, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2002, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -36,11 +36,14 @@ #include #include -static void pascal_type_print_varspec_suffix (struct type *, struct ui_file *, int, int, int); +static void pascal_type_print_varspec_suffix (struct type *, struct ui_file *, + int, int, int); -static void pascal_type_print_derivation_info (struct ui_file *, struct type *); +static void pascal_type_print_derivation_info (struct ui_file *, + struct type *); -void pascal_type_print_varspec_prefix (struct type *, struct ui_file *, int, int); +void pascal_type_print_varspec_prefix (struct type *, struct ui_file *, + int, int); /* LEVEL is the depth to indent lines by. */ @@ -80,7 +83,7 @@ pascal_print_type (struct type *type, const char *varstring, pascal_type_print_base (type, stream, show, level); /* For demangled function names, we have the arglist as part of the name, - so don't print an additional pair of ()'s */ + so don't print an additional pair of ()'s. */ demangled_args = varstring ? strchr (varstring, '(') != NULL : 0; pascal_type_print_varspec_suffix (type, stream, show, 0, demangled_args); @@ -104,7 +107,7 @@ pascal_print_typedef (struct type *type, struct symbol *new_symbol, /* If TYPE is a derived type, then print out derivation information. Print only the actual base classes of this type, not the base classes - of the base classes. I.E. for the derivation hierarchy: + of the base classes. I.e. for the derivation hierarchy: class A { int a; }; class B : public A {int b; }; @@ -124,7 +127,7 @@ pascal_print_typedef (struct type *type, struct symbol *new_symbol, } In general, gdb should try to print the types as closely as possible to - the form that they appear in the source code. */ + the form that they appear in the source code. */ static void pascal_type_print_derivation_info (struct ui_file *stream, struct type *type) @@ -165,14 +168,15 @@ pascal_type_print_method_args (char *physname, char *methodname, if (physname && (*physname != 0)) { - int i = 0; - int len = 0; - char storec; - char *argname; fputs_filtered (" (", stream); - /* we must demangle this */ + /* We must demangle this. */ while (isdigit (physname[0])) { + int len = 0; + int i; + char storec; + char *argname; + while (isdigit (physname[len])) { len++; @@ -218,7 +222,8 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_PTR: fprintf_filtered (stream, "^"); pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - break; /* pointer should be handled normally in pascal */ + break; /* Pointer should be handled normally + in pascal. */ case TYPE_CODE_METHOD: if (passed_a_ptr) @@ -235,7 +240,8 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream, if (passed_a_ptr) { fprintf_filtered (stream, " "); - pascal_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); + pascal_type_print_base (TYPE_DOMAIN_TYPE (type), + stream, 0, passed_a_ptr); fprintf_filtered (stream, "::"); } break; @@ -313,12 +319,13 @@ pascal_print_func_args (struct type *type, struct ui_file *stream) fputs_filtered (", ", stream); wrap_here (" "); } - /* can we find if it is a var parameter ?? + /* Can we find if it is a var parameter ?? if ( TYPE_FIELD(type, i) == ) { fprintf_filtered (stream, "var "); } */ - pascal_print_type (TYPE_FIELD_TYPE (type, i), "" /* TYPE_FIELD_NAME seems invalid ! */ + pascal_print_type (TYPE_FIELD_TYPE (type, i), "" /* TYPE_FIELD_NAME + seems invalid! */ ,stream, -1, 0); } if (len) @@ -360,7 +367,8 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream, if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { fprintf_filtered (stream, " : "); - pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, 0, 0); pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0); pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, passed_a_ptr, 0); @@ -369,7 +377,8 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream, case TYPE_CODE_PTR: case TYPE_CODE_REF: - pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0); + pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), + stream, 0, 1, 0); break; case TYPE_CODE_FUNC: @@ -380,7 +389,8 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream, if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { fprintf_filtered (stream, " : "); - pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, 0, 0); pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0); pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, passed_a_ptr, 0); @@ -450,7 +460,8 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, } /* void pointer */ - if ((TYPE_CODE (type) == TYPE_CODE_PTR) && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)) + if ((TYPE_CODE (type) == TYPE_CODE_PTR) + && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)) { fputs_filtered (TYPE_NAME (type) ? TYPE_NAME (type) : "pointer", stream); @@ -479,9 +490,12 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_ARRAY: - /* pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); - pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); - pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); */ + /* pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, 0, 0); + pascal_type_print_base (TYPE_TARGET_TYPE (type), + stream, show, level); + pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), + stream, 0, 0, 0); */ pascal_print_type (TYPE_TARGET_TYPE (type), NULL, stream, 0, 0); break; @@ -489,7 +503,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, case TYPE_CODE_METHOD: /* pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); - only after args !! */ + only after args !! */ break; case TYPE_CODE_STRUCT: if (TYPE_TAG_NAME (type) != NULL) @@ -538,7 +552,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, /* Start off with no specific section type, so we can print one for the first field we find, and use that section type - thereafter until we find another type. */ + thereafter until we find another type. */ section_type = s_none; @@ -555,7 +569,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, continue; /* If this is a pascal object or class we can print the - various section labels. */ + various section labels. */ if (HAVE_CPLUS_STRUCT (type)) { @@ -606,12 +620,12 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, fprintf_filtered (stream, ";\n"); } - /* If there are both fields and methods, put a space between. */ + /* If there are both fields and methods, put a space between. */ len = TYPE_NFN_FIELDS (type); if (len && section_type != s_none) fprintf_filtered (stream, "\n"); - /* Pbject pascal: print out the methods */ + /* Object pascal: print out the methods. */ for (i = 0; i < len; i++) { @@ -621,7 +635,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, /* this is GNU C++ specific how can we know constructor/destructor? - It might work for GNU pascal */ + It might work for GNU pascal. */ for (j = 0; j < len2; j++) { char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); @@ -685,7 +699,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, { fprintf_filtered (stream, "procedure "); } - /* this does not work, no idea why !! */ + /* This does not work, no idea why !! */ pascal_type_print_method_args (physname, method_name, @@ -717,7 +731,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, fputs_filtered (" ", stream); } /* enum is just defined by - type enume_name = (enum_member1,enum_member2,...) */ + type enume_name = (enum_member1,enum_member2,...) */ fprintf_filtered (stream, " = "); wrap_here (" "); if (show < 0) @@ -740,7 +754,8 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, fputs_filtered (TYPE_FIELD_NAME (type, i), stream); if (lastval != TYPE_FIELD_BITPOS (type, i)) { - fprintf_filtered (stream, " := %d", TYPE_FIELD_BITPOS (type, i)); + fprintf_filtered (stream, + " := %d", TYPE_FIELD_BITPOS (type, i)); lastval = TYPE_FIELD_BITPOS (type, i); } lastval++; @@ -761,7 +776,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type)); break; - /* this probably does not work for enums */ + /* this probably does not work for enums. */ case TYPE_CODE_RANGE: { struct type *target = TYPE_TARGET_TYPE (type); @@ -790,7 +805,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, /* Handle types not explicitly handled by the other cases, such as fundamental types. For these, just print whatever the type name is, as recorded in the type itself. If there - is no type name, then complain. */ + is no type name, then complain. */ if (TYPE_NAME (type) != NULL) { fputs_filtered (TYPE_NAME (type), stream); diff --git a/contrib/gdb-7/gdb/p-valprint.c b/contrib/gdb-7/gdb/p-valprint.c index 4d39bed265..d2efa5b3d2 100644 --- a/contrib/gdb-7/gdb/p-valprint.c +++ b/contrib/gdb-7/gdb/p-valprint.c @@ -1,6 +1,6 @@ /* Support for printing Pascal values for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -38,17 +38,12 @@ #include "p-lang.h" #include "cp-abi.h" #include "cp-support.h" +#include "exceptions.h" - - -/* Print data of type TYPE located at VALADDR (within GDB), which came from - the inferior at address ADDRESS, onto stdio stream STREAM according to - OPTIONS. The data at VALADDR is in target byte order. - - If the data are a string pointer, returns the number of string characters - printed. */ - +/* See val_print for a description of the various parameters of this + function; they are identical. The semantics of the return value is + also identical to val_print. */ int pascal_val_print (struct type *type, const gdb_byte *valaddr, @@ -73,7 +68,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - if (get_array_bounds (type, &low_bound, &high_bound)) + if (get_array_bounds (type, &low_bound, &high_bound)) { len = high_bound - low_bound + 1; elttype = check_typedef (TYPE_TARGET_TYPE (type)); @@ -96,7 +91,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, { unsigned int temp_len; - /* Look for a NULL char. */ + /* Look for a NULL char. */ for (temp_len = 0; extract_unsigned_integer (valaddr + embedded_offset + temp_len * eltlen, eltlen, @@ -125,35 +120,36 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, { i = 0; } - val_print_array_elements (type, valaddr + embedded_offset, address, stream, - recurse, original_value, options, i); + val_print_array_elements (type, valaddr, embedded_offset, + address, stream, recurse, + original_value, options, i); fprintf_filtered (stream, "}"); } break; } /* Array of unspecified length: treat like pointer to first elt. */ - addr = address; + addr = address + embedded_offset; goto print_unpacked_pointer; case TYPE_CODE_PTR: if (options->format && options->format != 's') { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } if (options->vtblprint && pascal_object_is_vtbl_ptr_type (type)) { /* Print the unmangled name if desired. */ /* Print vtable entry - we only get here if we ARE using - -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ + -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ /* Extract the address, assume that it is unsigned. */ addr = extract_unsigned_integer (valaddr + embedded_offset, TYPE_LENGTH (type), byte_order); print_address_demangle (gdbarch, addr, stream, demangle); break; } - elttype = check_typedef (TYPE_TARGET_TYPE (type)); + check_typedef (TYPE_TARGET_TYPE (type)); addr = unpack_pointer (type, valaddr + embedded_offset); print_unpacked_pointer: @@ -182,14 +178,14 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, && (options->format == 0 || options->format == 's') && addr != 0) { - /* no wide string yet */ - i = val_print_string (elttype, addr, -1, stream, options); + /* No wide string yet. */ + i = val_print_string (elttype, NULL, addr, -1, stream, options); } - /* also for pointers to pascal strings */ + /* Also for pointers to pascal strings. */ /* Note: this is Free Pascal specific: as GDB does not recognize stabs pascal strings Pascal strings are mapped to records - with lowercase names PM */ + with lowercase names PM. */ if (is_pascal_string_type (elttype, &length_pos, &length_size, &string_pos, &char_type, NULL) && addr != 0) @@ -202,12 +198,15 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, string_length = extract_unsigned_integer (buffer, length_size, byte_order); xfree (buffer); - i = val_print_string (char_type ,addr + string_pos, string_length, stream, options); + i = val_print_string (char_type, NULL, + addr + string_pos, string_length, + stream, options); } else if (pascal_object_is_vtbl_member (type)) { - /* print vtbl's nicely */ - CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset); + /* Print vtbl's nicely. */ + CORE_ADDR vt_address = unpack_pointer (type, + valaddr + embedded_offset); struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (vt_address); @@ -298,12 +297,16 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, { /* Print the unmangled name if desired. */ /* Print vtable entry - we only get here if NOT using - -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */ + -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */ /* Extract the address, assume that it is unsigned. */ print_address_demangle (gdbarch, - extract_unsigned_integer (valaddr + embedded_offset + TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8, - TYPE_LENGTH (TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET)), byte_order), + extract_unsigned_integer (valaddr + embedded_offset + + TYPE_FIELD_BITPOS (type, + VTBL_FNADDR_OFFSET) / 8, + TYPE_LENGTH (TYPE_FIELD_TYPE (type, + VTBL_FNADDR_OFFSET)), + byte_order), stream, demangle); } else @@ -311,22 +314,26 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, if (is_pascal_string_type (type, &length_pos, &length_size, &string_pos, &char_type, NULL)) { - len = extract_unsigned_integer (valaddr + embedded_offset + length_pos, length_size, byte_order); - LA_PRINT_STRING (stream, char_type, + len = extract_unsigned_integer (valaddr + embedded_offset + + length_pos, length_size, + byte_order); + LA_PRINT_STRING (stream, char_type, valaddr + embedded_offset + string_pos, len, NULL, 0, options); } else - pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream, - recurse, original_value, options, NULL, 0); + pascal_object_print_value_fields (type, valaddr, embedded_offset, + address, stream, recurse, + original_value, options, + NULL, 0); } break; case TYPE_CODE_ENUM: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } len = TYPE_NFIELDS (type); @@ -351,8 +358,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, case TYPE_CODE_FLAGS: if (options->format) - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); else val_print_type_code_flags (type, valaddr + embedded_offset, stream); break; @@ -360,8 +367,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, case TYPE_CODE_FUNC: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); break; } /* FIXME, we should consider, at least for ANSI C language, eliminating @@ -380,8 +387,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -415,8 +422,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -431,8 +438,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, opts.format = (options->format ? options->format : options->output_format); - print_scalar_formatted (valaddr + embedded_offset, type, - &opts, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, &opts, 0, stream); } else { @@ -449,8 +456,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, case TYPE_CODE_FLT: if (options->format) { - print_scalar_formatted (valaddr + embedded_offset, type, - options, 0, stream); + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); } else { @@ -499,7 +506,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, for (i = low_bound; i <= high_bound; i++) { - int element = value_bit_index (type, valaddr + embedded_offset, i); + int element = value_bit_index (type, + valaddr + embedded_offset, i); if (element < 0) { @@ -515,13 +523,17 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, print_type_scalar (range, i, stream); need_comma = 1; - if (i + 1 <= high_bound && value_bit_index (type, valaddr + embedded_offset, ++i)) + if (i + 1 <= high_bound + && value_bit_index (type, + valaddr + embedded_offset, ++i)) { int j = i; fputs_filtered ("..", stream); while (i + 1 <= high_bound - && value_bit_index (type, valaddr + embedded_offset, ++i)) + && value_bit_index (type, + valaddr + embedded_offset, + ++i)) j = i; print_type_scalar (range, j, stream); } @@ -551,7 +563,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, break; default: - error (_("Invalid pascal type code %d in symbol table."), TYPE_CODE (type)); + error (_("Invalid pascal type code %d in symbol table."), + TYPE_CODE (type)); } gdb_flush (stream); return (0); @@ -576,13 +589,13 @@ pascal_value_print (struct value *val, struct ui_file *stream, || TYPE_CODE (type) == TYPE_CODE_REF) { /* Hack: remove (char *) for char strings. Their - type is indicated by the quoted string anyway. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR + type is indicated by the quoted string anyway. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_NAME (type) == NULL && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0) { - /* Print nothing */ + /* Print nothing. */ } else { @@ -611,6 +624,7 @@ static void pascal_object_print_static_field (struct value *, const struct value_print_options *); static void pascal_object_print_value (struct type *, const gdb_byte *, + int, CORE_ADDR, struct ui_file *, int, const struct value *, const struct value_print_options *, @@ -644,11 +658,12 @@ pascal_object_is_vtbl_member (struct type *type) if (TYPE_CODE (type) == TYPE_CODE_ARRAY) { type = TYPE_TARGET_TYPE (type); - if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* if not using thunks */ - || TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* If not using + thunks. */ + || TYPE_CODE (type) == TYPE_CODE_PTR) /* If using thunks. */ { /* Virtual functions tables are full of pointers - to virtual functions. */ + to virtual functions. */ return pascal_object_is_vtbl_ptr_type (type); } } @@ -668,6 +683,7 @@ pascal_object_is_vtbl_member (struct type *type) void pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, + int offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, @@ -687,8 +703,9 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, /* Print out baseclasses such that we don't print duplicates of virtual baseclasses. */ if (n_baseclasses > 0) - pascal_object_print_value (type, valaddr, address, stream, - recurse + 1, val, options, dont_print_vb); + pascal_object_print_value (type, valaddr, offset, address, + stream, recurse + 1, val, + options, dont_print_vb); if (!len && n_baseclasses == 1) fprintf_filtered (stream, ""); @@ -777,17 +794,24 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, { fputs_filtered ("", stream); } + else if (value_bits_synthetic_pointer (val, + TYPE_FIELD_BITPOS (type, + i), + TYPE_FIELD_BITSIZE (type, + i))) + { + fputs_filtered (_(""), stream); + } else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i), TYPE_FIELD_BITSIZE (type, i))) { - fputs_filtered (_(""), stream); + val_print_optimized_out (stream); } else { struct value_print_options opts = *options; - v = value_from_longest (TYPE_FIELD_TYPE (type, i), - unpack_field_as_long (type, valaddr, i)); + v = value_field_bitfield (type, i, valaddr, offset, val); opts.deref_ref = 0; common_val_print (v, stream, recurse + 1, &opts, @@ -802,14 +826,14 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, } else if (field_is_static (&TYPE_FIELD (type, i))) { - /* struct value *v = value_static_field (type, i); v4.17 specific */ + /* struct value *v = value_static_field (type, i); + v4.17 specific. */ struct value *v; - v = value_from_longest (TYPE_FIELD_TYPE (type, i), - unpack_field_as_long (type, valaddr, i)); + v = value_field_bitfield (type, i, valaddr, offset, val); if (v == NULL) - fputs_filtered ("", stream); + val_print_optimized_out (stream); else pascal_object_print_static_field (v, stream, recurse + 1, options); @@ -824,9 +848,8 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, address + TYPE_FIELD_BITPOS (type, i) / 8, 0, stream, format, 0, recurse + 1, pretty); */ val_print (TYPE_FIELD_TYPE (type, i), - valaddr, TYPE_FIELD_BITPOS (type, i) / 8, - address + TYPE_FIELD_BITPOS (type, i) / 8, - stream, recurse + 1, val, &opts, + valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8, + address, stream, recurse + 1, val, &opts, current_language); } } @@ -855,6 +878,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, static void pascal_object_print_value (struct type *type, const gdb_byte *valaddr, + int offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, @@ -877,10 +901,13 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr, for (i = 0; i < n_baseclasses; i++) { - int boffset; + int boffset = 0; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); char *basename = type_name_no_tag (baseclass); - const gdb_byte *base_valaddr; + const gdb_byte *base_valaddr = NULL; + int thisoffset; + volatile struct gdb_exception ex; + int skip = 0; if (BASETYPE_VIA_VIRTUAL (type, i)) { @@ -897,7 +924,40 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr, obstack_ptr_grow (&dont_print_vb_obstack, baseclass); } - boffset = baseclass_offset (type, i, valaddr, address); + thisoffset = offset; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + boffset = baseclass_offset (type, i, valaddr, offset, address, val); + } + if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + skip = -1; + else if (ex.reason < 0) + skip = 1; + else + { + skip = 0; + + /* The virtual base class pointer might have been clobbered by the + user program. Make sure that it still points to a valid memory + location. */ + + if (boffset < 0 || boffset >= TYPE_LENGTH (type)) + { + /* FIXME (alloc): not safe is baseclass is really really big. */ + gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); + + base_valaddr = buf; + if (target_read_memory (address + boffset, buf, + TYPE_LENGTH (baseclass)) != 0) + skip = 1; + address = address + boffset; + thisoffset = 0; + boffset = 0; + } + else + base_valaddr = valaddr; + } if (options->pretty) { @@ -911,27 +971,13 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr, fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); - /* The virtual base class pointer might have been clobbered by the - user program. Make sure that it still points to a valid memory - location. */ - - if (boffset != -1 && (boffset < 0 || boffset >= TYPE_LENGTH (type))) - { - /* FIXME (alloc): not safe is baseclass is really really big. */ - gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); - - base_valaddr = buf; - if (target_read_memory (address + boffset, buf, - TYPE_LENGTH (baseclass)) != 0) - boffset = -1; - } - else - base_valaddr = valaddr + boffset; - - if (boffset == -1) - fprintf_filtered (stream, ""); + if (skip < 0) + val_print_unavailable (stream); + else if (skip > 0) + val_print_invalid_address (stream); else - pascal_object_print_value_fields (baseclass, base_valaddr, address + boffset, + pascal_object_print_value_fields (baseclass, base_valaddr, + thisoffset + boffset, address, stream, recurse, val, options, (struct type **) obstack_base (&dont_print_vb_obstack), 0); @@ -984,7 +1030,8 @@ pascal_object_print_static_field (struct value *val, { if (value_address (val) == first_dont_print[i]) { - fputs_filtered ("", + fputs_filtered ("\ +", stream); return; } @@ -995,9 +1042,12 @@ pascal_object_print_static_field (struct value *val, sizeof (CORE_ADDR)); CHECK_TYPEDEF (type); - pascal_object_print_value_fields (type, value_contents (val), addr, - stream, recurse, NULL, options, - NULL, 1); + pascal_object_print_value_fields (type, + value_contents_for_printing (val), + value_embedded_offset (val), + addr, + stream, recurse, + val, options, NULL, 1); return; } @@ -1006,7 +1056,8 @@ pascal_object_print_static_field (struct value *val, common_val_print (val, stream, recurse, &opts, current_language); } -extern initialize_file_ftype _initialize_pascal_valprint; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_pascal_valprint; void _initialize_pascal_valprint (void) diff --git a/contrib/gdb-7/gdb/parse.c b/contrib/gdb-7/gdb/parse.c index c885c6a6d5..4815854c83 100644 --- a/contrib/gdb-7/gdb/parse.c +++ b/contrib/gdb-7/gdb/parse.c @@ -1,7 +1,7 @@ /* Parse expressions for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Modified from expread.y by the Department of Computer Science at the @@ -196,7 +196,7 @@ free_funcalls (void *ignore) /* Add one element to the end of the expression. */ /* To avoid a bug in the Sun 4 compiler, we pass things that can fit into - a register through here */ + a register through here. */ void write_exp_elt (union exp_element expelt) @@ -309,7 +309,7 @@ write_exp_elt_intern (struct internalvar *expelt) that contains the length of the string, then stuffing the string constant itself into however many expression elements are needed to hold it, and then writing another expression element that contains - the length of the string. I.E. an expression element at each end of + the length of the string. I.e. an expression element at each end of the string records the string length, so you can skip over the expression elements containing the actual string bytes from either end of the string. Note that this also allows gdb to handle @@ -321,7 +321,7 @@ write_exp_elt_intern (struct internalvar *expelt) actual length is recorded in expression elements at each end of the string. The null byte is taken into consideration when computing how many expression elements are required to hold the string constant, of - course. */ + course. */ void @@ -334,12 +334,12 @@ write_exp_string (struct stoken str) /* Compute the number of expression elements required to hold the string (including a null byte terminator), along with one expression element at each end to record the actual string length (not including the - null byte terminator). */ + null byte terminator). */ lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1); /* Ensure that we have enough available expression elements to store - everything. */ + everything. */ if ((expout_ptr + lenelt) >= expout_size) { @@ -352,7 +352,7 @@ write_exp_string (struct stoken str) /* Write the leading length expression element (which advances the current expression element index), then write the string constant followed by a terminating null byte, and then write the trailing length expression - element. */ + element. */ write_exp_elt_longcst ((LONGEST) len); strdata = (char *) &expout->elts[expout_ptr]; @@ -427,10 +427,10 @@ write_exp_string_vector (int type, struct stoken_vector *vec) that contains the length of the bitstring (in bits), then stuffing the bitstring constant itself into however many expression elements are needed to hold it, and then writing another expression element that - contains the length of the bitstring. I.E. an expression element at + contains the length of the bitstring. I.e. an expression element at each end of the bitstring records the bitstring length, so you can skip over the expression elements containing the actual bitstring bytes from - either end of the bitstring. */ + either end of the bitstring. */ void write_exp_bitstring (struct stoken str) @@ -442,12 +442,12 @@ write_exp_bitstring (struct stoken str) /* Compute the number of expression elements required to hold the bitstring, along with one expression element at each end to record the actual - bitstring length in bits. */ + bitstring length in bits. */ lenelt = 2 + BYTES_TO_EXP_ELEM (len); /* Ensure that we have enough available expression elements to store - everything. */ + everything. */ if ((expout_ptr + lenelt) >= expout_size) { @@ -459,7 +459,7 @@ write_exp_bitstring (struct stoken str) /* Write the leading length expression element (which advances the current expression element index), then write the bitstring constant, and then - write the trailing length expression element. */ + write the trailing length expression element. */ write_exp_elt_longcst ((LONGEST) bits); strdata = (char *) &expout->elts[expout_ptr]; @@ -487,9 +487,22 @@ write_exp_msymbol (struct minimal_symbol *msymbol) pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); if (pc != addr) { + struct minimal_symbol *ifunc_msym = lookup_minimal_symbol_by_pc (pc); + /* In this case, assume we have a code symbol instead of a data symbol. */ - type = mst_text; + + if (ifunc_msym != NULL && MSYMBOL_TYPE (ifunc_msym) == mst_text_gnu_ifunc + && SYMBOL_VALUE_ADDRESS (ifunc_msym) == pc) + { + /* A function descriptor has been resolved but PC is still in the + STT_GNU_IFUNC resolver body (such as because inferior does not + run to be able to call it). */ + + type = mst_text_gnu_ifunc; + } + else + type = mst_text; section = NULL; addr = pc; } @@ -521,6 +534,11 @@ write_exp_msymbol (struct minimal_symbol *msymbol) write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol); break; + case mst_text_gnu_ifunc: + write_exp_elt_type (objfile_type (objfile) + ->nodebug_text_gnu_ifunc_symbol); + break; + case mst_data: case mst_file_data: case mst_bss: @@ -528,6 +546,10 @@ write_exp_msymbol (struct minimal_symbol *msymbol) write_exp_elt_type (objfile_type (objfile)->nodebug_data_symbol); break; + case mst_slot_got_plt: + write_exp_elt_type (objfile_type (objfile)->nodebug_got_plt_symbol); + break; + default: write_exp_elt_type (objfile_type (objfile)->nodebug_unknown_symbol); break; @@ -557,16 +579,14 @@ mark_struct_expression (void) from the first value which has index 1. $$digits Value history with index relative - to the last value. I.E. $$0 is the last + to the last value. I.e. $$0 is the last value, $$1 is the one previous to that, $$2 is the one previous to $$1, etc. $ | $0 | $$0 The last value in the value history. $$ An abbreviation for the second to the last - value in the value history, I.E. $$1 - - */ + value in the value history, I.e. $$1 */ void write_dollar_variable (struct stoken str) @@ -576,7 +596,7 @@ write_dollar_variable (struct stoken str) struct internalvar *isym = NULL; /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1) - and $$digits (equivalent to $<-digits> if you could type that). */ + and $$digits (equivalent to $<-digits> if you could type that). */ int negate = 0; int i = 1; @@ -589,7 +609,7 @@ write_dollar_variable (struct stoken str) } if (i == str.length) { - /* Just dollars (one or two) */ + /* Just dollars (one or two). */ i = -negate; goto handle_last; } @@ -624,7 +644,7 @@ write_dollar_variable (struct stoken str) } /* On some systems, such as HP-UX and hppa-linux, certain system routines - have names beginning with $ or $$. Check for those, first. */ + have names beginning with $ or $$. Check for those, first. */ sym = lookup_symbol (copy_name (str), (struct block *) NULL, VAR_DOMAIN, (int *) NULL); @@ -683,7 +703,7 @@ find_template_name_end (char *p) case '\"': case '{': case '}': - /* In future, may want to allow these?? */ + /* In future, may want to allow these?? */ return 0; case '<': depth++; /* start nested template */ @@ -852,7 +872,7 @@ operator_length_standard (const struct expression *expr, int endpos, args = 1; break; - case OP_OBJC_MSGCALL: /* Objective C message (method) call */ + case OP_OBJC_MSGCALL: /* Objective C message (method) call. */ oplen = 4; args = 1 + longest_to_int (expr->elts[endpos - 2].longconst); break; @@ -903,8 +923,9 @@ operator_length_standard (const struct expression *expr, int endpos, case OP_REGISTER: case OP_M2_STRING: case OP_STRING: - case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant */ - case OP_OBJC_SELECTOR: /* Objective C "@selector" pseudo-op */ + case OP_OBJC_NSSTRING: /* Objective C Foundation Class + NSString constant. */ + case OP_OBJC_SELECTOR: /* Objective C "@selector" pseudo-op. */ case OP_NAME: oplen = longest_to_int (expr->elts[endpos - 2].longconst); oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1); @@ -1038,8 +1059,6 @@ prefixify_subexp (struct expression *inexpr, return result; } -/* This page contains the two entry points to this file. */ - /* Read an expression from the string *STRINGPTR points to, parse it, and return a pointer to a struct expression that we malloc. Use block BLOCK as the lexical context for variable names; @@ -1118,9 +1137,9 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, startup phase to re-parse breakpoint expressions after a new shared library has been loaded. The language associated to the current frame at this moment is not relevant for - the breakpoint. Using it would therefore be silly, so it seems + the breakpoint. Using it would therefore be silly, so it seems better to rely on the current language rather than relying on - the current frame language to parse the expression. That's why + the current frame language to parse the expression. That's why we do the following language detection only if the context block has been specifically provided. */ struct symbol *func = block_linkage_function (block); @@ -1158,15 +1177,15 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, /* Record the actual number of expression elements, and then reallocate the expression memory so that we free up any - excess elements. */ + excess elements. */ expout->nelts = expout_ptr; expout = (struct expression *) xrealloc ((char *) expout, - sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr));; + sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr)); /* Convert expression from postfix form as generated by yacc - parser, to a prefix form. */ + parser, to a prefix form. */ if (expressiondebug) dump_raw_expression (expout, gdb_stdlog, @@ -1202,8 +1221,10 @@ parse_expression (char *string) /* Parse STRING as an expression. If parsing ends in the middle of a field reference, return the type of the left-hand-side of the reference; furthermore, if the parsing ends in the field name, - return the field name in *NAME. In all other cases, return NULL. - Returned non-NULL *NAME must be freed by the caller. */ + return the field name in *NAME. If the parsing ends in the middle + of a field reference, but the reference is somehow invalid, throw + an exception. In all other cases, return NULL. Returned non-NULL + *NAME must be freed by the caller. */ struct type * parse_field_expression (char *string, char **name) @@ -1213,7 +1234,7 @@ parse_field_expression (char *string, char **name) int subexp; volatile struct gdb_exception except; - TRY_CATCH (except, RETURN_MASK_ALL) + TRY_CATCH (except, RETURN_MASK_ERROR) { in_parse_field = 1; exp = parse_exp_in_context (&string, 0, 0, 0, &subexp); @@ -1233,21 +1254,90 @@ parse_field_expression (char *string, char **name) xfree (exp); return NULL; } - /* (*NAME) is a part of the EXP memory block freed below. */ - *name = xstrdup (*name); + /* This might throw an exception. If so, we want to let it + propagate. */ val = evaluate_subexpression_type (exp, subexp); + /* (*NAME) is a part of the EXP memory block freed below. */ + *name = xstrdup (*name); xfree (exp); return value_type (val); } -/* A post-parser that does nothing */ +/* A post-parser that does nothing. */ void null_post_parser (struct expression **exp, int void_context_p) { } + +/* Parse floating point value P of length LEN. + Return 0 (false) if invalid, 1 (true) if valid. + The successfully parsed number is stored in D. + *SUFFIX points to the suffix of the number in P. + + NOTE: This accepts the floating point syntax that sscanf accepts. */ + +int +parse_float (const char *p, int len, DOUBLEST *d, const char **suffix) +{ + char *copy; + char *s; + int n, num; + + copy = xmalloc (len + 1); + memcpy (copy, p, len); + copy[len] = 0; + + num = sscanf (copy, "%" DOUBLEST_SCAN_FORMAT "%n", d, &n); + xfree (copy); + + /* The sscanf man page suggests not making any assumptions on the effect + of %n on the result, so we don't. + That is why we simply test num == 0. */ + if (num == 0) + return 0; + + *suffix = p + n; + return 1; +} + +/* Parse floating point value P of length LEN, using the C syntax for floats. + Return 0 (false) if invalid, 1 (true) if valid. + The successfully parsed number is stored in *D. + Its type is taken from builtin_type (gdbarch) and is stored in *T. */ + +int +parse_c_float (struct gdbarch *gdbarch, const char *p, int len, + DOUBLEST *d, struct type **t) +{ + const char *suffix; + int suffix_len; + const struct builtin_type *builtin_types = builtin_type (gdbarch); + + if (! parse_float (p, len, d, &suffix)) + return 0; + + suffix_len = p + len - suffix; + + if (suffix_len == 0) + *t = builtin_types->builtin_double; + else if (suffix_len == 1) + { + /* Handle suffixes: 'f' for float, 'l' for long double. */ + if (tolower (*suffix) == 'f') + *t = builtin_types->builtin_float; + else if (tolower (*suffix) == 'l') + *t = builtin_types->builtin_long_double; + else + return 0; + } + else + return 0; + + return 1; +} /* Stuff for maintaining a stack of types. Currently just used by C, but probably useful for any language which declares its types "backwards". */ @@ -1559,18 +1649,20 @@ _initialize_parse (void) xmalloc (type_stack_size * sizeof (*type_stack)); add_setshow_zinteger_cmd ("expression", class_maintenance, - &expressiondebug, _("\ -Set expression debugging."), _("\ -Show expression debugging."), _("\ -When non-zero, the internal representation of expressions will be printed."), + &expressiondebug, + _("Set expression debugging."), + _("Show expression debugging."), + _("When non-zero, the internal representation " + "of expressions will be printed."), NULL, show_expressiondebug, &setdebuglist, &showdebuglist); add_setshow_boolean_cmd ("parser", class_maintenance, - &parser_debug, _("\ -Set parser debugging."), _("\ -Show parser debugging."), _("\ -When non-zero, expression parser tracing will be enabled."), + &parser_debug, + _("Set parser debugging."), + _("Show parser debugging."), + _("When non-zero, expression parser " + "tracing will be enabled."), NULL, show_parserdebug, &setdebuglist, &showdebuglist); diff --git a/contrib/gdb-7/gdb/parser-defs.h b/contrib/gdb-7/gdb/parser-defs.h index bb79ae1391..3f743d15be 100644 --- a/contrib/gdb-7/gdb/parser-defs.h +++ b/contrib/gdb-7/gdb/parser-defs.h @@ -1,7 +1,7 @@ /* Parser definitions for GDB. Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2002, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Modified from expread.y by the Department of Computer Science at the @@ -50,7 +50,7 @@ extern struct block *expression_context_block; extern CORE_ADDR expression_context_pc; /* The innermost context required by the stack and register variables - we've encountered so far. */ + we've encountered so far. */ extern struct block *innermost_block; /* The block in which the most recently discovered symbol was found. @@ -62,13 +62,13 @@ extern struct block *block_found; extern int arglist_len; /* A string token, either a char-string or bit-string. Char-strings are - used, for example, for the names of symbols. */ + used, for example, for the names of symbols. */ struct stoken { - /* Pointer to first byte of char-string or first bit of bit-string */ + /* Pointer to first byte of char-string or first bit of bit-string. */ char *ptr; - /* Length of string in bytes for char-string or bits for bit-string */ + /* Length of string in bytes for char-string or bits for bit-string. */ int length; }; @@ -76,9 +76,9 @@ struct typed_stoken { /* A language-specific type field. */ int type; - /* Pointer to first byte of char-string or first bit of bit-string */ + /* Pointer to first byte of char-string or first bit of bit-string. */ char *ptr; - /* Length of string in bytes for char-string or bits for bit-string */ + /* Length of string in bytes for char-string or bits for bit-string. */ int length; }; @@ -204,12 +204,18 @@ extern struct type *follow_types (struct type *); extern void null_post_parser (struct expression **, int); +extern int parse_float (const char *p, int len, DOUBLEST *d, + const char **suffix); + +extern int parse_c_float (struct gdbarch *gdbarch, const char *p, int len, + DOUBLEST *d, struct type **t); + /* During parsing of a C expression, the pointer to the next character is in this variable. */ extern char *lexptr; -/* After a token has been recognized, this variable points to it. +/* After a token has been recognized, this variable points to it. Currently used only for error reporting. */ extern char *prev_lexptr; @@ -259,7 +265,7 @@ struct op_print enum precedence precedence; /* For a binary operator: 1 iff right associate. - For a unary operator: 1 iff postfix. */ + For a unary operator: 1 iff postfix. */ int right_assoc; }; diff --git a/contrib/gdb-7/gdb/posix-hdep.c b/contrib/gdb-7/gdb/posix-hdep.c index bcc1dee02e..9bd3a9a072 100644 --- a/contrib/gdb-7/gdb/posix-hdep.c +++ b/contrib/gdb-7/gdb/posix-hdep.c @@ -1,6 +1,7 @@ /* Host support routines for MinGW, for GDB, the GNU debugger. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -26,7 +27,7 @@ /* The strerror() function can return NULL for errno values that are out of range. Provide a "safe" version that always returns a - printable string. */ + printable string. */ char * safe_strerror (int errnum) diff --git a/contrib/gdb-7/gdb/printcmd.c b/contrib/gdb-7/gdb/printcmd.c index 5ffa099d87..f1ebb7e9e0 100644 --- a/contrib/gdb-7/gdb/printcmd.c +++ b/contrib/gdb-7/gdb/printcmd.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -49,9 +49,10 @@ #include "parser-defs.h" #include "charset.h" #include "arch-utils.h" +#include "cli/cli-utils.h" #ifdef TUI -#include "tui/tui.h" /* For tui_active et.al. */ +#include "tui/tui.h" /* For tui_active et al. */ #endif #if defined(__MINGW32__) && !defined(PRINTF_HAS_LONG_LONG) @@ -61,7 +62,8 @@ # define USE_PRINTF_I64 0 #endif -extern int asm_demangle; /* Whether to demangle syms in asm printouts */ +extern int asm_demangle; /* Whether to demangle syms in asm + printouts. */ struct format_data { @@ -108,8 +110,9 @@ static void show_max_symbolic_offset (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The largest offset that will be printed in form is %s.\n"), + fprintf_filtered (file, + _("The largest offset that will be " + "printed in form is %s.\n"), value); } @@ -120,8 +123,8 @@ static void show_print_symbol_filename (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Printing of source filename and line number with is %s.\n"), + fprintf_filtered (file, _("Printing of source filename and " + "line number with is %s.\n"), value); } @@ -151,10 +154,10 @@ struct display /* Program space associated with `block'. */ struct program_space *pspace; - /* Innermost block required by this expression when evaluated */ + /* Innermost block required by this expression when evaluated. */ struct block *block; - /* Status of this display (enabled or disabled) */ + /* Status of this display (enabled or disabled). */ int enabled_p; }; @@ -165,13 +168,25 @@ static struct display *display_chain; static int display_number; -/* Prototypes for exported functions. */ +/* Walk the following statement or block through all displays. + ALL_DISPLAYS_SAFE does so even if the statement deletes the current + display. */ + +#define ALL_DISPLAYS(B) \ + for (B = display_chain; B; B = B->next) + +#define ALL_DISPLAYS_SAFE(B,TMP) \ + for (B = display_chain; \ + B ? (TMP = B->next, 1): 0; \ + B = TMP) + +/* Prototypes for exported functions. */ void output_command (char *, int); void _initialize_printcmd (void); -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static void do_one_display (struct display *); @@ -260,7 +275,8 @@ decode_format (char **string_ptr, int oformat, int osize) val.size = osize ? 'b' : osize; break; case 's': - /* Display strings with byte size chars unless explicitly specified. */ + /* Display strings with byte size chars unless explicitly + specified. */ val.size = '\0'; break; @@ -298,7 +314,7 @@ print_formatted (struct value *val, int size, struct type *elttype = value_type (val); next_address = (value_address (val) - + val_print_string (elttype, + + val_print_string (elttype, NULL, value_address (val), -1, stream, options) * len); } @@ -324,10 +340,13 @@ print_formatted (struct value *val, int size, || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) value_print (val, stream, options); else - /* User specified format, so don't look to the the type to - tell us what to do. */ - print_scalar_formatted (value_contents (val), type, - options, size, stream); + /* User specified format, so don't look to the type to tell us + what to do. */ + val_print_scalar_formatted (type, + value_contents_for_printing (val), + value_embedded_offset (val), + val, + options, size, stream); } /* Return builtin floating point type of same length as TYPE. @@ -350,11 +369,8 @@ float_type_from_length (struct type *type) } /* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, - according to OPTIONS and SIZE on STREAM. - Formats s and i are not supported at this level. - - This is how the elements of an array or structure are printed - with a format. */ + according to OPTIONS and SIZE on STREAM. Formats s and i are not + supported at this level. */ void print_scalar_formatted (const void *valaddr, struct type *type, @@ -366,18 +382,8 @@ print_scalar_formatted (const void *valaddr, struct type *type, unsigned int len = TYPE_LENGTH (type); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - /* If we get here with a string format, try again without it. Go - all the way back to the language printers, which may call us - again. */ - if (options->format == 's') - { - struct value_print_options opts = *options; - opts.format = 0; - opts.deref_ref = 0; - val_print (type, valaddr, 0, 0, stream, 0, NULL, &opts, - current_language); - return; - } + /* String printing should go through val_print_scalar_formatted. */ + gdb_assert (options->format != 's'); if (len > sizeof(LONGEST) && (TYPE_CODE (type) == TYPE_CODE_INT @@ -534,7 +540,7 @@ print_scalar_formatted (const void *valaddr, struct type *type, if (*cp == '\0') cp--; } - strcpy (buf, cp); + strncpy (buf, cp, sizeof (bits)); fputs_filtered (buf, stream); } break; @@ -617,11 +623,11 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, } /* Given an address ADDR return all the elements needed to print the - address in a symbolic form. NAME can be mangled or not depending + address in a symbolic form. NAME can be mangled or not depending on DO_DEMANGLE (and also on the asm_demangle global variable, - manipulated via ''set print asm-demangle''). Return 0 in case of - success, when all the info in the OUT paramters is valid. Return 1 - otherwise. */ + manipulated via ''set print asm-demangle''). Return 0 in case of + success, when all the info in the OUT paramters is valid. Return 1 + otherwise. */ int build_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, /* IN */ @@ -753,9 +759,7 @@ pc_prefix (CORE_ADDR addr) CORE_ADDR pc; frame = get_selected_frame (NULL); - pc = get_frame_pc (frame); - - if (pc == addr) + if (get_frame_pc_if_available (frame, &pc) && pc == addr) return "=> "; } return " "; @@ -855,8 +859,8 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) else { if (size != '\0' && size != 'b') - warning (_("Unable to display strings with size '%c', using 'b' \ -instead."), size); + warning (_("Unable to display strings with " + "size '%c', using 'b' instead."), size); size = 'b'; val_type = builtin_type (next_gdbarch)->builtin_int8; } @@ -902,7 +906,7 @@ instead."), size); the address stored in LAST_EXAMINE_VALUE. FIXME: Should the disassembler be modified so that LAST_EXAMINE_VALUE is left with the byte sequence from the last complete - instruction fetched from memory? */ + instruction fetched from memory? */ last_examine_value = value_at_lazy (val_type, next_address); if (last_examine_value) @@ -1187,7 +1191,7 @@ address_info (char *exp, int from_tty) struct obj_section *section; CORE_ADDR load_addr, context_pc = 0; int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero - if exp is a field of `this'. */ + if exp is a field of `this'. */ if (exp == 0) error (_("Argument required.")); @@ -1273,7 +1277,8 @@ address_info (char *exp, int from_tty) Unfortunately DWARF 2 stores the frame-base (instead of the function) location in a function's symbol. Oops! For the moment enable this when/where applicable. */ - SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, context_pc, gdb_stdout); + SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, context_pc, + gdb_stdout); break; case LOC_REGISTER: @@ -1450,7 +1455,7 @@ x_command (char *exp, int from_tty) last_size = fmt.size; last_format = fmt.format; - /* Set a couple of internal variables if appropriate. */ + /* Set a couple of internal variables if appropriate. */ if (last_examine_value) { /* Make last address examined available to the user as $_. Use @@ -1561,48 +1566,85 @@ clear_displays (void) } } -/* Delete the auto-display number NUM. */ +/* Delete the auto-display DISPLAY. */ static void -delete_display (int num) +delete_display (struct display *display) { - struct display *d1, *d; + struct display *d; - if (!display_chain) - error (_("No display number %d."), num); + gdb_assert (display != NULL); - if (display_chain->number == num) - { - d1 = display_chain; - display_chain = d1->next; - free_display (d1); - } - else - for (d = display_chain;; d = d->next) + if (display_chain == display) + display_chain = display->next; + + ALL_DISPLAYS (d) + if (d->next == display) { - if (d->next == 0) - error (_("No display number %d."), num); - if (d->next->number == num) - { - d1 = d->next; - d->next = d1->next; - free_display (d1); - break; - } + d->next = display->next; + break; } + + free_display (display); } -/* Delete some values from the auto-display chain. - Specify the element numbers. */ +/* Call FUNCTION on each of the displays whose numbers are given in + ARGS. DATA is passed unmodified to FUNCTION. */ + +static void +map_display_numbers (char *args, + void (*function) (struct display *, + void *), + void *data) +{ + struct get_number_or_range_state state; + struct display *b, *tmp; + int num; + + if (args == NULL) + error_no_arg (_("one or more display numbers")); + + init_number_or_range (&state, args); + + while (!state.finished) + { + char *p = state.string; + + num = get_number_or_range (&state); + if (num == 0) + warning (_("bad display number at or near '%s'"), p); + else + { + struct display *d, *tmp; + + ALL_DISPLAYS_SAFE (d, tmp) + if (d->number == num) + break; + if (d == NULL) + printf_unfiltered (_("No display number %d.\n"), num); + else + function (d, data); + } + } +} + +/* Callback for map_display_numbers, that deletes a display. */ + +static void +do_delete_display (struct display *d, void *data) +{ + delete_display (d); +} + +/* "undisplay" command. */ static void undisplay_command (char *args, int from_tty) { - char *p = args; - char *p1; int num; + struct get_number_or_range_state state; - if (args == 0) + if (args == NULL) { if (query (_("Delete all auto-display expressions? "))) clear_displays (); @@ -1610,28 +1652,13 @@ undisplay_command (char *args, int from_tty) return; } - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); - - num = atoi (p); - - delete_display (num); - - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + map_display_numbers (args, do_delete_display, NULL); dont_repeat (); } /* Display a single auto-display. Do nothing if the display cannot be printed in the current context, - or if the display is disabled. */ + or if the display is disabled. */ static void do_one_display (struct display *d) @@ -1793,8 +1820,9 @@ disable_current_display (void) if (current_display_number >= 0) { disable_display (current_display_number); - fprintf_unfiltered (gdb_stderr, _("\ -Disabling display %d to avoid infinite recursion.\n"), + fprintf_unfiltered (gdb_stderr, + _("Disabling display %d to " + "avoid infinite recursion.\n"), current_display_number); } current_display_number = -1; @@ -1827,71 +1855,47 @@ Num Enb Expression\n")); } } +/* Callback fo map_display_numbers, that enables or disables the + passed in display D. */ + static void -enable_display (char *args, int from_tty) +do_enable_disable_display (struct display *d, void *data) { - char *p = args; - char *p1; - int num; - struct display *d; + d->enabled_p = *(int *) data; +} - if (p == 0) +/* Implamentation of both the "disable display" and "enable display" + commands. ENABLE decides what to do. */ + +static void +enable_disable_display_command (char *args, int from_tty, int enable) +{ + if (args == NULL) { - for (d = display_chain; d; d = d->next) - d->enabled_p = 1; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); + struct display *d; - num = atoi (p); + ALL_DISPLAYS (d) + d->enabled_p = enable; + return; + } - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->enabled_p = 1; - goto win; - } - printf_unfiltered (_("No display number %d.\n"), num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + map_display_numbers (args, do_enable_disable_display, &enable); } +/* The "enable display" command. */ + static void -disable_display_command (char *args, int from_tty) +enable_display_command (char *args, int from_tty) { - char *p = args; - char *p1; - struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d = d->next) - d->enabled_p = 0; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); + enable_disable_display_command (args, from_tty, 1); +} - disable_display (atoi (p)); +/* The "disable display" command. */ - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } +static void +disable_display_command (char *args, int from_tty) +{ + enable_disable_display_command (args, from_tty, 0); } /* display_chain items point to blocks and expressions. Some expressions in @@ -1984,9 +1988,7 @@ ui_printf (char *arg, struct ui_file *stream) if (s == 0) error_no_arg (_("format-control string and values to print")); - /* Skip white space before format string */ - while (*s == ' ' || *s == '\t') - s++; + s = skip_spaces (s); /* A format string should follow, enveloped in double quotes. */ if (*s++ != '"') @@ -2036,7 +2038,7 @@ ui_printf (char *arg, struct ui_file *stream) *f++ = '"'; break; default: - /* ??? TODO: handle other escape sequences */ + /* ??? TODO: handle other escape sequences. */ error (_("Unrecognized escape character \\%c in format string."), c); } @@ -2050,16 +2052,14 @@ ui_printf (char *arg, struct ui_file *stream) /* Skip over " and following space and comma. */ s++; *f++ = '\0'; - while (*s == ' ' || *s == '\t') - s++; + s = skip_spaces (s); if (*s != ',' && *s != 0) error (_("Invalid argument syntax")); if (*s == ',') s++; - while (*s == ' ' || *s == '\t') - s++; + s = skip_spaces (s); /* Need extra space for the '\0's. Doubling the size is sufficient. */ substrings = alloca (strlen (string) * 2); @@ -2258,7 +2258,8 @@ ui_printf (char *arg, struct ui_file *stream) } if (bad) - error (_("Inappropriate modifiers to format specifier '%c' in printf"), + error (_("Inappropriate modifiers to " + "format specifier '%c' in printf"), *f); f++; @@ -2756,7 +2757,7 @@ and examining is done as in the \"x\" command.\n\n\ With no argument, display all currently requested auto-display expressions.\n\ Use \"undisplay\" to cancel display requests previously made.")); - add_cmd ("display", class_vars, enable_display, _("\ + add_cmd ("display", class_vars, enable_display_command, _("\ Enable some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to resume displaying.\n\ No argument means enable all automatic-display expressions.\n\ @@ -2804,7 +2805,7 @@ Use \"set variable\" for variables with names identical to set subcommands.\n\ \nWith a subcommand, this command modifies parts of the gdb environment.\n\ You can see these environment settings with the \"show\" command.")); - /* "call" is the same as "set", but handy for dbx users to call fns. */ + /* "call" is the same as "set", but handy for dbx users to call fns. */ c = add_com ("call", class_vars, call_command, _("\ Call a function in the program.\n\ The argument is the function name and arguments, in the notation of the\n\ diff --git a/contrib/gdb-7/gdb/proc-service.list b/contrib/gdb-7/gdb/proc-service.list index 9b3eb43327..101dd1f151 100644 --- a/contrib/gdb-7/gdb/proc-service.list +++ b/contrib/gdb-7/gdb/proc-service.list @@ -1,6 +1,6 @@ /* -Wl,--dynamic-list symbols exported for libthread_db. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/progspace.c b/contrib/gdb-7/gdb/progspace.c index b1abcf929e..9f32cef6ec 100644 --- a/contrib/gdb-7/gdb/progspace.c +++ b/contrib/gdb-7/gdb/progspace.c @@ -1,6 +1,6 @@ /* Program and address space management, for GDB, the GNU debugger. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -596,7 +596,8 @@ set_program_space_data (struct program_space *pspace, } void * -program_space_data (struct program_space *pspace, const struct program_space_data *data) +program_space_data (struct program_space *pspace, + const struct program_space_data *data) { gdb_assert (data->index < pspace->num_data); return pspace->data[data->index]; @@ -608,8 +609,8 @@ void initialize_progspace (void) { add_cmd ("program-spaces", class_maintenance, - maintenance_info_program_spaces_command, _("\ -Info about currently known program spaces."), + maintenance_info_program_spaces_command, + _("Info about currently known program spaces."), &maintenanceinfolist); /* There's always one program space. Note that this function isn't diff --git a/contrib/gdb-7/gdb/progspace.h b/contrib/gdb-7/gdb/progspace.h index 8a6466a57e..5d3ed950f7 100644 --- a/contrib/gdb-7/gdb/progspace.h +++ b/contrib/gdb-7/gdb/progspace.h @@ -1,6 +1,6 @@ /* Program and address space management, for GDB, the GNU debugger. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -174,7 +174,7 @@ struct program_space struct objfile *symfile_object_file; /* All known objfiles are kept in a linked list. This points to - the head of this list. */ + the head of this list. */ struct objfile *objfiles; /* The set of target sections matching the sections mapped into @@ -196,7 +196,7 @@ struct program_space #define symfile_objfile current_program_space->symfile_object_file /* All known objfiles are kept in a linked list. This points to the - root of this list. */ + root of this list. */ #define object_files current_program_space->objfiles /* The set of target sections matching the sections mapped into the @@ -283,7 +283,8 @@ extern const struct program_space_data *register_program_space_data_with_cleanup (void (*cleanup) (struct program_space *, void *)); extern void clear_program_space_data (struct program_space *pspace); extern void set_program_space_data (struct program_space *pspace, - const struct program_space_data *data, void *value); + const struct program_space_data *data, + void *value); extern void *program_space_data (struct program_space *pspace, const struct program_space_data *data); diff --git a/contrib/gdb-7/gdb/prologue-value.c b/contrib/gdb-7/gdb/prologue-value.c index 4ff5a0c7f6..46c5b689d3 100644 --- a/contrib/gdb-7/gdb/prologue-value.c +++ b/contrib/gdb-7/gdb/prologue-value.c @@ -1,5 +1,5 @@ /* Prologue value handling for GDB. - Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ #include "defs.h" #include "gdb_string.h" @@ -203,7 +203,7 @@ pv_is_identical (pv_t a, pv_t b) case pvk_register: return (a.reg == b.reg && a.k == b.k); default: - gdb_assert (0); + gdb_assert_not_reached ("unexpected prologue value kind"); } } diff --git a/contrib/gdb-7/gdb/prologue-value.h b/contrib/gdb-7/gdb/prologue-value.h index a1706b283c..c8d45ffc9a 100644 --- a/contrib/gdb-7/gdb/prologue-value.h +++ b/contrib/gdb-7/gdb/prologue-value.h @@ -1,5 +1,5 @@ /* Interface to prologue value handling for GDB. - Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ #ifndef PROLOGUE_VALUE_H #define PROLOGUE_VALUE_H diff --git a/contrib/gdb-7/gdb/psympriv.h b/contrib/gdb-7/gdb/psympriv.h index 52f6e03c69..95d7676cbf 100644 --- a/contrib/gdb-7/gdb/psympriv.h +++ b/contrib/gdb-7/gdb/psympriv.h @@ -1,6 +1,6 @@ /* Private partial symbol table definitions. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,8 @@ #include "psymtab.h" +struct psymbol_allocation_list; + /* A partial_symbol records the name, domain, and address class of symbols whose types we have not parsed yet. For functions, it also contains their memory address, so we can find them from a PC value. @@ -30,12 +32,12 @@ normal symtab once the partial_symtab has been referenced. */ /* This structure is space critical. See space comments at the top of - symtab.h. */ + symtab.h. */ struct partial_symbol { - /* The general symbol info required for all types of symbols. */ + /* The general symbol info required for all types of symbols. */ struct general_symbol_info ginfo; @@ -43,7 +45,7 @@ struct partial_symbol ENUM_BITFIELD(domain_enum_tag) domain : 6; - /* Address class (for info_symbols) */ + /* Address class (for info_symbols). */ ENUM_BITFIELD(address_class) aclass : 6; @@ -69,9 +71,9 @@ struct partial_symtab struct partial_symtab *next; - /* Name of the source file which this partial_symtab defines */ + /* Name of the source file which this partial_symtab defines. */ - char *filename; + const char *filename; /* Full path of the source file. NULL if not known. */ @@ -79,7 +81,7 @@ struct partial_symtab /* Directory in which it was compiled, or NULL if we don't know. */ - char *dirname; + const char *dirname; /* Information about the object file from which symbols should be read. */ @@ -90,7 +92,7 @@ struct partial_symtab struct section_offsets *section_offsets; /* Range of text addresses covered by this file; texthigh is the - beginning of the next section. */ + beginning of the next section. */ CORE_ADDR textlow; CORE_ADDR texthigh; @@ -110,7 +112,7 @@ struct partial_symtab /* Global symbol list. This list will be sorted after readin to improve access. Binary search will be the usual method of - finding a symbol within it. globals_offset is an integer offset + finding a symbol within it. globals_offset is an integer offset within global_psymbols[]. */ int globals_offset; @@ -127,6 +129,12 @@ struct partial_symtab int statics_offset; int n_static_syms; + /* Non-zero if the symtab corresponding to this psymtab has been + readin. This is located here so that this structure packs better + on 64-bit systems. */ + + unsigned char readin; + /* Pointer to symtab eventually allocated for this source file, 0 if !readin or if we haven't looked for the symtab after it was readin. */ @@ -143,23 +151,36 @@ struct partial_symtab the various symbol reading modules. */ void *read_symtab_private; - - /* Non-zero if the symtab corresponding to this psymtab has been readin */ - - unsigned char readin; }; extern void sort_pst_symbols (struct partial_symtab *); +/* Add any kind of symbol to a psymbol_allocation_list. */ + +extern const +struct partial_symbol *add_psymbol_to_list (const char *, int, + int, domain_enum, + enum address_class, + struct psymbol_allocation_list *, + long, CORE_ADDR, + enum language, struct objfile *); + +extern void init_psymbol_list (struct objfile *, int); + +extern struct partial_symtab *start_psymtab_common (struct objfile *, + struct section_offsets *, + const char *, CORE_ADDR, + struct partial_symbol **, + struct partial_symbol **); + +extern struct partial_symtab *allocate_psymtab (const char *, + struct objfile *); + +extern void discard_psymtab (struct partial_symtab *); + /* Traverse all psymtabs in one objfile. */ #define ALL_OBJFILE_PSYMTABS(objfile, p) \ for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next) -/* Traverse all psymtabs in all objfiles. */ - -#define ALL_PSYMTABS(objfile, p) \ - ALL_OBJFILES (objfile) \ - ALL_OBJFILE_PSYMTABS (objfile, p) - #endif /* PSYMPRIV_H */ diff --git a/contrib/gdb-7/gdb/psymtab.c b/contrib/gdb-7/gdb/psymtab.c index 97a4eecd41..cd117c1e1e 100644 --- a/contrib/gdb-7/gdb/psymtab.c +++ b/contrib/gdb-7/gdb/psymtab.c @@ -1,6 +1,6 @@ /* Partial symbol tables. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -32,16 +32,29 @@ #include "command.h" #include "readline/readline.h" #include "gdb_regex.h" +#include "dictionary.h" +#include "language.h" +#include "cp-support.h" #ifndef DEV_TTY #define DEV_TTY "/dev/tty" #endif +struct psymbol_bcache +{ + struct bcache *bcache; +}; + /* A fast way to get from a psymtab to its symtab (after the first time). */ #define PSYMTAB_TO_SYMTAB(pst) \ ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst)) -/* Lookup a partial symbol. */ +static struct partial_symbol *match_partial_symbol (struct partial_symtab *, + int, + const char *, domain_enum, + symbol_compare_ftype *, + symbol_compare_ftype *); + static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *, const char *, int, domain_enum); @@ -58,6 +71,60 @@ static struct partial_symbol *fixup_psymbol_section (struct partial_symbol static struct symtab *psymtab_to_symtab (struct partial_symtab *pst); +/* Ensure that the partial symbols for OBJFILE have been loaded. This + function always returns its argument, as a convenience. */ + +struct objfile * +require_partial_symbols (struct objfile *objfile, int verbose) +{ + if ((objfile->flags & OBJF_PSYMTABS_READ) == 0) + { + objfile->flags |= OBJF_PSYMTABS_READ; + + if (objfile->sf->sym_read_psymbols) + { + if (verbose) + { + printf_unfiltered (_("Reading symbols from %s..."), + objfile->name); + gdb_flush (gdb_stdout); + } + (*objfile->sf->sym_read_psymbols) (objfile); + if (verbose) + { + if (!objfile_has_symbols (objfile)) + { + wrap_here (""); + printf_unfiltered (_("(no debugging symbols found)...")); + wrap_here (""); + } + + printf_unfiltered (_("done.\n")); + } + } + } + + return objfile; +} + +/* Traverse all psymtabs in one objfile, requiring that the psymtabs + be read in. */ + +#define ALL_OBJFILE_PSYMTABS_REQUIRED(objfile, p) \ + for ((p) = require_partial_symbols (objfile, 1)->psymtabs; \ + (p) != NULL; \ + (p) = (p)->next) + +/* We want to make sure this file always requires psymtabs. */ + +#undef ALL_OBJFILE_PSYMTABS + +/* Traverse all psymtabs in all objfiles. */ + +#define ALL_PSYMTABS(objfile, p) \ + ALL_OBJFILES (objfile) \ + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p) + /* Lookup the partial symbol table of a source file named NAME. *If* there is no '/' in the name, a match after a '/' in the psymtab filename will also work. */ @@ -68,7 +135,7 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, { struct partial_symtab *pst; - ALL_OBJFILE_PSYMTABS (objfile, pst) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (FILENAME_CMP (name, pst->filename) == 0) { @@ -103,10 +170,10 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, } } - /* Now, search for a matching tail (only if name doesn't have any dirs) */ + /* Now, search for a matching tail (only if name doesn't have any dirs). */ if (lbasename (name) == name) - ALL_OBJFILE_PSYMTABS (objfile, pst) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (FILENAME_CMP (lbasename (pst->filename), name) == 0) return (pst); @@ -152,7 +219,7 @@ find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section, we want the partial symbol table that contains the function containing the PC. */ if (!(objfile->flags & OBJF_REORDERED) && - section == 0) /* can't validate section this way */ + section == 0) /* Can't validate section this way. */ return pst; if (msymbol == NULL) @@ -160,7 +227,7 @@ find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section, /* The code range of partial symtabs sometimes overlap, so, in the loop below, we need to check all partial symtabs and - find the one that fits better for the given PC address. We + find the one that fits better for the given PC address. We select the partial symtab that contains a symbol whose address is closest to the PC address. By closest we mean that find_pc_sect_symbol returns the symbol with address @@ -196,11 +263,11 @@ find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section, necessarily lower or equal to PC, the symbol closer to PC is the symbol which address is the highest. This way we return the psymtab which contains such - best match symbol. This can help in cases where the + best match symbol. This can help in cases where the symbol information/debuginfo is not complete, like for instance on IRIX6 with gcc, where no debug info - is emitted for statics. (See also the nodebug.exp - testcase.) */ + is emitted for statics. (See also the nodebug.exp + testcase.) */ if (this_addr > best_addr) { best_addr = this_addr; @@ -269,7 +336,7 @@ find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc, its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying debug info type in single OBJFILE. */ - ALL_OBJFILE_PSYMTABS (objfile, pst) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) if (pc >= pst->textlow && pc < pst->texthigh) { struct partial_symtab *best_pst; @@ -316,7 +383,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc, gdb_assert (psymtab != NULL); - /* Cope with programs that start at address 0 */ + /* Cope with programs that start at address 0. */ best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0; /* Search the global symbols as well as the static symbols, so that @@ -335,7 +402,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc, || (psymtab->textlow == 0 && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0))) { - if (section) /* match on a specific section */ + if (section) /* Match on a specific section. */ { fixup_psymbol_section (p, psymtab->objfile); if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section)) @@ -359,7 +426,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc, || (psymtab->textlow == 0 && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0))) { - if (section) /* match on a specific section */ + if (section) /* Match on a specific section. */ { fixup_psymbol_section (p, psymtab->objfile); if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section)) @@ -412,17 +479,156 @@ lookup_symbol_aux_psymtabs (struct objfile *objfile, struct partial_symtab *ps; const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0); - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { if (!ps->readin && lookup_partial_symbol (ps, name, psymtab_index, domain)) - return PSYMTAB_TO_SYMTAB (ps); + { + struct symbol *sym = NULL; + struct symtab *stab = PSYMTAB_TO_SYMTAB (ps); + + /* Some caution must be observed with overloaded functions + and methods, since the psymtab will not contain any overload + information (but NAME might contain it). */ + if (stab->primary) + { + struct blockvector *bv = BLOCKVECTOR (stab); + struct block *block = BLOCKVECTOR_BLOCK (bv, block_index); + + sym = lookup_block_symbol (block, name, domain); + } + + if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) + return stab; + + /* Keep looking through other psymtabs. */ + } } return NULL; } +/* Look in PST for a symbol in DOMAIN whose name matches NAME. Search + the global block of PST if GLOBAL, and otherwise the static block. + MATCH is the comparison operation that returns true iff MATCH (s, + NAME), where s is a SYMBOL_SEARCH_NAME. If ORDERED_COMPARE is + non-null, the symbols in the block are assumed to be ordered + according to it (allowing binary search). It must be compatible + with MATCH. Returns the symbol, if found, and otherwise NULL. */ + +static struct partial_symbol * +match_partial_symbol (struct partial_symtab *pst, int global, + const char *name, domain_enum domain, + symbol_compare_ftype *match, + symbol_compare_ftype *ordered_compare) +{ + struct partial_symbol **start, **psym; + struct partial_symbol **top, **real_top, **bottom, **center; + int length = (global ? pst->n_global_syms : pst->n_static_syms); + int do_linear_search = 1; + + if (length == 0) + return NULL; + start = (global ? + pst->objfile->global_psymbols.list + pst->globals_offset : + pst->objfile->static_psymbols.list + pst->statics_offset); + + if (global && ordered_compare) /* Can use a binary search. */ + { + do_linear_search = 0; + + /* Binary search. This search is guaranteed to end with center + pointing at the earliest partial symbol whose name might be + correct. At that point *all* partial symbols with an + appropriate name will be checked against the correct + domain. */ + + bottom = start; + top = start + length - 1; + real_top = top; + while (top > bottom) + { + center = bottom + (top - bottom) / 2; + gdb_assert (center < top); + if (!do_linear_search + && (SYMBOL_LANGUAGE (*center) == language_java)) + do_linear_search = 1; + if (ordered_compare (SYMBOL_SEARCH_NAME (*center), name) >= 0) + top = center; + else + bottom = center + 1; + } + gdb_assert (top == bottom); + + while (top <= real_top + && match (SYMBOL_SEARCH_NAME (*top), name) == 0) + { + if (symbol_matches_domain (SYMBOL_LANGUAGE (*top), + SYMBOL_DOMAIN (*top), domain)) + return *top; + top++; + } + } + + /* Can't use a binary search or else we found during the binary search that + we should also do a linear search. */ + + if (do_linear_search) + { + for (psym = start; psym < start + length; psym++) + { + if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym), + SYMBOL_DOMAIN (*psym), domain) + && match (SYMBOL_SEARCH_NAME (*psym), name) == 0) + return *psym; + } + } + + return NULL; +} + +static void +pre_expand_symtabs_matching_psymtabs (struct objfile *objfile, + int kind, const char *name, + domain_enum domain) +{ + /* Nothing. */ +} + +/* Returns the name used to search psymtabs. Unlike symtabs, psymtabs do + not contain any method/function instance information (since this would + force reading type information while reading psymtabs). Therefore, + if NAME contains overload information, it must be stripped before searching + psymtabs. + + The caller is responsible for freeing the return result. */ + +static char * +psymtab_search_name (const char *name) +{ + switch (current_language->la_language) + { + case language_cplus: + case language_java: + { + if (strchr (name, '(')) + { + char *ret = cp_remove_params (name); + + if (ret) + return ret; + } + } + break; + + default: + break; + } + + return xstrdup (name); +} + /* Look, in partial_symtab PST, for symbol whose natural name is NAME. - Check the global symbols if GLOBAL, the static symbols if not. */ + Check the global symbols if GLOBAL, the static symbols if not. */ static struct partial_symbol * lookup_partial_symbol (struct partial_symtab *pst, const char *name, @@ -432,16 +638,21 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, struct partial_symbol **top, **real_top, **bottom, **center; int length = (global ? pst->n_global_syms : pst->n_static_syms); int do_linear_search = 1; + char *search_name; + struct cleanup *cleanup; if (length == 0) { return (NULL); } + + search_name = psymtab_search_name (name); + cleanup = make_cleanup (xfree, search_name); start = (global ? pst->objfile->global_psymbols.list + pst->globals_offset : pst->objfile->static_psymbols.list + pst->statics_offset); - if (global) /* This means we can use a binary search. */ + if (global) /* This means we can use a binary search. */ { do_linear_search = 0; @@ -458,13 +669,15 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, { center = bottom + (top - bottom) / 2; if (!(center < top)) - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); if (!do_linear_search - && (SYMBOL_LANGUAGE (*center) == language_java)) + && SYMBOL_LANGUAGE (*center) == language_java) { do_linear_search = 1; } - if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0) + if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), + search_name) >= 0) { top = center; } @@ -474,20 +687,24 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, } } if (!(top == bottom)) - internal_error (__FILE__, __LINE__, _("failed internal consistency check")); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); while (top <= real_top - && SYMBOL_MATCHES_SEARCH_NAME (*top, name)) + && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) { if (symbol_matches_domain (SYMBOL_LANGUAGE (*top), SYMBOL_DOMAIN (*top), domain)) - return (*top); + { + do_cleanups (cleanup); + return (*top); + } top++; } } /* Can't use a binary search or else we found during the binary search that - we should also do a linear search. */ + we should also do a linear search. */ if (do_linear_search) { @@ -495,11 +712,15 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, { if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym), SYMBOL_DOMAIN (*psym), domain) - && SYMBOL_MATCHES_SEARCH_NAME (*psym, name)) - return (*psym); + && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name)) + { + do_cleanups (cleanup); + return (*psym); + } } } + do_cleanups (cleanup); return (NULL); } @@ -511,7 +732,7 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, static struct symtab * psymtab_to_symtab (struct partial_symtab *pst) { - /* If it's been looked up before, return it. */ + /* If it's been looked up before, return it. */ if (pst->symtab) return pst->symtab; @@ -535,7 +756,7 @@ relocate_psymtabs (struct objfile *objfile, struct partial_symbol **psym; struct partial_symtab *p; - ALL_OBJFILE_PSYMTABS (objfile, p) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p) { p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); @@ -567,7 +788,7 @@ find_last_source_symtab_from_partial (struct objfile *ofp) struct partial_symtab *ps; struct partial_symtab *cs_pst = 0; - ALL_OBJFILE_PSYMTABS (ofp, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (ofp, ps) { const char *name = ps->filename; int len = strlen (name); @@ -596,7 +817,7 @@ forget_cached_source_info_partial (struct objfile *objfile) { struct partial_symtab *pst; - ALL_OBJFILE_PSYMTABS (objfile, pst) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (pst->fullname != NULL) { @@ -626,7 +847,7 @@ print_partial_symbols (struct gdbarch *gdbarch, fputs_filtered ("undefined domain, ", outfile); break; case VAR_DOMAIN: - /* This is the usual thing -- don't print it */ + /* This is the usual thing -- don't print it. */ break; case STRUCT_DOMAIN: fputs_filtered ("struct domain, ", outfile); @@ -773,7 +994,7 @@ print_psymtab_stats_for_objfile (struct objfile *objfile) struct partial_symtab *ps; i = 0; - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { if (ps->readin == 0) i++; @@ -808,14 +1029,14 @@ dump_psymtabs_for_objfile (struct objfile *objfile) } /* Look through the partial symtabs for all symbols which begin - by matching FUNC_NAME. Make sure we read that symbol table in. */ + by matching FUNC_NAME. Make sure we read that symbol table in. */ static void read_symtabs_for_function (struct objfile *objfile, const char *func_name) { struct partial_symtab *ps; - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { if (ps->readin) continue; @@ -833,9 +1054,7 @@ expand_partial_symbol_tables (struct objfile *objfile) { struct partial_symtab *psymtab; - for (psymtab = objfile->psymtabs; - psymtab != NULL; - psymtab = psymtab->next) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, psymtab) { psymtab_to_symtab (psymtab); } @@ -846,49 +1065,13 @@ read_psymtabs_with_filename (struct objfile *objfile, const char *filename) { struct partial_symtab *p; - ALL_OBJFILE_PSYMTABS (objfile, p) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p) { - if (strcmp (filename, p->filename) == 0) + if (filename_cmp (filename, p->filename) == 0) PSYMTAB_TO_SYMTAB (p); } } -static void -map_symbol_names_psymtab (struct objfile *objfile, - void (*fun) (const char *, void *), void *data) -{ - struct partial_symtab *ps; - - ALL_OBJFILE_PSYMTABS (objfile, ps) - { - struct partial_symbol **psym; - - /* If the psymtab's been read in we'll get it when we search - through the blockvector. */ - if (ps->readin) - continue; - - for (psym = objfile->global_psymbols.list + ps->globals_offset; - psym < (objfile->global_psymbols.list + ps->globals_offset - + ps->n_global_syms); - psym++) - { - /* If interrupted, then quit. */ - QUIT; - (*fun) (SYMBOL_NATURAL_NAME (*psym), data); - } - - for (psym = objfile->static_psymbols.list + ps->statics_offset; - psym < (objfile->static_psymbols.list + ps->statics_offset - + ps->n_static_syms); - psym++) - { - QUIT; - (*fun) (SYMBOL_NATURAL_NAME (*psym), data); - } - } -} - static void map_symbol_filenames_psymtab (struct objfile *objfile, void (*fun) (const char *, const char *, @@ -897,7 +1080,7 @@ map_symbol_filenames_psymtab (struct objfile *objfile, { struct partial_symtab *ps; - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { const char *fullname; @@ -929,7 +1112,7 @@ psymtab_to_fullname (struct partial_symtab *ps) return NULL; /* Don't check ps->fullname here, the file could have been - deleted/moved/..., look for it again */ + deleted/moved/..., look for it again. */ r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname); if (r >= 0) @@ -941,12 +1124,12 @@ psymtab_to_fullname (struct partial_symtab *ps) return NULL; } -static char * +static const char * find_symbol_file_from_partial (struct objfile *objfile, const char *name) { struct partial_symtab *pst; - ALL_OBJFILE_PSYMTABS (objfile, pst) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (lookup_partial_symbol (pst, name, 1, VAR_DOMAIN)) return pst->filename; @@ -954,185 +1137,83 @@ find_symbol_file_from_partial (struct objfile *objfile, const char *name) return NULL; } -/* Look, in partial_symtab PST, for symbol NAME in given namespace. - Check the global symbols if GLOBAL, the static symbols if not. - Do wild-card match if WILD. */ +/* For all symbols, s, in BLOCK that are in NAMESPACE and match NAME + according to the function MATCH, call CALLBACK(BLOCK, s, DATA). + BLOCK is assumed to come from OBJFILE. Returns 1 iff CALLBACK + ever returns non-zero, and otherwise returns 0. */ -static struct partial_symbol * -ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name, - int global, domain_enum namespace, int wild, - int (*wild_match) (const char *, int, const char *), - int (*is_name_suffix) (const char *)) +static int +map_block (const char *name, domain_enum namespace, struct objfile *objfile, + struct block *block, + int (*callback) (struct block *, struct symbol *, void *), + void *data, symbol_compare_ftype *match) { - struct partial_symbol **start; - int name_len = strlen (name); - int length = (global ? pst->n_global_syms : pst->n_static_syms); - int i; + struct dict_iterator iter; + struct symbol *sym; - if (length == 0) + for (sym = dict_iter_match_first (BLOCK_DICT (block), name, match, &iter); + sym != NULL; sym = dict_iter_match_next (name, match, &iter)) { - return (NULL); + if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), + SYMBOL_DOMAIN (sym), namespace)) + { + if (callback (block, sym, data)) + return 1; + } } - start = (global ? - pst->objfile->global_psymbols.list + pst->globals_offset : - pst->objfile->static_psymbols.list + pst->statics_offset); - - if (wild) - { - for (i = 0; i < length; i += 1) - { - struct partial_symbol *psym = start[i]; - - if (symbol_matches_domain (SYMBOL_LANGUAGE (psym), - SYMBOL_DOMAIN (psym), namespace) - && (*wild_match) (name, name_len, SYMBOL_LINKAGE_NAME (psym))) - return psym; - } - return NULL; - } - else - { - if (global) - { - int U; - - i = 0; - U = length - 1; - while (U - i > 4) - { - int M = (U + i) >> 1; - struct partial_symbol *psym = start[M]; - - if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0]) - i = M + 1; - else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0]) - U = M - 1; - else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0) - i = M + 1; - else - U = M; - } - } - else - i = 0; - - while (i < length) - { - struct partial_symbol *psym = start[i]; - - if (symbol_matches_domain (SYMBOL_LANGUAGE (psym), - SYMBOL_DOMAIN (psym), namespace)) - { - int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len); - - if (cmp < 0) - { - if (global) - break; - } - else if (cmp == 0 - && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym) - + name_len)) - return psym; - } - i += 1; - } - - if (global) - { - int U; - - i = 0; - U = length - 1; - while (U - i > 4) - { - int M = (U + i) >> 1; - struct partial_symbol *psym = start[M]; - - if (SYMBOL_LINKAGE_NAME (psym)[0] < '_') - i = M + 1; - else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_') - U = M - 1; - else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0) - i = M + 1; - else - U = M; - } - } - else - i = 0; - - while (i < length) - { - struct partial_symbol *psym = start[i]; - - if (symbol_matches_domain (SYMBOL_LANGUAGE (psym), - SYMBOL_DOMAIN (psym), namespace)) - { - int cmp; - - cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0]; - if (cmp == 0) - { - cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5); - if (cmp == 0) - cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5, - name_len); - } - - if (cmp < 0) - { - if (global) - break; - } - else if (cmp == 0 - && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym) - + name_len + 5)) - return psym; - } - i += 1; - } - } - return NULL; + return 0; } +/* Psymtab version of map_matching_symbols. See its definition in + the definition of quick_symbol_functions in symfile.h. */ + static void -map_ada_symtabs (struct objfile *objfile, - int (*wild_match) (const char *, int, const char *), - int (*is_name_suffix) (const char *), - void (*callback) (struct objfile *, struct symtab *, void *), - const char *name, int global, domain_enum namespace, int wild, - void *data) +map_matching_symbols_psymtab (const char *name, domain_enum namespace, + struct objfile *objfile, int global, + int (*callback) (struct block *, + struct symbol *, void *), + void *data, + symbol_compare_ftype *match, + symbol_compare_ftype *ordered_compare) { + const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK; struct partial_symtab *ps; - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { QUIT; if (ps->readin - || ada_lookup_partial_symbol (ps, name, global, namespace, wild, - wild_match, is_name_suffix)) + || match_partial_symbol (ps, global, name, namespace, match, + ordered_compare)) { struct symtab *s = PSYMTAB_TO_SYMTAB (ps); + struct block *block; if (s == NULL || !s->primary) continue; - (*callback) (objfile, s, data); + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind); + if (map_block (name, namespace, objfile, block, + callback, data, match)) + return; + if (callback (block, NULL, data)) + return; } } -} +} static void expand_symtabs_matching_via_partial (struct objfile *objfile, - int (*file_matcher) (const char *, void *), - int (*name_matcher) (const char *, void *), + int (*file_matcher) (const char *, + void *), + int (*name_matcher) (const char *, + void *), domain_enum kind, void *data) { struct partial_symtab *ps; - ALL_OBJFILE_PSYMTABS (objfile, ps) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { struct partial_symbol **psym; struct partial_symbol **bound, **gbound, **sbound; @@ -1141,15 +1222,17 @@ expand_symtabs_matching_via_partial (struct objfile *objfile, if (ps->readin) continue; - if (! (*file_matcher) (ps->filename, data)) + if (file_matcher && ! (*file_matcher) (ps->filename, data)) continue; - gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms; - sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms; + gbound = objfile->global_psymbols.list + + ps->globals_offset + ps->n_global_syms; + sbound = objfile->static_psymbols.list + + ps->statics_offset + ps->n_static_syms; bound = gbound; /* Go through all of the symbols stored in a partial - symtab in one loop. */ + symtab in one loop. */ psym = objfile->global_psymbols.list + ps->globals_offset; while (keep_going) { @@ -1168,14 +1251,15 @@ expand_symtabs_matching_via_partial (struct objfile *objfile, { QUIT; - if ((*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data) - && ((kind == VARIABLES_DOMAIN + if ((kind == ALL_DOMAIN + || (kind == VARIABLES_DOMAIN && SYMBOL_CLASS (*psym) != LOC_TYPEDEF && SYMBOL_CLASS (*psym) != LOC_BLOCK) - || (kind == FUNCTIONS_DOMAIN - && SYMBOL_CLASS (*psym) == LOC_BLOCK) - || (kind == TYPES_DOMAIN - && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))) + || (kind == FUNCTIONS_DOMAIN + && SYMBOL_CLASS (*psym) == LOC_BLOCK) + || (kind == TYPES_DOMAIN + && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)) + && (*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data)) { PSYMTAB_TO_SYMTAB (ps); keep_going = 0; @@ -1199,6 +1283,7 @@ const struct quick_symbol_functions psym_functions = forget_cached_source_info_partial, lookup_symtab_via_partial_symtab, lookup_symbol_aux_psymtabs, + pre_expand_symtabs_matching_psymtabs, print_psymtab_stats_for_objfile, dump_psymtabs_for_objfile, relocate_psymtabs, @@ -1206,10 +1291,9 @@ const struct quick_symbol_functions psym_functions = expand_partial_symbol_tables, read_psymtabs_with_filename, find_symbol_file_from_partial, - map_ada_symtabs, + map_matching_symbols_psymtab, expand_symtabs_matching_via_partial, find_pc_sect_symtab_from_partial, - map_symbol_names_psymtab, map_symbol_filenames_psymtab }; @@ -1231,7 +1315,7 @@ compare_psymbols (const void *s1p, const void *s2p) void sort_pst_symbols (struct partial_symtab *pst) { - /* Sort the global list; don't sort the static list */ + /* Sort the global list; don't sort the static list. */ qsort (pst->objfile->global_psymbols.list + pst->globals_offset, pst->n_global_syms, sizeof (struct partial_symbol *), @@ -1241,7 +1325,7 @@ sort_pst_symbols (struct partial_symtab *pst) /* Allocate and partially fill a partial symtab. It will be completely filled at the end of the symbol list. - FILENAME is the name of the symbol-file we are reading from. */ + FILENAME is the name of the symbol-file we are reading from. */ struct partial_symtab * start_psymtab_common (struct objfile *objfile, @@ -1261,6 +1345,92 @@ start_psymtab_common (struct objfile *objfile, return (psymtab); } +/* Calculate a hash code for the given partial symbol. The hash is + calculated using the symbol's value, language, domain, class + and name. These are the values which are set by + add_psymbol_to_bcache. */ + +static unsigned long +psymbol_hash (const void *addr, int length) +{ + unsigned long h = 0; + struct partial_symbol *psymbol = (struct partial_symbol *) addr; + unsigned int lang = psymbol->ginfo.language; + unsigned int domain = PSYMBOL_DOMAIN (psymbol); + unsigned int class = PSYMBOL_CLASS (psymbol); + + h = hash_continue (&psymbol->ginfo.value, sizeof (psymbol->ginfo.value), h); + h = hash_continue (&lang, sizeof (unsigned int), h); + h = hash_continue (&domain, sizeof (unsigned int), h); + h = hash_continue (&class, sizeof (unsigned int), h); + h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h); + + return h; +} + +/* Returns true if the symbol at addr1 equals the symbol at addr2. + For the comparison this function uses a symbols value, + language, domain, class and name. */ + +static int +psymbol_compare (const void *addr1, const void *addr2, int length) +{ + struct partial_symbol *sym1 = (struct partial_symbol *) addr1; + struct partial_symbol *sym2 = (struct partial_symbol *) addr2; + + return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value, + sizeof (sym1->ginfo.value)) == 0 + && sym1->ginfo.language == sym2->ginfo.language + && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2) + && PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2) + && sym1->ginfo.name == sym2->ginfo.name); +} + +/* Initialize a partial symbol bcache. */ + +struct psymbol_bcache * +psymbol_bcache_init (void) +{ + struct psymbol_bcache *bcache = XCALLOC (1, struct psymbol_bcache); + bcache->bcache = bcache_xmalloc (psymbol_hash, psymbol_compare); + return bcache; +} + +/* Free a partial symbol bcache. */ +void +psymbol_bcache_free (struct psymbol_bcache *bcache) +{ + if (bcache == NULL) + return; + + bcache_xfree (bcache->bcache); + xfree (bcache); +} + +/* Return the internal bcache of the psymbol_bcache BCACHE. */ + +struct bcache * +psymbol_bcache_get_bcache (struct psymbol_bcache *bcache) +{ + return bcache->bcache; +} + +/* Find a copy of the SYM in BCACHE. If BCACHE has never seen this + symbol before, add a copy to BCACHE. In either case, return a pointer + to BCACHE's copy of the symbol. If optional ADDED is not NULL, return + 1 in case of new entry or 0 if returning an old entry. */ + +static const struct partial_symbol * +psymbol_bcache_full (struct partial_symbol *sym, + struct psymbol_bcache *bcache, + int *added) +{ + return bcache_full (sym, + sizeof (struct partial_symbol), + bcache->bcache, + added); +} + /* Helper function, initialises partial symbol structure and stashes it into objfile's bcache. Note that our caching mechanism will use all fields of struct partial_symbol to determine hash value of the @@ -1268,7 +1438,7 @@ start_psymtab_common (struct objfile *objfile, different domain (or address) is possible and correct. */ static const struct partial_symbol * -add_psymbol_to_bcache (char *name, int namelength, int copy_name, +add_psymbol_to_bcache (const char *name, int namelength, int copy_name, domain_enum domain, enum address_class class, long val, /* Value as a long */ @@ -1276,16 +1446,14 @@ add_psymbol_to_bcache (char *name, int namelength, int copy_name, enum language language, struct objfile *objfile, int *added) { - /* psymbol is static so that there will be no uninitialized gaps in the - structure which might contain random data, causing cache misses in - bcache. */ - static struct partial_symbol psymbol; - - /* However, we must ensure that the entire 'value' field has been - zeroed before assigning to it, because an assignment may not - write the entire field. */ + struct partial_symbol psymbol; + + /* We must ensure that the entire 'value' field has been zeroed + before assigning to it, because an assignment may not write the + entire field. */ memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value)); - /* val and coreaddr are mutually exclusive, one of them *will* be zero */ + + /* val and coreaddr are mutually exclusive, one of them *will* be zero. */ if (val != 0) { SYMBOL_VALUE (&psymbol) = val; @@ -1295,15 +1463,46 @@ add_psymbol_to_bcache (char *name, int namelength, int copy_name, SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr; } SYMBOL_SECTION (&psymbol) = 0; - SYMBOL_LANGUAGE (&psymbol) = language; + SYMBOL_OBJ_SECTION (&psymbol) = NULL; + SYMBOL_SET_LANGUAGE (&psymbol, language); PSYMBOL_DOMAIN (&psymbol) = domain; PSYMBOL_CLASS (&psymbol) = class; SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile); - /* Stash the partial symbol away in the cache */ - return bcache_full (&psymbol, sizeof (struct partial_symbol), - objfile->psymbol_cache, added); + /* Stash the partial symbol away in the cache. */ + return psymbol_bcache_full (&psymbol, + objfile->psymbol_cache, + added); +} + +/* Increase the space allocated for LISTP, which is probably + global_psymbols or static_psymbols. This space will eventually + be freed in free_objfile(). */ + +static void +extend_psymbol_list (struct psymbol_allocation_list *listp, + struct objfile *objfile) +{ + int new_size; + + if (listp->size == 0) + { + new_size = 255; + listp->list = (struct partial_symbol **) + xmalloc (new_size * sizeof (struct partial_symbol *)); + } + else + { + new_size = listp->size * 2; + listp->list = (struct partial_symbol **) + xrealloc ((char *) listp->list, + new_size * sizeof (struct partial_symbol *)); + } + /* Next assumes we only went one over. Should be good if + program works correctly. */ + listp->next = listp->list + listp->size; + listp->size = new_size; } /* Helper function, adds partial symbol to the given partial symbol @@ -1336,7 +1535,7 @@ append_psymbol_to_list (struct psymbol_allocation_list *list, cache. */ const struct partial_symbol * -add_psymbol_to_list (char *name, int namelength, int copy_name, +add_psymbol_to_list (const char *name, int namelength, int copy_name, domain_enum domain, enum address_class class, struct psymbol_allocation_list *list, @@ -1348,7 +1547,7 @@ add_psymbol_to_list (char *name, int namelength, int copy_name, int added; - /* Stash the partial symbol away in the cache */ + /* Stash the partial symbol away in the cache. */ psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class, val, coreaddr, language, objfile, &added); @@ -1357,7 +1556,7 @@ add_psymbol_to_list (char *name, int namelength, int copy_name, && !added) return psym; - /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ + /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ append_psymbol_to_list (list, psym, objfile); return psym; } @@ -1380,7 +1579,7 @@ init_psymbol_list (struct objfile *objfile, int total_symbols) /* Current best guess is that approximately a twentieth of the total symbols (in a debugging file) are global or static - oriented symbols */ + oriented symbols. */ objfile->global_psymbols.size = total_symbols / 10; objfile->static_psymbols.size = total_symbols / 10; @@ -1423,7 +1622,7 @@ allocate_psymtab (const char *filename, struct objfile *objfile) /* Prepend it to the psymtab list for the objfile it belongs to. Psymtabs are searched in most recent inserted -> least recent - inserted order. */ + inserted order. */ psymtab->objfile = objfile; psymtab->next = objfile->psymtabs; @@ -1444,48 +1643,19 @@ discard_psymtab (struct partial_symtab *pst) nothing else is not empty, but we don't realize that. Fixing that without slowing things down might be tricky. */ - /* First, snip it out of the psymtab chain */ + /* First, snip it out of the psymtab chain. */ prev_pst = &(pst->objfile->psymtabs); while ((*prev_pst) != pst) prev_pst = &((*prev_pst)->next); (*prev_pst) = pst->next; - /* Next, put it on a free list for recycling */ + /* Next, put it on a free list for recycling. */ pst->next = pst->objfile->free_psymtabs; pst->objfile->free_psymtabs = pst; } -/* Increase the space allocated for LISTP, which is probably - global_psymbols or static_psymbols. This space will eventually - be freed in free_objfile(). */ - -void -extend_psymbol_list (struct psymbol_allocation_list *listp, - struct objfile *objfile) -{ - int new_size; - - if (listp->size == 0) - { - new_size = 255; - listp->list = (struct partial_symbol **) - xmalloc (new_size * sizeof (struct partial_symbol *)); - } - else - { - new_size = listp->size * 2; - listp->list = (struct partial_symbol **) - xrealloc ((char *) listp->list, - new_size * sizeof (struct partial_symbol *)); - } - /* Next assumes we only went one over. Should be good if - program works correctly */ - listp->next = listp->list + listp->size; - listp->size = new_size; -} - void @@ -1503,7 +1673,8 @@ maintenance_print_psymbols (char *args, int from_tty) if (args == NULL) { - error (_("print-psymbols takes an output file name and optional symbol file name")); + error (_("\ +print-psymbols takes an output file name and optional symbol file name")); } argv = gdb_buildargv (args); cleanups = make_cleanup_freeargv (argv); @@ -1511,7 +1682,7 @@ maintenance_print_psymbols (char *args, int from_tty) if (argv[0] != NULL) { filename = argv[0]; - /* If a second arg is supplied, it is a source file name to match on */ + /* If a second arg is supplied, it is a source file name to match on. */ if (argv[1] != NULL) { symname = argv[1]; @@ -1528,7 +1699,7 @@ maintenance_print_psymbols (char *args, int from_tty) immediate_quit++; ALL_PSYMTABS (objfile, ps) - if (symname == NULL || strcmp (symname, ps->filename) == 0) + if (symname == NULL || filename_cmp (symname, ps->filename) == 0) dump_psymtab (objfile, ps, outfile); immediate_quit--; do_cleanups (cleanups); @@ -1554,7 +1725,7 @@ maintenance_info_psymtabs (char *regexp, int from_tty) actually find a symtab whose name matches. */ int printed_objfile_start = 0; - ALL_OBJFILE_PSYMTABS (objfile, psymtab) + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, psymtab) { QUIT; @@ -1578,7 +1749,8 @@ maintenance_info_psymtabs (char *regexp, int from_tty) printf_filtered (" readin %s\n", psymtab->readin ? "yes" : "no"); printf_filtered (" fullname %s\n", - psymtab->fullname ? psymtab->fullname : "(null)"); + psymtab->fullname + ? psymtab->fullname : "(null)"); printf_filtered (" text addresses "); fputs_filtered (paddress (gdbarch, psymtab->textlow), gdb_stdout); @@ -1724,14 +1896,15 @@ maintenance_check_symtabs (char *ignore, int from_tty) void -map_partial_symbol_names (void (*fun) (const char *, void *), void *data) +expand_partial_symbol_names (int (*fun) (const char *, void *), void *data) { struct objfile *objfile; ALL_OBJFILES (objfile) { if (objfile->sf) - objfile->sf->qf->map_symbol_names (objfile, fun, data); + objfile->sf->qf->expand_symtabs_matching (objfile, NULL, fun, + ALL_DOMAIN, data); } } diff --git a/contrib/gdb-7/gdb/psymtab.h b/contrib/gdb-7/gdb/psymtab.h index 9b8c8dfc31..086ff2fb66 100644 --- a/contrib/gdb-7/gdb/psymtab.h +++ b/contrib/gdb-7/gdb/psymtab.h @@ -1,6 +1,6 @@ /* Public partial symbol table definitions. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +20,16 @@ #ifndef PSYMTAB_H #define PSYMTAB_H -void map_partial_symbol_names (void (*) (const char *, void *), void *); +/* A bcache for partial symbols. */ + +struct psymbol_bcache; + +extern struct psymbol_bcache *psymbol_bcache_init (void); +extern void psymbol_bcache_free (struct psymbol_bcache *); +extern struct bcache *psymbol_bcache_get_bcache (struct psymbol_bcache *); + +void expand_partial_symbol_names (int (*fun) (const char *, void *), + void *data); void map_partial_symbol_filenames (void (*) (const char *, const char *, void *), @@ -28,4 +37,14 @@ void map_partial_symbol_filenames (void (*) (const char *, const char *, extern const struct quick_symbol_functions psym_functions; +extern const struct quick_symbol_functions dwarf2_gdb_index_functions; + +/* Ensure that the partial symbols for OBJFILE have been loaded. If + VERBOSE is non-zero, then this will print a message when symbols + are loaded. This function always returns its argument, as a + convenience. */ + +extern struct objfile *require_partial_symbols (struct objfile *objfile, + int verbose); + #endif /* PSYMTAB_H */ diff --git a/contrib/gdb-7/gdb/python/lib/gdb/__init__.py b/contrib/gdb-7/gdb/python/lib/gdb/__init__.py new file mode 100644 index 0000000000..43975c2819 --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/__init__.py @@ -0,0 +1,18 @@ +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import gdb.command.pretty_printers + +gdb.command.pretty_printers.register_pretty_printer_commands() diff --git a/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py b/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py new file mode 100644 index 0000000000..ee2b61ff06 --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py @@ -0,0 +1,16 @@ +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + diff --git a/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py b/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py new file mode 100644 index 0000000000..86923d7cf8 --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py @@ -0,0 +1,370 @@ +# Pretty-printer commands. +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""GDB commands for working with pretty-printers.""" + +import copy +import gdb +import re + + +def parse_printer_regexps(arg): + """Internal utility to parse a pretty-printer command argv. + + Arguments: + arg: The arguments to the command. The format is: + [object-regexp [name-regexp]]. + Individual printers in a collection are named as + printer-name;subprinter-name. + + Returns: + The result is a 3-tuple of compiled regular expressions, except that + the resulting compiled subprinter regexp is None if not provided. + + Raises: + SyntaxError: an error processing ARG + """ + + argv = gdb.string_to_argv(arg); + argc = len(argv) + object_regexp = "" # match everything + name_regexp = "" # match everything + subname_regexp = None + if argc > 3: + raise SyntaxError("too many arguments") + if argc >= 1: + object_regexp = argv[0] + if argc >= 2: + name_subname = argv[1].split(";", 1) + name_regexp = name_subname[0] + if len(name_subname) == 2: + subname_regexp = name_subname[1] + # That re.compile raises SyntaxError was determined empirically. + # We catch it and reraise it to provide a slightly more useful + # error message for the user. + try: + object_re = re.compile(object_regexp) + except SyntaxError: + raise SyntaxError("invalid object regexp: %s" % object_regexp) + try: + name_re = re.compile (name_regexp) + except SyntaxError: + raise SyntaxError("invalid name regexp: %s" % name_regexp) + if subname_regexp is not None: + try: + subname_re = re.compile(subname_regexp) + except SyntaxError: + raise SyntaxError("invalid subname regexp: %s" % subname_regexp) + else: + subname_re = None + return(object_re, name_re, subname_re) + + +def printer_enabled_p(printer): + """Internal utility to see if printer (or subprinter) is enabled.""" + if hasattr(printer, "enabled"): + return printer.enabled + else: + return True + + +class InfoPrettyPrinter(gdb.Command): + """GDB command to list all registered pretty-printers. + + Usage: info pretty-printer [object-regexp [name-regexp]] + + OBJECT-REGEXP is a regular expression matching the objects to list. + Objects are "global", the program space's file, and the objfiles within + that program space. + + NAME-REGEXP matches the name of the pretty-printer. + Individual printers in a collection are named as + printer-name;subprinter-name. + """ + + def __init__ (self): + super(InfoPrettyPrinter, self).__init__("info pretty-printer", + gdb.COMMAND_DATA) + + @staticmethod + def enabled_string(printer): + """Return "" if PRINTER is enabled, otherwise " [disabled]".""" + if printer_enabled_p(printer): + return "" + else: + return " [disabled]" + + @staticmethod + def printer_name(printer): + """Return the printer's name.""" + if hasattr(printer, "name"): + return printer.name + if hasattr(printer, "__name__"): + return printer.__name__ + # This "shouldn't happen", but the public API allows for + # direct additions to the pretty-printer list, and we shouldn't + # crash because someone added a bogus printer. + # Plus we want to give the user a way to list unknown printers. + return "unknown" + + def list_pretty_printers(self, pretty_printers, name_re, subname_re): + """Print a list of pretty-printers.""" + # A potential enhancement is to provide an option to list printers in + # "lookup order" (i.e. unsorted). + sorted_pretty_printers = copy.copy(pretty_printers) + sorted_pretty_printers.sort(lambda x, y: + cmp(self.printer_name(x), + self.printer_name(y))) + for printer in sorted_pretty_printers: + name = self.printer_name(printer) + enabled = self.enabled_string(printer) + if name_re.match(name): + print " %s%s" % (name, enabled) + if (hasattr(printer, "subprinters") and + printer.subprinters is not None): + sorted_subprinters = copy.copy(printer.subprinters) + sorted_subprinters.sort(lambda x, y: + cmp(self.printer_name(x), + self.printer_name(y))) + for subprinter in sorted_subprinters: + if (not subname_re or + subname_re.match(subprinter.name)): + print (" %s%s" % + (subprinter.name, + self.enabled_string(subprinter))) + + def invoke1(self, title, printer_list, + obj_name_to_match, object_re, name_re, subname_re): + """"Subroutine of invoke to simplify it.""" + if printer_list and object_re.match(obj_name_to_match): + print title + self.list_pretty_printers(printer_list, name_re, subname_re) + + def invoke(self, arg, from_tty): + """GDB calls this to perform the command.""" + (object_re, name_re, subname_re) = parse_printer_regexps(arg) + self.invoke1("global pretty-printers:", gdb.pretty_printers, + "global", object_re, name_re, subname_re) + cp = gdb.current_progspace() + self.invoke1("progspace %s pretty-printers:" % cp.filename, + cp.pretty_printers, "progspace", + object_re, name_re, subname_re) + for objfile in gdb.objfiles(): + self.invoke1(" objfile %s pretty-printers:" % objfile.filename, + objfile.pretty_printers, objfile.filename, + object_re, name_re, subname_re) + + +def count_enabled_printers(pretty_printers): + """Return a 2-tuple of number of enabled and total printers.""" + enabled = 0 + total = 0 + for printer in pretty_printers: + if (hasattr(printer, "subprinters") + and printer.subprinters is not None): + if printer_enabled_p(printer): + for subprinter in printer.subprinters: + if printer_enabled_p(subprinter): + enabled += 1 + total += len(printer.subprinters) + else: + if printer_enabled_p(printer): + enabled += 1 + total += 1 + return (enabled, total) + + +def count_all_enabled_printers(): + """Return a 2-tuble of the enabled state and total number of all printers. + This includes subprinters. + """ + enabled_count = 0 + total_count = 0 + (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers) + enabled_count += t_enabled + total_count += t_total + (t_enabled, t_total) = count_enabled_printers(gdb.current_progspace().pretty_printers) + enabled_count += t_enabled + total_count += t_total + for objfile in gdb.objfiles(): + (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers) + enabled_count += t_enabled + total_count += t_total + return (enabled_count, total_count) + + +def pluralize(text, n, suffix="s"): + """Return TEXT pluralized if N != 1.""" + if n != 1: + return "%s%s" % (text, suffix) + else: + return text + + +def show_pretty_printer_enabled_summary(): + """Print the number of printers enabled/disabled. + We count subprinters individually. + """ + (enabled_count, total_count) = count_all_enabled_printers() + print "%d of %d printers enabled" % (enabled_count, total_count) + + +def do_enable_pretty_printer_1 (pretty_printers, name_re, subname_re, flag): + """Worker for enabling/disabling pretty-printers. + + Arguments: + pretty_printers: list of pretty-printers + name_re: regular-expression object to select printers + subname_re: regular expression object to select subprinters or None + if all are affected + flag: True for Enable, False for Disable + + Returns: + The number of printers affected. + This is just for informational purposes for the user. + """ + total = 0 + for printer in pretty_printers: + if (hasattr(printer, "name") and name_re.match(printer.name) or + hasattr(printer, "__name__") and name_re.match(printer.__name__)): + if (hasattr(printer, "subprinters") and + printer.subprinters is not None): + if not subname_re: + # Only record printers that change state. + if printer_enabled_p(printer) != flag: + for subprinter in printer.subprinters: + if printer_enabled_p(subprinter): + total += 1 + # NOTE: We preserve individual subprinter settings. + printer.enabled = flag + else: + # NOTE: Whether this actually disables the subprinter + # depends on whether the printer's lookup function supports + # the "enable" API. We can only assume it does. + for subprinter in printer.subprinters: + if subname_re.match(subprinter.name): + # Only record printers that change state. + if (printer_enabled_p(printer) and + printer_enabled_p(subprinter) != flag): + total += 1 + subprinter.enabled = flag + else: + # This printer has no subprinters. + # If the user does "disable pretty-printer .* .* foo" + # should we disable printers that don't have subprinters? + # How do we apply "foo" in this context? Since there is no + # "foo" subprinter it feels like we should skip this printer. + # There's still the issue of how to handle + # "disable pretty-printer .* .* .*", and every other variation + # that can match everything. For now punt and only support + # "disable pretty-printer .* .*" (i.e. subname is elided) + # to disable everything. + if not subname_re: + # Only record printers that change state. + if printer_enabled_p(printer) != flag: + total += 1 + printer.enabled = flag + return total + + +def do_enable_pretty_printer (arg, flag): + """Internal worker for enabling/disabling pretty-printers.""" + (object_re, name_re, subname_re) = parse_printer_regexps(arg) + + total = 0 + if object_re.match("global"): + total += do_enable_pretty_printer_1(gdb.pretty_printers, + name_re, subname_re, flag) + cp = gdb.current_progspace() + if object_re.match("progspace"): + total += do_enable_pretty_printer_1(cp.pretty_printers, + name_re, subname_re, flag) + for objfile in gdb.objfiles(): + if object_re.match(objfile.filename): + total += do_enable_pretty_printer_1(objfile.pretty_printers, + name_re, subname_re, flag) + + if flag: + state = "enabled" + else: + state = "disabled" + print "%d %s %s" % (total, pluralize("printer", total), state) + + # Print the total list of printers currently enabled/disabled. + # This is to further assist the user in determining whether the result + # is expected. Since we use regexps to select it's useful. + show_pretty_printer_enabled_summary() + + +# Enable/Disable one or more pretty-printers. +# +# This is intended for use when a broken pretty-printer is shipped/installed +# and the user wants to disable that printer without disabling all the other +# printers. +# +# A useful addition would be -v (verbose) to show each printer affected. + +class EnablePrettyPrinter (gdb.Command): + """GDB command to enable the specified pretty-printer. + + Usage: enable pretty-printer [object-regexp [name-regexp]] + + OBJECT-REGEXP is a regular expression matching the objects to examine. + Objects are "global", the program space's file, and the objfiles within + that program space. + + NAME-REGEXP matches the name of the pretty-printer. + Individual printers in a collection are named as + printer-name;subprinter-name. + """ + + def __init__(self): + super(EnablePrettyPrinter, self).__init__("enable pretty-printer", + gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + """GDB calls this to perform the command.""" + do_enable_pretty_printer(arg, True) + + +class DisablePrettyPrinter (gdb.Command): + """GDB command to disable the specified pretty-printer. + + Usage: disable pretty-printer [object-regexp [name-regexp]] + + OBJECT-REGEXP is a regular expression matching the objects to examine. + Objects are "global", the program space's file, and the objfiles within + that program space. + + NAME-REGEXP matches the name of the pretty-printer. + Individual printers in a collection are named as + printer-name;subprinter-name. + """ + + def __init__(self): + super(DisablePrettyPrinter, self).__init__("disable pretty-printer", + gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + """GDB calls this to perform the command.""" + do_enable_pretty_printer(arg, False) + + +def register_pretty_printer_commands(): + """Call from a top level script to install the pretty-printer commands.""" + InfoPrettyPrinter() + EnablePrettyPrinter() + DisablePrettyPrinter() diff --git a/contrib/gdb-7/gdb/python/lib/gdb/printing.py b/contrib/gdb-7/gdb/python/lib/gdb/printing.py new file mode 100644 index 0000000000..ff24bb4e7a --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/printing.py @@ -0,0 +1,197 @@ +# Pretty-printer utilities. +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Utilities for working with pretty-printers.""" + +import gdb +import gdb.types +import re + + +class PrettyPrinter(object): + """A basic pretty-printer. + + Attributes: + name: A unique string among all printers for the context in which + it is defined (objfile, progspace, or global(gdb)), and should + meaningfully describe what can be pretty-printed. + E.g., "StringPiece" or "protobufs". + subprinters: An iterable object with each element having a `name' + attribute, and, potentially, "enabled" attribute. + Or this is None if there are no subprinters. + enabled: A boolean indicating if the printer is enabled. + + Subprinters are for situations where "one" pretty-printer is actually a + collection of several printers. E.g., The libstdc++ pretty-printer has + a pretty-printer for each of several different types, based on regexps. + """ + + # While one might want to push subprinters into the subclass, it's + # present here to formalize such support to simplify + # commands/pretty_printers.py. + + def __init__(self, name, subprinters=None): + self.name = name + self.subprinters = subprinters + self.enabled = True + + def __call__(self, val): + # The subclass must define this. + raise NotImplementedError("PrettyPrinter __call__") + + +class SubPrettyPrinter(object): + """Baseclass for sub-pretty-printers. + + Sub-pretty-printers needn't use this, but it formalizes what's needed. + + Attributes: + name: The name of the subprinter. + enabled: A boolean indicating if the subprinter is enabled. + """ + + def __init__(self, name): + self.name = name + self.enabled = True + + +def register_pretty_printer(obj, printer): + """Register pretty-printer PRINTER with OBJ. + + The printer is added to the front of the search list, thus one can override + an existing printer if one needs to. + + Arguments: + obj: Either an objfile, progspace, or None (in which case the printer + is registered globally). + printer: Either a function of one argument (old way) or any object + which has attributes: name, enabled, __call__. + + Returns: + Nothing. + + Raises: + TypeError: A problem with the type of the printer. + ValueError: The printer's name contains a semicolon ";". + + If the caller wants the printer to be listable and disableable, it must + follow the PrettyPrinter API. This applies to the old way (functions) too. + If printer is an object, __call__ is a method of two arguments: + self, and the value to be pretty-printed. See PrettyPrinter. + """ + + # Watch for both __name__ and name. + # Functions get the former for free, but we don't want to use an + # attribute named __foo__ for pretty-printers-as-objects. + # If printer has both, we use `name'. + if not hasattr(printer, "__name__") and not hasattr(printer, "name"): + raise TypeError("printer missing attribute: name") + if hasattr(printer, "name") and not hasattr(printer, "enabled"): + raise TypeError("printer missing attribute: enabled") + if not hasattr(printer, "__call__"): + raise TypeError("printer missing attribute: __call__") + + if obj is None: + if gdb.parameter("verbose"): + gdb.write("Registering global %s pretty-printer ...\n" % name) + obj = gdb + else: + if gdb.parameter("verbose"): + gdb.write("Registering %s pretty-printer for %s ...\n" % + (printer.name, obj.filename)) + + if hasattr(printer, "name"): + if not isinstance(printer.name, basestring): + raise TypeError("printer name is not a string") + # If printer provides a name, make sure it doesn't contain ";". + # Semicolon is used by the info/enable/disable pretty-printer commands + # to delimit subprinters. + if printer.name.find(";") >= 0: + raise ValueError("semicolon ';' in printer name") + # Also make sure the name is unique. + # Alas, we can't do the same for functions and __name__, they could + # all have a canonical name like "lookup_function". + # PERF: gdb records printers in a list, making this inefficient. + if (printer.name in + [p.name for p in obj.pretty_printers if hasattr(p, "name")]): + raise RuntimeError("pretty-printer already registered: %s" % + printer.name) + + obj.pretty_printers.insert(0, printer) + + +class RegexpCollectionPrettyPrinter(PrettyPrinter): + """Class for implementing a collection of regular-expression based pretty-printers. + + Intended usage: + + pretty_printer = RegexpCollectionPrettyPrinter("my_library") + pretty_printer.add_printer("myclass1", "^myclass1$", MyClass1Printer) + ... + pretty_printer.add_printer("myclassN", "^myclassN$", MyClassNPrinter) + register_pretty_printer(obj, pretty_printer) + """ + + class RegexpSubprinter(SubPrettyPrinter): + def __init__(self, name, regexp, gen_printer): + super(RegexpCollectionPrettyPrinter.RegexpSubprinter, self).__init__(name) + self.regexp = regexp + self.gen_printer = gen_printer + self.compiled_re = re.compile(regexp) + + def __init__(self, name): + super(RegexpCollectionPrettyPrinter, self).__init__(name, []) + + def add_printer(self, name, regexp, gen_printer): + """Add a printer to the list. + + The printer is added to the end of the list. + + Arguments: + name: The name of the subprinter. + regexp: The regular expression, as a string. + gen_printer: A function/method that given a value returns an + object to pretty-print it. + + Returns: + Nothing. + """ + + # NOTE: A previous version made the name of each printer the regexp. + # That makes it awkward to pass to the enable/disable commands (it's + # cumbersome to make a regexp of a regexp). So now the name is a + # separate parameter. + + self.subprinters.append(self.RegexpSubprinter(name, regexp, + gen_printer)) + + def __call__(self, val): + """Lookup the pretty-printer for the provided value.""" + + # Get the type name. + typename = gdb.types.get_basic_type(val.type).tag + if not typename: + return None + + # Iterate over table of type regexps to determine + # if a printer is registered for that type. + # Return an instantiation of the printer if found. + for printer in self.subprinters: + if printer.enabled and printer.compiled_re.search(typename): + return printer.gen_printer(val) + + # Cannot find a pretty printer. Return None. + return None diff --git a/contrib/gdb-7/gdb/python/lib/gdb/types.py b/contrib/gdb-7/gdb/python/lib/gdb/types.py new file mode 100644 index 0000000000..54fbe3c7bf --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/types.py @@ -0,0 +1,91 @@ +# Type utilities. +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Utilities for working with gdb.Types.""" + +import gdb + + +def get_basic_type(type_): + """Return the "basic" type of a type. + + Arguments: + type_: The type to reduce to its basic type. + + Returns: + type_ with const/volatile is stripped away, + and typedefs/references converted to the underlying type. + """ + + while (type_.code == gdb.TYPE_CODE_REF or + type_.code == gdb.TYPE_CODE_TYPEDEF): + if type_.code == gdb.TYPE_CODE_REF: + type_ = type_.target() + else: + type_ = type_.strip_typedefs() + return type_.unqualified() + + +def has_field(type_, field): + """Return True if a type has the specified field. + + Arguments: + type_: The type to examine. + It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION. + field: The name of the field to look up. + + Returns: + True if the field is present either in type_ or any baseclass. + + Raises: + TypeError: The type is not a struct or union. + """ + + type_ = get_basic_type(type_) + if (type_.code != gdb.TYPE_CODE_STRUCT and + type_.code != gdb.TYPE_CODE_UNION): + raise TypeError("not a struct or union") + for f in type_.fields(): + if f.is_base_class: + if has_field(f.type, field): + return True + else: + # NOTE: f.name could be None + if f.name == field: + return True + return False + + +def make_enum_dict(enum_type): + """Return a dictionary from a program's enum type. + + Arguments: + enum_type: The enum to compute the dictionary for. + + Returns: + The dictionary of the enum. + + Raises: + TypeError: The type is not an enum. + """ + + if enum_type.code != gdb.TYPE_CODE_ENUM: + raise TypeError("not an enum type") + enum_dict = {} + for field in enum_type.fields(): + # The enum's value is stored in "bitpos". + enum_dict[field.name] = field.bitpos + return enum_dict diff --git a/contrib/gdb-7/gdb/python/py-auto-load.c b/contrib/gdb-7/gdb/python/py-auto-load.c index 044d968b57..e822838ebd 100644 --- a/contrib/gdb-7/gdb/python/py-auto-load.c +++ b/contrib/gdb-7/gdb/python/py-auto-load.c @@ -1,6 +1,6 @@ /* GDB routines for supporting auto-loaded scripts. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -34,7 +34,7 @@ This is true if we should auto-load python code when an objfile is opened, false otherwise. - Both gdbpy_auto_load && gdbpy_global_auto_load must be true to enable + Both auto_load_scripts && gdbpy_global_auto_load must be true to enable auto-loading. This flag exists to facilitate deferring auto-loading during start-up @@ -82,10 +82,15 @@ struct loaded_script_entry }; /* User-settable option to enable/disable auto-loading: - maint set python auto-load on|off - This is true if we should auto-load python code when an objfile is opened, - false otherwise. */ -static int gdbpy_auto_load = 1; + set auto-load-scripts on|off + This is true if we should auto-load associated scripts when an objfile + is opened, false otherwise. + At the moment, this only affects python scripts, but there's no reason + one couldn't also have other kinds of auto-loaded scripts, and there's + no reason to have them each controlled by a separate flag. + So we elide "python" from the name here and in the option. + The fact that it lives here is just an implementation detail. */ +static int auto_load_scripts = 1; /* Per-program-space data key. */ static const struct program_space_data *auto_load_pspace_data; @@ -395,8 +400,6 @@ auto_load_new_objfile (struct objfile *objfile) clear_section_scripts (); return; } - if (!objfile->name) - return; load_auto_scripts_for_objfile (objfile); } @@ -406,7 +409,7 @@ auto_load_new_objfile (struct objfile *objfile) void load_auto_scripts_for_objfile (struct objfile *objfile) { - if (gdbpy_auto_load && gdbpy_global_auto_load) + if (auto_load_scripts && gdbpy_global_auto_load) { auto_load_objfile_script (objfile, GDBPY_AUTO_FILE_NAME); auto_load_section_scripts (objfile, GDBPY_AUTO_SECTION_NAME); @@ -473,16 +476,18 @@ gdbpy_initialize_auto_load (void) observer_attach_new_objfile (auto_load_new_objfile); - add_setshow_boolean_cmd ("auto-load", class_maintenance, - &gdbpy_auto_load, _("\ -Enable or disable auto-loading of Python code when an object is opened."), _("\ -Show whether Python code will be auto-loaded when an object is opened."), _("\ -Enables or disables auto-loading of Python code when an object is opened."), + add_setshow_boolean_cmd ("auto-load-scripts", class_support, + &auto_load_scripts, _("\ +Set the debugger's behaviour regarding auto-loaded scripts."), _("\ +Show the debugger's behaviour regarding auto-loaded scripts."), _("\ +If enabled, auto-loaded scripts are loaded when the debugger reads\n\ +an executable or shared library."), NULL, NULL, - &set_python_list, - &show_python_list); + &setlist, + &showlist); - add_cmd ("section-scripts", class_maintenance, maintenance_print_section_scripts, + add_cmd ("section-scripts", class_maintenance, + maintenance_print_section_scripts, _("Print dump of auto-loaded section scripts matching REGEXP."), &maintenanceprintlist); } diff --git a/contrib/gdb-7/gdb/python/py-block.c b/contrib/gdb-7/gdb/python/py-block.c new file mode 100644 index 0000000000..08d4455508 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-block.c @@ -0,0 +1,463 @@ +/* Python interface to blocks. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "block.h" +#include "dictionary.h" +#include "symtab.h" +#include "python-internal.h" +#include "objfiles.h" +#include "symtab.h" + +typedef struct blpy_block_object { + PyObject_HEAD + /* The GDB block structure that represents a frame's code block. */ + struct block *block; + /* The backing object file. There is no direct relationship in GDB + between a block and an object file. When a block is created also + store a pointer to the object file for later use. */ + struct objfile *objfile; + /* Keep track of all blocks with a doubly-linked list. Needed for + block invalidation if the source object file has been freed. */ + struct blpy_block_object *prev; + struct blpy_block_object *next; +} block_object; + +typedef struct { + PyObject_HEAD + /* The block dictionary of symbols. */ + struct dictionary *dict; + /* The iterator for that dictionary. */ + struct dict_iterator iter; + /* Has the iterator been initialized flag. */ + int initialized_p; + /* Pointer back to the original source block object. Needed to + check if the block is still valid, and has not been invalidated + when an object file has been freed. */ + struct blpy_block_object *source; +} block_syms_iterator_object; + +/* Require a valid block. All access to block_object->block should be + gated by this call. */ +#define BLPY_REQUIRE_VALID(block_obj, block) \ + do { \ + block = block_object_to_block (block_obj); \ + if (block == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Block is invalid.")); \ + return NULL; \ + } \ + } while (0) + +/* Require a valid block. This macro is called during block iterator + creation, and at each next call. */ +#define BLPY_ITER_REQUIRE_VALID(block_obj) \ + do { \ + if (block_obj->block == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Source block for iterator is invalid.")); \ + return NULL; \ + } \ + } while (0) + +static PyTypeObject block_syms_iterator_object_type; +static const struct objfile_data *blpy_objfile_data_key; + +static PyObject * +blpy_iter (PyObject *self) +{ + block_syms_iterator_object *block_iter_obj; + struct block *block = NULL; + + BLPY_REQUIRE_VALID (self, block); + + block_iter_obj = PyObject_New (block_syms_iterator_object, + &block_syms_iterator_object_type); + if (block_iter_obj == NULL) + return NULL; + + block_iter_obj->dict = BLOCK_DICT (block); + block_iter_obj->initialized_p = 0; + Py_INCREF (self); + block_iter_obj->source = (block_object *) self; + + return (PyObject *) block_iter_obj; +} + +static PyObject * +blpy_get_start (PyObject *self, void *closure) +{ + struct block *block = NULL; + + BLPY_REQUIRE_VALID (self, block); + + return gdb_py_object_from_ulongest (BLOCK_START (block)); +} + +static PyObject * +blpy_get_end (PyObject *self, void *closure) +{ + struct block *block = NULL; + + BLPY_REQUIRE_VALID (self, block); + + return gdb_py_object_from_ulongest (BLOCK_END (block)); +} + +static PyObject * +blpy_get_function (PyObject *self, void *closure) +{ + struct symbol *sym; + struct block *block = NULL; + + BLPY_REQUIRE_VALID (self, block); + + sym = BLOCK_FUNCTION (block); + if (sym) + return symbol_to_symbol_object (sym); + + Py_RETURN_NONE; +} + +static PyObject * +blpy_get_superblock (PyObject *self, void *closure) +{ + struct block *block = NULL; + struct block *super_block = NULL; + block_object *self_obj = (block_object *) self; + + BLPY_REQUIRE_VALID (self, block); + + super_block = BLOCK_SUPERBLOCK (block); + if (super_block) + return block_to_block_object (super_block, self_obj->objfile); + + Py_RETURN_NONE; +} + +static void +blpy_dealloc (PyObject *obj) +{ + block_object *block = (block_object *) obj; + + if (block->prev) + block->prev->next = block->next; + else if (block->objfile) + { + set_objfile_data (block->objfile, blpy_objfile_data_key, + block->next); + } + if (block->next) + block->next->prev = block->prev; + block->block = NULL; +} + +/* Given a block, and a block_object that has previously been + allocated and initialized, populate the block_object with the + struct block data. Also, register the block_object life-cycle + with the life-cycle of the object file associated with this + block, if needed. */ +static void +set_block (block_object *obj, struct block *block, + struct objfile *objfile) +{ + obj->block = block; + obj->prev = NULL; + if (objfile) + { + obj->objfile = objfile; + obj->next = objfile_data (objfile, blpy_objfile_data_key); + if (obj->next) + obj->next->prev = obj; + set_objfile_data (objfile, blpy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +/* Create a new block object (gdb.Block) that encapsulates the struct + block object from GDB. */ +PyObject * +block_to_block_object (struct block *block, struct objfile *objfile) +{ + block_object *block_obj; + + block_obj = PyObject_New (block_object, &block_object_type); + if (block_obj) + set_block (block_obj, block, objfile); + + return (PyObject *) block_obj; +} + +/* Return struct block reference that is wrapped by this object. */ +struct block * +block_object_to_block (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &block_object_type)) + return NULL; + return ((block_object *) obj)->block; +} + +/* Return a reference to the block iterator. */ +static PyObject * +blpy_block_syms_iter (PyObject *self) +{ + block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self; + + BLPY_ITER_REQUIRE_VALID (iter_obj->source); + + Py_INCREF (self); + return self; +} + +/* Return the next symbol in the iteration through the block's + dictionary. */ +static PyObject * +blpy_block_syms_iternext (PyObject *self) +{ + block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self; + struct symbol *sym; + + BLPY_ITER_REQUIRE_VALID (iter_obj->source); + + if (!iter_obj->initialized_p) + { + sym = dict_iterator_first (iter_obj->dict, &(iter_obj->iter)); + iter_obj->initialized_p = 1; + } + else + sym = dict_iterator_next (&(iter_obj->iter)); + + if (sym == NULL) + { + PyErr_SetString (PyExc_StopIteration, _("Symbol is null.")); + return NULL; + } + + return symbol_to_symbol_object (sym); +} + +static void +blpy_block_syms_dealloc (PyObject *obj) +{ + block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) obj; + + Py_XDECREF (iter_obj->source); +} + +/* Implementation of gdb.Block.is_valid (self) -> Boolean. + Returns True if this block object still exists in GDB. */ + +static PyObject * +blpy_is_valid (PyObject *self, PyObject *args) +{ + struct block *block; + + block = block_object_to_block (self); + if (block == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Implementation of gdb.BlockIterator.is_valid (self) -> Boolean. + Returns True if this block iterator object still exists in GDB */ + +static PyObject * +blpy_iter_is_valid (PyObject *self, PyObject *args) +{ + block_syms_iterator_object *iter_obj = + (block_syms_iterator_object *) self; + + if (iter_obj->source->block == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Return the innermost lexical block containing the specified pc value, + or 0 if there is none. */ +PyObject * +gdbpy_block_for_pc (PyObject *self, PyObject *args) +{ + gdb_py_ulongest pc; + struct block *block; + struct obj_section *section; + struct symtab *symtab; + + if (!PyArg_ParseTuple (args, GDB_PY_LLU_ARG, &pc)) + return NULL; + + section = find_pc_mapped_section (pc); + symtab = find_pc_sect_symtab (pc, section); + if (!symtab || symtab->objfile == NULL) + { + PyErr_SetString (PyExc_RuntimeError, + _("Cannot locate object file for block.")); + return NULL; + } + + block = block_for_pc (pc); + if (block) + return block_to_block_object (block, symtab->objfile); + + Py_RETURN_NONE; +} + +/* This function is called when an objfile is about to be freed. + Invalidate the block as further actions on the block would result + in bad data. All access to obj->symbol should be gated by + BLPY_REQUIRE_VALID which will raise an exception on invalid + blocks. */ +static void +del_objfile_blocks (struct objfile *objfile, void *datum) +{ + block_object *obj = datum; + + while (obj) + { + block_object *next = obj->next; + + obj->block = NULL; + obj->objfile = NULL; + obj->next = NULL; + obj->prev = NULL; + + obj = next; + } +} + +void +gdbpy_initialize_blocks (void) +{ + block_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&block_object_type) < 0) + return; + + block_syms_iterator_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&block_syms_iterator_object_type) < 0) + return; + + /* Register an objfile "free" callback so we can properly + invalidate blocks when an object file is about to be + deleted. */ + blpy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, del_objfile_blocks); + + Py_INCREF (&block_object_type); + PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type); + + Py_INCREF (&block_syms_iterator_object_type); + PyModule_AddObject (gdb_module, "BlockIterator", + (PyObject *) &block_syms_iterator_object_type); +} + + + +static PyMethodDef block_object_methods[] = { + { "is_valid", blpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this block is valid, false if not." }, + {NULL} /* Sentinel */ +}; + +static PyGetSetDef block_object_getset[] = { + { "start", blpy_get_start, NULL, "Start address of the block.", NULL }, + { "end", blpy_get_end, NULL, "End address of the block.", NULL }, + { "function", blpy_get_function, NULL, + "Symbol that names the block, or None.", NULL }, + { "superblock", blpy_get_superblock, NULL, + "Block containing the block, or None.", NULL }, + { NULL } /* Sentinel */ +}; + +PyTypeObject block_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Block", /*tp_name*/ + sizeof (block_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + blpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB block object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + blpy_iter, /* tp_iter */ + 0, /* tp_iternext */ + block_object_methods, /* tp_methods */ + 0, /* tp_members */ + block_object_getset /* tp_getset */ +}; + +static PyMethodDef block_iterator_object_methods[] = { + { "is_valid", blpy_iter_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this block iterator is valid, false if not." }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject block_syms_iterator_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.BlockIterator", /*tp_name*/ + sizeof (block_syms_iterator_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + blpy_block_syms_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB block syms iterator object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + blpy_block_syms_iter, /*tp_iter */ + blpy_block_syms_iternext, /*tp_iternext */ + block_iterator_object_methods /*tp_methods */ +}; diff --git a/contrib/gdb-7/gdb/python/py-bpevent.c b/contrib/gdb-7/gdb/python/py-bpevent.c new file mode 100644 index 0000000000..c7f79654a1 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-bpevent.c @@ -0,0 +1,52 @@ +/* Python interface to inferior breakpoint stop events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-stopevent.h" + +static PyTypeObject breakpoint_event_object_type; + +/* Create and initialize a BreakpointEvent object. */ + +PyObject * +create_breakpoint_event_object (PyObject *breakpoint) +{ + PyObject *breakpoint_event_obj = + create_stop_event_object (&breakpoint_event_object_type); + + if (!breakpoint_event_obj) + goto fail; + + if (evpy_add_attribute (breakpoint_event_obj, + "breakpoint", + breakpoint) < 0) + goto fail; + + return breakpoint_event_obj; + + fail: + Py_XDECREF (breakpoint_event_obj); + return NULL; +} + +GDBPY_NEW_EVENT_TYPE (breakpoint, + "gdb.BreakpointEvent", + "BreakpointEvent", + "GDB breakpoint stop event object", + stop_event_object_type, + static); diff --git a/contrib/gdb-7/gdb/python/py-breakpoint.c b/contrib/gdb-7/gdb/python/py-breakpoint.c new file mode 100644 index 0000000000..0c21bfc302 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-breakpoint.c @@ -0,0 +1,1019 @@ +/* Python interface to breakpoints + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "breakpoint.h" +#include "gdbcmd.h" +#include "gdbthread.h" +#include "observer.h" +#include "cli/cli-script.h" +#include "ada-lang.h" +#include "arch-utils.h" +#include "language.h" + +static PyTypeObject breakpoint_object_type; + +/* Number of live breakpoints. */ +static int bppy_live; + +/* Variables used to pass information between the Breakpoint + constructor and the breakpoint-created hook function. */ +static breakpoint_object *bppy_pending_object; + +/* Function that is called when a Python condition is evaluated. */ +static char * const stop_func = "stop"; + +struct breakpoint_object +{ + PyObject_HEAD + + /* The breakpoint number according to gdb. */ + int number; + + /* The gdb breakpoint object, or NULL if the breakpoint has been + deleted. */ + struct breakpoint *bp; +}; + +/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python + exception if it is invalid. */ +#define BPPY_REQUIRE_VALID(Breakpoint) \ + do { \ + if ((Breakpoint)->bp == NULL) \ + return PyErr_Format (PyExc_RuntimeError, \ + _("Breakpoint %d is invalid."), \ + (Breakpoint)->number); \ + } while (0) + +/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python + exception if it is invalid. This macro is for use in setter functions. */ +#define BPPY_SET_REQUIRE_VALID(Breakpoint) \ + do { \ + if ((Breakpoint)->bp == NULL) \ + { \ + PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \ + (Breakpoint)->number); \ + return -1; \ + } \ + } while (0) + +/* This is used to initialize various gdb.bp_* constants. */ +struct pybp_code +{ + /* The name. */ + const char *name; + /* The code. */ + enum type_code code; +}; + +/* Entries related to the type of user set breakpoints. */ +static struct pybp_code pybp_codes[] = +{ + { "BP_NONE", bp_none}, + { "BP_BREAKPOINT", bp_breakpoint}, + { "BP_WATCHPOINT", bp_watchpoint}, + { "BP_HARDWARE_WATCHPOINT", bp_hardware_watchpoint}, + { "BP_READ_WATCHPOINT", bp_read_watchpoint}, + { "BP_ACCESS_WATCHPOINT", bp_access_watchpoint}, + {NULL} /* Sentinel. */ +}; + +/* Entries related to the type of watchpoint. */ +static struct pybp_code pybp_watch_types[] = +{ + { "WP_READ", hw_read}, + { "WP_WRITE", hw_write}, + { "WP_ACCESS", hw_access}, + {NULL} /* Sentinel. */ +}; + +/* Python function which checks the validity of a breakpoint object. */ +static PyObject * +bppy_is_valid (PyObject *self, PyObject *args) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + if (self_bp->bp) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +/* Python function to test whether or not the breakpoint is enabled. */ +static PyObject * +bppy_get_enabled (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + if (! self_bp->bp) + Py_RETURN_FALSE; + if (self_bp->bp->enable_state == bp_enabled) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +/* Python function to test whether or not the breakpoint is silent. */ +static PyObject * +bppy_get_silent (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + if (self_bp->bp->silent) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +/* Python function to set the enabled state of a breakpoint. */ +static int +bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + int cmp; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `enabled' attribute.")); + + return -1; + } + else if (! PyBool_Check (newvalue)) + { + PyErr_SetString (PyExc_TypeError, + _("The value of `enabled' must be a boolean.")); + return -1; + } + + cmp = PyObject_IsTrue (newvalue); + if (cmp < 0) + return -1; + else if (cmp == 1) + enable_breakpoint (self_bp->bp); + else + disable_breakpoint (self_bp->bp); + return 0; +} + +/* Python function to set the 'silent' state of a breakpoint. */ +static int +bppy_set_silent (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + int cmp; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `silent' attribute.")); + return -1; + } + else if (! PyBool_Check (newvalue)) + { + PyErr_SetString (PyExc_TypeError, + _("The value of `silent' must be a boolean.")); + return -1; + } + + cmp = PyObject_IsTrue (newvalue); + if (cmp < 0) + return -1; + else + breakpoint_set_silent (self_bp->bp, cmp); + + return 0; +} + +/* Python function to set the thread of a breakpoint. */ +static int +bppy_set_thread (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + long id; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `thread' attribute.")); + return -1; + } + else if (PyInt_Check (newvalue)) + { + if (! gdb_py_int_as_long (newvalue, &id)) + return -1; + + if (! valid_thread_id (id)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Invalid thread ID.")); + return -1; + } + } + else if (newvalue == Py_None) + id = -1; + else + { + PyErr_SetString (PyExc_TypeError, + _("The value of `thread' must be an integer or None.")); + return -1; + } + + breakpoint_set_thread (self_bp->bp, id); + + return 0; +} + +/* Python function to set the (Ada) task of a breakpoint. */ +static int +bppy_set_task (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + long id; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `task' attribute.")); + return -1; + } + else if (PyInt_Check (newvalue)) + { + if (! gdb_py_int_as_long (newvalue, &id)) + return -1; + + if (! valid_task_id (id)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Invalid task ID.")); + return -1; + } + } + else if (newvalue == Py_None) + id = 0; + else + { + PyErr_SetString (PyExc_TypeError, + _("The value of `task' must be an integer or None.")); + return -1; + } + + breakpoint_set_task (self_bp->bp, id); + + return 0; +} + +/* Python function which deletes the underlying GDB breakpoint. This + triggers the breakpoint_deleted observer which will call + gdbpy_breakpoint_deleted; that function cleans up the Python + sections. */ + +static PyObject * +bppy_delete_breakpoint (PyObject *self, PyObject *args) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + delete_breakpoint (self_bp->bp); + + Py_RETURN_NONE; +} + + +/* Python function to set the ignore count of a breakpoint. */ +static int +bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + long value; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `ignore_count' attribute.")); + return -1; + } + else if (! PyInt_Check (newvalue)) + { + PyErr_SetString (PyExc_TypeError, + _("The value of `ignore_count' must be an integer.")); + return -1; + } + + if (! gdb_py_int_as_long (newvalue, &value)) + return -1; + + if (value < 0) + value = 0; + set_ignore_count (self_bp->number, (int) value, 0); + + return 0; +} + +/* Python function to set the hit count of a breakpoint. */ +static int +bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `hit_count' attribute.")); + return -1; + } + else + { + long value; + + if (! gdb_py_int_as_long (newvalue, &value)) + return -1; + + if (value != 0) + { + PyErr_SetString (PyExc_AttributeError, + _("The value of `hit_count' must be zero.")); + return -1; + } + } + + self_bp->bp->hit_count = 0; + + return 0; +} + +/* Python function to get the location of a breakpoint. */ +static PyObject * +bppy_get_location (PyObject *self, void *closure) +{ + char *str; + breakpoint_object *obj = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (obj); + + if (obj->bp->type != bp_breakpoint) + Py_RETURN_NONE; + + str = obj->bp->addr_string; + + if (! str) + str = ""; + return PyString_Decode (str, strlen (str), host_charset (), NULL); +} + +/* Python function to get the breakpoint expression. */ +static PyObject * +bppy_get_expression (PyObject *self, void *closure) +{ + char *str; + breakpoint_object *obj = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (obj); + + if (obj->bp->type != bp_watchpoint + && obj->bp->type != bp_hardware_watchpoint + && obj->bp->type != bp_read_watchpoint + && obj->bp->type != bp_access_watchpoint) + Py_RETURN_NONE; + + str = obj->bp->exp_string; + if (! str) + str = ""; + + return PyString_Decode (str, strlen (str), host_charset (), NULL); +} + +/* Python function to get the condition expression of a breakpoint. */ +static PyObject * +bppy_get_condition (PyObject *self, void *closure) +{ + char *str; + breakpoint_object *obj = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (obj); + + str = obj->bp->cond_string; + if (! str) + Py_RETURN_NONE; + + return PyString_Decode (str, strlen (str), host_charset (), NULL); +} + +/* Returns 0 on success. Returns -1 on error, with a python exception set. + */ + +static int +bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure) +{ + char *exp; + breakpoint_object *self_bp = (breakpoint_object *) self; + volatile struct gdb_exception except; + + BPPY_SET_REQUIRE_VALID (self_bp); + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `condition' attribute.")); + return -1; + } + else if (newvalue == Py_None) + exp = ""; + else + { + exp = python_string_to_host_string (newvalue); + if (exp == NULL) + return -1; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + set_breakpoint_condition (self_bp->bp, exp, 0); + } + + if (newvalue != Py_None) + xfree (exp); + + GDB_PY_SET_HANDLE_EXCEPTION (except); + + return 0; +} + +/* Python function to get the commands attached to a breakpoint. */ +static PyObject * +bppy_get_commands (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + struct breakpoint *bp = self_bp->bp; + long length; + volatile struct gdb_exception except; + struct ui_file *string_file; + struct cleanup *chain; + PyObject *result; + char *cmdstr; + + BPPY_REQUIRE_VALID (self_bp); + + if (! self_bp->bp->commands) + Py_RETURN_NONE; + + string_file = mem_fileopen (); + chain = make_cleanup_ui_file_delete (string_file); + + ui_out_redirect (uiout, string_file); + TRY_CATCH (except, RETURN_MASK_ALL) + { + print_command_lines (uiout, breakpoint_commands (bp), 0); + } + ui_out_redirect (uiout, NULL); + GDB_PY_HANDLE_EXCEPTION (except); + + cmdstr = ui_file_xstrdup (string_file, &length); + make_cleanup (xfree, cmdstr); + result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (), NULL); + do_cleanups (chain); + return result; +} + +/* Python function to get the breakpoint type. */ +static PyObject * +bppy_get_type (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + return PyInt_FromLong (self_bp->bp->type); +} + +/* Python function to get the visibility of the breakpoint. */ + +static PyObject * +bppy_get_visibility (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + if (self_bp->bp->number < 0) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Python function to get the breakpoint's number. */ +static PyObject * +bppy_get_number (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + return PyInt_FromLong (self_bp->number); +} + +/* Python function to get the breakpoint's thread ID. */ +static PyObject * +bppy_get_thread (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + if (self_bp->bp->thread == -1) + Py_RETURN_NONE; + + return PyInt_FromLong (self_bp->bp->thread); +} + +/* Python function to get the breakpoint's task ID (in Ada). */ +static PyObject * +bppy_get_task (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + if (self_bp->bp->task == 0) + Py_RETURN_NONE; + + return PyInt_FromLong (self_bp->bp->task); +} + +/* Python function to get the breakpoint's hit count. */ +static PyObject * +bppy_get_hit_count (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + return PyInt_FromLong (self_bp->bp->hit_count); +} + +/* Python function to get the breakpoint's ignore count. */ +static PyObject * +bppy_get_ignore_count (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + return PyInt_FromLong (self_bp->bp->ignore_count); +} + +/* Python function to create a new breakpoint. */ +static int +bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL }; + char *spec; + int type = bp_breakpoint; + int access_type = hw_write; + PyObject *internal = NULL; + int internal_bp = 0; + volatile struct gdb_exception except; + + if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords, + &spec, &type, &access_type, &internal)) + return -1; + + if (internal) + { + internal_bp = PyObject_IsTrue (internal); + if (internal_bp == -1) + return -1; + } + + bppy_pending_object = (breakpoint_object *) self; + bppy_pending_object->number = -1; + bppy_pending_object->bp = NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + switch (type) + { + case bp_breakpoint: + { + create_breakpoint (python_gdbarch, + spec, NULL, -1, + 0, + 0, bp_breakpoint, + 0, + AUTO_BOOLEAN_TRUE, + NULL, 0, 1, internal_bp); + break; + } + case bp_watchpoint: + { + if (access_type == hw_write) + watch_command_wrapper (spec, 0, internal_bp); + else if (access_type == hw_access) + awatch_command_wrapper (spec, 0, internal_bp); + else if (access_type == hw_read) + rwatch_command_wrapper (spec, 0, internal_bp); + else + error(_("Cannot understand watchpoint access type.")); + break; + } + default: + error(_("Do not understand breakpoint type to set.")); + } + } + if (except.reason < 0) + { + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return -1; + } + + BPPY_SET_REQUIRE_VALID ((breakpoint_object *) self); + return 0; +} + + + +static int +build_bp_list (struct breakpoint *b, void *arg) +{ + PyObject *list = arg; + PyObject *bp = (PyObject *) b->py_bp_object; + int iserr = 0; + + /* Not all breakpoints will have a companion Python object. + Only breakpoints that were created via bppy_new, or + breakpoints that were created externally and are tracked by + the Python Scripting API. */ + if (bp) + iserr = PyList_Append (list, bp); + + if (iserr == -1) + return 1; + + return 0; +} + +/* Static function to return a tuple holding all breakpoints. */ + +PyObject * +gdbpy_breakpoints (PyObject *self, PyObject *args) +{ + PyObject *list; + + if (bppy_live == 0) + Py_RETURN_NONE; + + list = PyList_New (0); + if (!list) + return NULL; + + /* If iteratre_over_breakpoints returns non NULL it signals an error + condition. In that case abandon building the list and return + NULL. */ + if (iterate_over_breakpoints (build_bp_list, list) != NULL) + { + Py_DECREF (list); + return NULL; + } + + return PyList_AsTuple (list); +} + +/* Call the "stop" method (if implemented) in the breakpoint + class. If the method returns True, the inferior will be + stopped at the breakpoint. Otherwise the inferior will be + allowed to continue. */ + +int +gdbpy_should_stop (struct breakpoint_object *bp_obj) +{ + int stop = 1; + + PyObject *py_bp = (PyObject *) bp_obj; + struct breakpoint *b = bp_obj->bp; + struct gdbarch *garch = b->gdbarch ? b->gdbarch : get_current_arch (); + struct cleanup *cleanup = ensure_python_env (garch, current_language); + + if (PyObject_HasAttrString (py_bp, stop_func)) + { + PyObject *result = PyObject_CallMethod (py_bp, stop_func, NULL); + + if (result) + { + int evaluate = PyObject_IsTrue (result); + + if (evaluate == -1) + gdbpy_print_stack (); + + /* If the "stop" function returns False that means + the Python breakpoint wants GDB to continue. */ + if (! evaluate) + stop = 0; + + Py_DECREF (result); + } + else + gdbpy_print_stack (); + } + do_cleanups (cleanup); + + return stop; +} + +/* Checks if the "stop" method exists in this breakpoint. + Used by condition_command to ensure mutual exclusion of breakpoint + conditions. */ + +int +gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) +{ + int has_func = 0; + PyObject *py_bp = (PyObject *) bp_obj; + struct gdbarch *garch = bp_obj->bp->gdbarch ? bp_obj->bp->gdbarch : + get_current_arch (); + struct cleanup *cleanup = ensure_python_env (garch, current_language); + + if (py_bp == NULL) + return 0; + + has_func = PyObject_HasAttrString (py_bp, stop_func); + do_cleanups (cleanup); + + return has_func; +} + + + +/* Event callback functions. */ + +/* Callback that is used when a breakpoint is created. This function + will create a new Python breakpoint object. */ +static void +gdbpy_breakpoint_created (int num) +{ + breakpoint_object *newbp; + struct breakpoint *bp = NULL; + PyGILState_STATE state; + + bp = get_breakpoint (num); + if (! bp) + return; + + if (num < 0 && bppy_pending_object == NULL) + return; + + if (bp->type != bp_breakpoint + && bp->type != bp_watchpoint + && bp->type != bp_hardware_watchpoint + && bp->type != bp_read_watchpoint + && bp->type != bp_access_watchpoint) + return; + + state = PyGILState_Ensure (); + + if (bppy_pending_object) + { + newbp = bppy_pending_object; + bppy_pending_object = NULL; + } + else + newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); + if (newbp) + { + newbp->number = num; + newbp->bp = bp; + newbp->bp->py_bp_object = newbp; + Py_INCREF (newbp); + ++bppy_live; + } + else + { + PyErr_SetString (PyExc_RuntimeError, + _("Error while creating breakpoint from GDB.")); + gdbpy_print_stack (); + } + + PyGILState_Release (state); +} + +/* Callback that is used when a breakpoint is deleted. This will + invalidate the corresponding Python object. */ +static void +gdbpy_breakpoint_deleted (int num) +{ + PyGILState_STATE state; + struct breakpoint *bp = NULL; + breakpoint_object *bp_obj; + + state = PyGILState_Ensure (); + bp = get_breakpoint (num); + if (! bp) + return; + + bp_obj = bp->py_bp_object; + if (bp_obj) + { + bp_obj->bp = NULL; + --bppy_live; + Py_DECREF (bp_obj); + } + PyGILState_Release (state); +} + + + +/* Initialize the Python breakpoint code. */ +void +gdbpy_initialize_breakpoints (void) +{ + int i; + + if (PyType_Ready (&breakpoint_object_type) < 0) + return; + + Py_INCREF (&breakpoint_object_type); + PyModule_AddObject (gdb_module, "Breakpoint", + (PyObject *) &breakpoint_object_type); + + observer_attach_breakpoint_created (gdbpy_breakpoint_created); + observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted); + + /* Add breakpoint types constants. */ + for (i = 0; pybp_codes[i].name; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + /* Cast needed for Python 2.4. */ + (char *) pybp_codes[i].name, + pybp_codes[i].code) < 0) + return; + } + + /* Add watchpoint types constants. */ + for (i = 0; pybp_watch_types[i].name; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + /* Cast needed for Python 2.4. */ + (char *) pybp_watch_types[i].name, + pybp_watch_types[i].code) < 0) + return; + } + +} + + + +/* Helper function that overrides this Python object's + PyObject_GenericSetAttr to allow extra validation of the attribute + being set. */ + +static int +local_setattro (PyObject *self, PyObject *name, PyObject *v) +{ + breakpoint_object *obj = (breakpoint_object *) self; + char *attr = python_string_to_host_string (name); + + if (attr == NULL) + return -1; + + /* If the attribute trying to be set is the "stop" method, + but we already have a condition set in the CLI, disallow this + operation. */ + if (strcmp (attr, stop_func) == 0 && obj->bp->cond_string) + { + xfree (attr); + PyErr_SetString (PyExc_RuntimeError, + _("Cannot set 'stop' method. There is an " \ + "existing GDB condition attached to the " \ + "breakpoint.")); + return -1; + } + + xfree (attr); + + return PyObject_GenericSetAttr ((PyObject *)self, name, v); +} + +static PyGetSetDef breakpoint_object_getset[] = { + { "enabled", bppy_get_enabled, bppy_set_enabled, + "Boolean telling whether the breakpoint is enabled.", NULL }, + { "silent", bppy_get_silent, bppy_set_silent, + "Boolean telling whether the breakpoint is silent.", NULL }, + { "thread", bppy_get_thread, bppy_set_thread, + "Thread ID for the breakpoint.\n\ +If the value is a thread ID (integer), then this is a thread-specific breakpoint.\n\ +If the value is None, then this breakpoint is not thread-specific.\n\ +No other type of value can be used.", NULL }, + { "task", bppy_get_task, bppy_set_task, + "Thread ID for the breakpoint.\n\ +If the value is a task ID (integer), then this is an Ada task-specific breakpoint.\n\ +If the value is None, then this breakpoint is not task-specific.\n\ +No other type of value can be used.", NULL }, + { "ignore_count", bppy_get_ignore_count, bppy_set_ignore_count, + "Number of times this breakpoint should be automatically continued.", + NULL }, + { "number", bppy_get_number, NULL, + "Breakpoint's number assigned by GDB.", NULL }, + { "hit_count", bppy_get_hit_count, bppy_set_hit_count, + "Number of times the breakpoint has been hit.\n\ +Can be set to zero to clear the count. No other value is valid\n\ +when setting this property.", NULL }, + { "location", bppy_get_location, NULL, + "Location of the breakpoint, as specified by the user.", NULL}, + { "expression", bppy_get_expression, NULL, + "Expression of the breakpoint, as specified by the user.", NULL}, + { "condition", bppy_get_condition, bppy_set_condition, + "Condition of the breakpoint, as specified by the user,\ +or None if no condition set."}, + { "commands", bppy_get_commands, NULL, + "Commands of the breakpoint, as specified by the user."}, + { "type", bppy_get_type, NULL, + "Type of breakpoint."}, + { "visible", bppy_get_visibility, NULL, + "Whether the breakpoint is visible to the user."}, + { NULL } /* Sentinel. */ +}; + +static PyMethodDef breakpoint_object_methods[] = +{ + { "is_valid", bppy_is_valid, METH_NOARGS, + "Return true if this breakpoint is valid, false if not." }, + { "delete", bppy_delete_breakpoint, METH_NOARGS, + "Delete the underlying GDB breakpoint." }, + { NULL } /* Sentinel. */ +}; + +static PyTypeObject breakpoint_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Breakpoint", /*tp_name*/ + sizeof (breakpoint_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + (setattrofunc)local_setattro, /*tp_setattro */ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB breakpoint object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + breakpoint_object_methods, /* tp_methods */ + 0, /* tp_members */ + breakpoint_object_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + bppy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-cmd.c b/contrib/gdb-7/gdb/python/py-cmd.c new file mode 100644 index 0000000000..c0e3291411 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-cmd.c @@ -0,0 +1,699 @@ +/* gdb commands implemented in Python + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "defs.h" +#include "arch-utils.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbcmd.h" +#include "cli/cli-decode.h" +#include "completer.h" +#include "language.h" + +/* Struct representing built-in completion types. */ +struct cmdpy_completer +{ + /* Python symbol name. */ + char *name; + /* Completion function. */ + char **(*completer) (struct cmd_list_element *, char *, char *); +}; + +static struct cmdpy_completer completers[] = +{ + { "COMPLETE_NONE", noop_completer }, + { "COMPLETE_FILENAME", filename_completer }, + { "COMPLETE_LOCATION", location_completer }, + { "COMPLETE_COMMAND", command_completer }, + { "COMPLETE_SYMBOL", make_symbol_completion_list_fn }, +}; + +#define N_COMPLETERS (sizeof (completers) / sizeof (completers[0])) + +/* A gdb command. For the time being only ordinary commands (not + set/show commands) are allowed. */ +struct cmdpy_object +{ + PyObject_HEAD + + /* The corresponding gdb command object, or NULL if the command is + no longer installed. */ + struct cmd_list_element *command; + + /* A prefix command requires storage for a list of its sub-commands. + A pointer to this is passed to add_prefix_command, and to add_cmd + for sub-commands of that prefix. If this Command is not a prefix + command, then this field is unused. */ + struct cmd_list_element *sub_list; +}; + +typedef struct cmdpy_object cmdpy_object; + +static PyTypeObject cmdpy_object_type; + + +/* Constants used by this module. */ +static PyObject *invoke_cst; +static PyObject *complete_cst; + + + +/* Python function which wraps dont_repeat. */ +static PyObject * +cmdpy_dont_repeat (PyObject *self, PyObject *args) +{ + dont_repeat (); + Py_RETURN_NONE; +} + + + +/* Called if the gdb cmd_list_element is destroyed. */ + +static void +cmdpy_destroyer (struct cmd_list_element *self, void *context) +{ + cmdpy_object *cmd; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + /* Release our hold on the command object. */ + cmd = (cmdpy_object *) context; + cmd->command = NULL; + Py_DECREF (cmd); + + /* We allocated the name, doc string, and perhaps the prefix + name. */ + xfree (self->name); + xfree (self->doc); + xfree (self->prefixname); + + do_cleanups (cleanup); +} + +/* Called by gdb to invoke the command. */ + +static void +cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) +{ + cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command); + PyObject *argobj, *ttyobj, *result; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (! obj) + error (_("Invalid invocation of Python command object.")); + if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst)) + { + if (obj->command->prefixname) + { + /* A prefix command does not need an invoke method. */ + do_cleanups (cleanup); + return; + } + error (_("Python command object missing 'invoke' method.")); + } + + if (! args) + args = ""; + argobj = PyUnicode_Decode (args, strlen (args), host_charset (), NULL); + if (! argobj) + { + gdbpy_print_stack (); + error (_("Could not convert arguments to Python string.")); + } + + ttyobj = from_tty ? Py_True : Py_False; + Py_INCREF (ttyobj); + result = PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst, argobj, + ttyobj, NULL); + Py_DECREF (argobj); + Py_DECREF (ttyobj); + + if (! result) + { + PyObject *ptype, *pvalue, *ptraceback; + char *msg; + + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + + /* Try to fetch an error message contained within ptype, pvalue. + When fetching the error message we need to make our own copy, + we no longer own ptype, pvalue after the call to PyErr_Restore. */ + + msg = gdbpy_exception_to_string (ptype, pvalue); + make_cleanup (xfree, msg); + + if (msg == NULL) + { + /* An error occurred computing the string representation of the + error message. This is rare, but we should inform the user. */ + printf_filtered (_("An error occurred in a Python command\n" + "and then another occurred computing the " + "error message.\n")); + gdbpy_print_stack (); + } + + /* Don't print the stack for gdb.GdbError exceptions. + It is generally used to flag user errors. + + We also don't want to print "Error occurred in Python command" + for user errors. However, a missing message for gdb.GdbError + exceptions is arguably a bug, so we flag it as such. */ + + if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc) + || msg == NULL || *msg == '\0') + { + PyErr_Restore (ptype, pvalue, ptraceback); + gdbpy_print_stack (); + if (msg != NULL && *msg != '\0') + error (_("Error occurred in Python command: %s"), msg); + else + error (_("Error occurred in Python command.")); + } + else + { + Py_XDECREF (ptype); + Py_XDECREF (pvalue); + Py_XDECREF (ptraceback); + error ("%s", msg); + } + } + + Py_DECREF (result); + do_cleanups (cleanup); +} + +/* Called by gdb for command completion. */ +static char ** +cmdpy_completer (struct cmd_list_element *command, char *text, char *word) +{ + cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command); + PyObject *textobj, *wordobj, *resultobj = NULL; + char **result = NULL; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (! obj) + error (_("Invalid invocation of Python command object.")); + if (! PyObject_HasAttr ((PyObject *) obj, complete_cst)) + { + /* If there is no complete method, don't error -- instead, just + say that there are no completions. */ + goto done; + } + + textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL); + if (! textobj) + error (_("Could not convert argument to Python string.")); + wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL); + if (! wordobj) + error (_("Could not convert argument to Python string.")); + + resultobj = PyObject_CallMethodObjArgs ((PyObject *) obj, complete_cst, + textobj, wordobj, NULL); + Py_DECREF (textobj); + Py_DECREF (wordobj); + if (! resultobj) + { + /* Just swallow errors here. */ + PyErr_Clear (); + goto done; + } + make_cleanup_py_decref (resultobj); + + result = NULL; + if (PySequence_Check (resultobj)) + { + Py_ssize_t i, len = PySequence_Size (resultobj); + Py_ssize_t out; + + if (len < 0) + goto done; + + result = (char **) xmalloc ((len + 1) * sizeof (char *)); + for (i = out = 0; i < len; ++i) + { + PyObject *elt = PySequence_GetItem (resultobj, i); + + if (elt == NULL || ! gdbpy_is_string (elt)) + { + /* Skip problem elements. */ + PyErr_Clear (); + continue; + } + result[out] = python_string_to_host_string (elt); + if (result[out] == NULL) + { + /* Skip problem elements. */ + PyErr_Clear (); + continue; + } + ++out; + } + result[out] = NULL; + } + else if (PyInt_Check (resultobj)) + { + /* User code may also return one of the completion constants, + thus requesting that sort of completion. */ + long value; + + if (! gdb_py_int_as_long (resultobj, &value)) + { + /* Ignore. */ + PyErr_Clear (); + } + else if (value >= 0 && value < (long) N_COMPLETERS) + result = completers[value].completer (command, text, word); + } + + done: + + do_cleanups (cleanup); + + return result; +} + +/* Helper for cmdpy_init which locates the command list to use and + pulls out the command name. + + TEXT is the command name list. The final word in the list is the + name of the new command. All earlier words must be existing prefix + commands. + + *BASE_LIST is set to the final prefix command's list of + *sub-commands. + + START_LIST is the list in which the search starts. + + This function returns the xmalloc()d name of the new command. On + error sets the Python error and returns NULL. */ +char * +gdbpy_parse_command_name (char *text, + struct cmd_list_element ***base_list, + struct cmd_list_element **start_list) +{ + struct cmd_list_element *elt; + int len = strlen (text); + int i, lastchar; + char *prefix_text; + char *result; + + /* Skip trailing whitespace. */ + for (i = len - 1; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + ; + if (i < 0) + { + PyErr_SetString (PyExc_RuntimeError, _("No command name found.")); + return NULL; + } + lastchar = i; + + /* Find first character of the final word. */ + for (; i > 0 && (isalnum (text[i - 1]) + || text[i - 1] == '-' + || text[i - 1] == '_'); + --i) + ; + result = xmalloc (lastchar - i + 2); + memcpy (result, &text[i], lastchar - i + 1); + result[lastchar - i + 1] = '\0'; + + /* Skip whitespace again. */ + for (--i; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + ; + if (i < 0) + { + *base_list = start_list; + return result; + } + + prefix_text = xmalloc (i + 2); + memcpy (prefix_text, text, i + 1); + prefix_text[i + 1] = '\0'; + + text = prefix_text; + elt = lookup_cmd_1 (&text, *start_list, NULL, 1); + if (!elt || elt == (struct cmd_list_element *) -1) + { + PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."), + prefix_text); + xfree (prefix_text); + xfree (result); + return NULL; + } + + if (elt->prefixlist) + { + xfree (prefix_text); + *base_list = elt->prefixlist; + return result; + } + + PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command."), + prefix_text); + xfree (prefix_text); + xfree (result); + return NULL; +} + +/* Object initializer; sets up gdb-side structures for command. + + Use: __init__(NAME, COMMAND_CLASS [, COMPLETER_CLASS][, PREFIX]]). + + NAME is the name of the command. It may consist of multiple words, + in which case the final word is the name of the new command, and + earlier words must be prefix commands. + + COMMAND_CLASS is the kind of command. It should be one of the COMMAND_* + constants defined in the gdb module. + + COMPLETER_CLASS is the kind of completer. If not given, the + "complete" method will be used. Otherwise, it should be one of the + COMPLETE_* constants defined in the gdb module. + + If PREFIX is True, then this command is a prefix command. + + The documentation for the command is taken from the doc string for + the python class. + +*/ +static int +cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) +{ + cmdpy_object *obj = (cmdpy_object *) self; + char *name; + int cmdtype; + int completetype = -1; + char *docstring = NULL; + volatile struct gdb_exception except; + struct cmd_list_element **cmd_list; + char *cmd_name, *pfx_name; + static char *keywords[] = { "name", "command_class", "completer_class", + "prefix", NULL }; + PyObject *is_prefix = NULL; + int cmp; + + if (obj->command) + { + /* Note: this is apparently not documented in Python. We return + 0 for success, -1 for failure. */ + PyErr_Format (PyExc_RuntimeError, + _("Command object already initialized.")); + return -1; + } + + if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iO", + keywords, &name, &cmdtype, + &completetype, &is_prefix)) + return -1; + + if (cmdtype != no_class && cmdtype != class_run + && cmdtype != class_vars && cmdtype != class_stack + && cmdtype != class_files && cmdtype != class_support + && cmdtype != class_info && cmdtype != class_breakpoint + && cmdtype != class_trace && cmdtype != class_obscure + && cmdtype != class_maintenance) + { + PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument.")); + return -1; + } + + if (completetype < -1 || completetype >= (int) N_COMPLETERS) + { + PyErr_Format (PyExc_RuntimeError, + _("Invalid completion type argument.")); + return -1; + } + + cmd_name = gdbpy_parse_command_name (name, &cmd_list, &cmdlist); + if (! cmd_name) + return -1; + + pfx_name = NULL; + if (is_prefix != NULL) + { + cmp = PyObject_IsTrue (is_prefix); + if (cmp == 1) + { + int i, out; + + /* Make a normalized form of the command name. */ + pfx_name = xmalloc (strlen (name) + 2); + + i = 0; + out = 0; + while (name[i]) + { + /* Skip whitespace. */ + while (name[i] == ' ' || name[i] == '\t') + ++i; + /* Copy non-whitespace characters. */ + while (name[i] && name[i] != ' ' && name[i] != '\t') + pfx_name[out++] = name[i++]; + /* Add a single space after each word -- including the final + word. */ + pfx_name[out++] = ' '; + } + pfx_name[out] = '\0'; + } + else if (cmp < 0) + { + xfree (cmd_name); + return -1; + } + } + if (PyObject_HasAttr (self, gdbpy_doc_cst)) + { + PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst); + + if (ds_obj && gdbpy_is_string (ds_obj)) + { + docstring = python_string_to_host_string (ds_obj); + if (docstring == NULL) + { + xfree (cmd_name); + xfree (pfx_name); + return -1; + } + } + } + if (! docstring) + docstring = xstrdup (_("This command is not documented.")); + + Py_INCREF (self); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct cmd_list_element *cmd; + + if (pfx_name) + { + int allow_unknown; + + /* If we have our own "invoke" method, then allow unknown + sub-commands. */ + allow_unknown = PyObject_HasAttr (self, invoke_cst); + cmd = add_prefix_cmd (cmd_name, (enum command_class) cmdtype, + NULL, docstring, &obj->sub_list, + pfx_name, allow_unknown, cmd_list); + } + else + cmd = add_cmd (cmd_name, (enum command_class) cmdtype, NULL, + docstring, cmd_list); + + /* There appears to be no API to set this. */ + cmd->func = cmdpy_function; + cmd->destroyer = cmdpy_destroyer; + + obj->command = cmd; + set_cmd_context (cmd, self); + set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer + : completers[completetype].completer)); + } + if (except.reason < 0) + { + xfree (cmd_name); + xfree (docstring); + xfree (pfx_name); + Py_DECREF (self); + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return -1; + } + return 0; +} + + + +/* Initialize the 'commands' code. */ +void +gdbpy_initialize_commands (void) +{ + int i; + + if (PyType_Ready (&cmdpy_object_type) < 0) + return; + + /* Note: alias and user are special; pseudo appears to be unused, + and there is no reason to expose tui or xdb, I think. */ + if (PyModule_AddIntConstant (gdb_module, "COMMAND_NONE", no_class) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_RUNNING", class_run) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_DATA", class_vars) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_STACK", class_stack) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_FILES", class_files) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_SUPPORT", + class_support) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_STATUS", class_info) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_BREAKPOINTS", + class_breakpoint) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_TRACEPOINTS", + class_trace) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE", + class_obscure) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE", + class_maintenance) < 0) + return; + + for (i = 0; i < N_COMPLETERS; ++i) + { + if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0) + return; + } + + Py_INCREF (&cmdpy_object_type); + PyModule_AddObject (gdb_module, "Command", + (PyObject *) &cmdpy_object_type); + + invoke_cst = PyString_FromString ("invoke"); + complete_cst = PyString_FromString ("complete"); +} + + + +static PyMethodDef cmdpy_object_methods[] = +{ + { "dont_repeat", cmdpy_dont_repeat, METH_NOARGS, + "Prevent command repetition when user enters empty line." }, + + { 0 } +}; + +static PyTypeObject cmdpy_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Command", /*tp_name*/ + sizeof (cmdpy_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB command object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + cmdpy_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + cmdpy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; + + + +/* Utility to build a buildargv-like result from ARGS. + This intentionally parses arguments the way libiberty/argv.c:buildargv + does. It splits up arguments in a reasonable way, and we want a standard + way of parsing arguments. Several gdb commands use buildargv to parse their + arguments. Plus we want to be able to write compatible python + implementations of gdb commands. */ + +PyObject * +gdbpy_string_to_argv (PyObject *self, PyObject *args) +{ + PyObject *py_argv; + char *input; + + if (!PyArg_ParseTuple (args, "s", &input)) + return NULL; + + py_argv = PyList_New (0); + + /* buildargv uses NULL to represent an empty argument list, but we can't use + that in Python. Instead, if ARGS is "" then return an empty list. + This undoes the NULL -> "" conversion that cmdpy_function does. */ + + if (*input != '\0') + { + char **c_argv = gdb_buildargv (input); + int i; + + for (i = 0; c_argv[i] != NULL; ++i) + { + PyObject *argp = PyString_FromString (c_argv[i]); + + if (argp == NULL + || PyList_Append (py_argv, argp) < 0) + { + if (argp != NULL) + { + Py_DECREF (argp); + } + Py_DECREF (py_argv); + freeargv (c_argv); + return NULL; + } + } + + freeargv (c_argv); + } + + return py_argv; +} diff --git a/contrib/gdb-7/gdb/python/py-continueevent.c b/contrib/gdb-7/gdb/python/py-continueevent.c new file mode 100644 index 0000000000..1338ba6b2b --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-continueevent.c @@ -0,0 +1,53 @@ +/* Python interface to inferior continue events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-event.h" + +static PyTypeObject continue_event_object_type; + +PyObject * +create_continue_event_object (void) +{ + return create_thread_event_object (&continue_event_object_type); +} + +/* Callback function which notifies observers when a continue event occurs. + This function will create a new Python continue event object. + Return -1 if emit fails. */ + +int +emit_continue_event (ptid_t ptid) +{ + PyObject *event; + + if (evregpy_no_listeners_p (gdb_py_events.cont)) + return 0; + + event = create_continue_event_object (); + if (event) + return evpy_emit_event (event, gdb_py_events.cont); + return -1; +} + +GDBPY_NEW_EVENT_TYPE (continue, + "gdb.ContinueEvent", + "ContinueEvent", + "GDB continue event object", + thread_event_object_type, + static); diff --git a/contrib/gdb-7/gdb/python/py-event.c b/contrib/gdb-7/gdb/python/py-event.c new file mode 100644 index 0000000000..88f8db6385 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-event.c @@ -0,0 +1,175 @@ +/* Python interface to inferior events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-event.h" + +void +evpy_dealloc (PyObject *self) +{ + Py_XDECREF (((event_object *) self)->dict); + self->ob_type->tp_free (self); +} + +PyObject * +create_event_object (PyTypeObject *py_type) +{ + event_object *event_obj; + + event_obj = PyObject_New (event_object, py_type); + if (!event_obj) + goto fail; + + event_obj->dict = PyDict_New (); + if (!event_obj->dict) + goto fail; + + return (PyObject*) event_obj; + + fail: + Py_XDECREF (event_obj); + return NULL; +} + +/* Add the attribute ATTR to the event object EVENT. In + python this attribute will be accessible by the name NAME. + returns 0 if the operation succeeds and -1 otherwise. */ + +int +evpy_add_attribute (PyObject *event, char *name, PyObject *attr) +{ + return PyObject_SetAttrString (event, name, attr); +} + +/* Initialize the Python event code. */ + +void +gdbpy_initialize_event (void) +{ + gdbpy_initialize_event_generic (&event_object_type, + "Event"); +} + +/* Initialize the given event type. If BASE is not NULL it will + be set as the types base. + Returns 0 if initialization was successful -1 otherwise. */ + +int +gdbpy_initialize_event_generic (PyTypeObject *type, + char *name) +{ + if (PyType_Ready (type) < 0) + goto fail; + + Py_INCREF (type); + if (PyModule_AddObject (gdb_module, name, (PyObject *) type) < 0) + goto fail; + + return 0; + + fail: + Py_XDECREF (type); + return -1; +} + + +/* Notify the list of listens that the given EVENT has occurred. + returns 0 if emit is successful -1 otherwise. */ + +int +evpy_emit_event (PyObject *event, + eventregistry_object *registry) +{ + PyObject *callback_list_copy = NULL; + Py_ssize_t i; + + /* Create a copy of call back list and use that for + notifying listeners to avoid skipping callbacks + in the case of a callback being disconnected during + a notification. */ + callback_list_copy = PySequence_List (registry->callbacks); + if (!callback_list_copy) + goto fail; + + for (i = 0; i < PyList_Size (callback_list_copy); i++) + { + PyObject *func = PyList_GetItem (callback_list_copy, i); + + if (func == NULL) + goto fail; + + if (!PyObject_CallFunctionObjArgs (func, event, NULL)) + { + /* Print the trace here, but keep going -- we want to try to + call all of the callbacks even if one is broken. */ + gdbpy_print_stack (); + } + } + + Py_XDECREF (callback_list_copy); + Py_XDECREF (event); + return 0; + + fail: + gdbpy_print_stack (); + Py_XDECREF (callback_list_copy); + Py_XDECREF (event); + return -1; +} + +PyTypeObject event_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "gdb.Event", /* tp_name */ + sizeof (event_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + evpy_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "GDB event object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof (event_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0 /* tp_alloc */ +}; diff --git a/contrib/gdb-7/gdb/python/py-event.h b/contrib/gdb-7/gdb/python/py-event.h new file mode 100644 index 0000000000..f4b3ee2569 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-event.h @@ -0,0 +1,121 @@ +/* Python interface to inferior events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PY_EVENT_H +#define GDB_PY_EVENT_H + +#include "defs.h" +#include "py-events.h" +#include "command.h" +#include "python-internal.h" +#include "inferior.h" + +/* This macro creates the following functions: + + gdbpy_initialize_{NAME}_event + Used to add the newly created event type to the gdb module. + + and the python type data structure for the event: + + struct PyTypeObject {NAME}_event_object_type + + NAME is the name of the event. + PY_PATH is a string representing the module and python name of + the event. + PY_NAME a string representing what the event should be called in + python. + DOC Python documentation for the new event type + BASE the base event for this event usually just event_object_type. + QUAL qualification for the create event usually 'static' +*/ + +#define GDBPY_NEW_EVENT_TYPE(name, py_path, py_name, doc, base, qual) \ +\ + qual PyTypeObject name##_event_object_type = \ + { \ + PyObject_HEAD_INIT (NULL) \ + 0, /* ob_size */ \ + py_path, /* tp_name */ \ + sizeof (event_object), /* tp_basicsize */ \ + 0, /* tp_itemsize */ \ + evpy_dealloc, /* tp_dealloc */ \ + 0, /* tp_print */ \ + 0, /* tp_getattr */ \ + 0, /* tp_setattr */ \ + 0, /* tp_compare */ \ + 0, /* tp_repr */ \ + 0, /* tp_as_number */ \ + 0, /* tp_as_sequence */ \ + 0, /* tp_as_mapping */ \ + 0, /* tp_hash */ \ + 0, /* tp_call */ \ + 0, /* tp_str */ \ + 0, /* tp_getattro */ \ + 0, /* tp_setattro */ \ + 0, /* tp_as_buffer */ \ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ \ + doc, /* tp_doc */ \ + 0, /* tp_traverse */ \ + 0, /* tp_clear */ \ + 0, /* tp_richcompare */ \ + 0, /* tp_weaklistoffset */ \ + 0, /* tp_iter */ \ + 0, /* tp_iternext */ \ + 0, /* tp_methods */ \ + 0, /* tp_members */ \ + 0, /* tp_getset */ \ + &base, /* tp_base */ \ + 0, /* tp_dict */ \ + 0, /* tp_descr_get */ \ + 0, /* tp_descr_set */ \ + 0, /* tp_dictoffset */ \ + 0, /* tp_init */ \ + 0 /* tp_alloc */ \ + }; \ +\ +void \ +gdbpy_initialize_##name##_event (void) \ +{ \ + gdbpy_initialize_event_generic (&name##_event_object_type, \ + py_name); \ +} + +typedef struct +{ + PyObject_HEAD + + PyObject *dict; +} event_object; + +extern int emit_continue_event (ptid_t ptid); +extern int emit_exited_event (const LONGEST *exit_code); + +extern int evpy_emit_event (PyObject *event, + eventregistry_object *registry); + +extern PyObject *create_event_object (PyTypeObject *py_type); +extern PyObject *create_thread_event_object (PyTypeObject *py_type); + +extern void evpy_dealloc (PyObject *self); +extern int evpy_add_attribute (PyObject *event, + char *name, PyObject *attr); +int gdbpy_initialize_event_generic (PyTypeObject *type, char *name); + + +#endif /* GDB_PY_EVENT_H */ diff --git a/contrib/gdb-7/gdb/python/py-events.h b/contrib/gdb-7/gdb/python/py-events.h new file mode 100644 index 0000000000..6d4dae57c0 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-events.h @@ -0,0 +1,59 @@ +/* Python interface to inferior events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PY_EVENTS_H +#define GDB_PY_EVENTS_H + +#include "defs.h" +#include "command.h" +#include "python-internal.h" +#include "inferior.h" + +extern PyTypeObject thread_event_object_type; + +/* Stores a list of objects to be notified when the event for which this + registry tracks occurs. */ + +typedef struct +{ + PyObject_HEAD + + PyObject *callbacks; +} eventregistry_object; + +/* Struct holding references to event registries both in python and c. + This is meant to be a singleton. */ + +typedef struct +{ + eventregistry_object *stop; + eventregistry_object *cont; + eventregistry_object *exited; + + PyObject *module; + +} events_object; + +/* Python events singleton. */ +events_object gdb_py_events; + +extern eventregistry_object *create_eventregistry_object (void); +extern int evregpy_no_listeners_p (eventregistry_object *registry); + +#endif /* GDB_PY_EVENTS_H */ diff --git a/contrib/gdb-7/gdb/python/py-evtregistry.c b/contrib/gdb-7/gdb/python/py-evtregistry.c new file mode 100644 index 0000000000..e1b4346c6b --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-evtregistry.c @@ -0,0 +1,170 @@ +/* Python interface to inferior thread event registries. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "command.h" +#include "py-events.h" + +static PyTypeObject eventregistry_object_type; + +/* Implementation of EventRegistry.connect () -> NULL. + Add FUNCTION to the list of listeners. */ + +static PyObject * +evregpy_connect (PyObject *self, PyObject *function) +{ + PyObject *func; + PyObject *callback_list = (((eventregistry_object *) self)->callbacks); + + if (!PyArg_ParseTuple (function, "O", &func)) + return NULL; + + if (!PyCallable_Check (func)) + { + PyErr_SetString (PyExc_RuntimeError, "Function is not callable"); + return NULL; + } + + if (PyList_Append (callback_list, func) < 0) + return NULL; + + Py_RETURN_NONE; +} + +/* Implementation of EventRegistry.disconnect () -> NULL. + Remove FUNCTION from the list of listeners. */ + +static PyObject * +evregpy_disconnect (PyObject *self, PyObject *function) +{ + PyObject *func; + int index; + PyObject *callback_list = (((eventregistry_object *) self)->callbacks); + + if (!PyArg_ParseTuple (function, "O", &func)) + return NULL; + + index = PySequence_Index (callback_list, func); + if (index < 0) + Py_RETURN_NONE; + + if (PySequence_DelItem (callback_list, index) < 0) + return NULL; + + Py_RETURN_NONE; +} + +/* Create a new event registry. This function uses PyObject_New + and therefore returns a new reference that callers must handle. */ + +eventregistry_object * +create_eventregistry_object (void) +{ + eventregistry_object *eventregistry_obj; + + eventregistry_obj = PyObject_New (eventregistry_object, + &eventregistry_object_type); + + if (!eventregistry_obj) + return NULL; + + eventregistry_obj->callbacks = PyList_New (0); + if (!eventregistry_obj->callbacks) + return NULL; + + return eventregistry_obj; +} + +static void +evregpy_dealloc (PyObject *self) +{ + Py_XDECREF (((eventregistry_object *) self)->callbacks); + self->ob_type->tp_free (self); +} + +/* Initialize the Python event registry code. */ + +void +gdbpy_initialize_eventregistry (void) +{ + if (PyType_Ready (&eventregistry_object_type) < 0) + return; + + Py_INCREF (&eventregistry_object_type); + PyModule_AddObject (gdb_module, "EventRegistry", + (PyObject *) &eventregistry_object_type); +} + +/* Retern the number of listeners currently connected to this + registry. */ + +int +evregpy_no_listeners_p (eventregistry_object *registry) +{ + return PyList_Size (registry->callbacks) == 0; +} + +static PyMethodDef eventregistry_object_methods[] = +{ + { "connect", evregpy_connect, METH_VARARGS, "Add function" }, + { "disconnect", evregpy_disconnect, METH_VARARGS, "Remove function" }, + { NULL } /* Sentinel. */ +}; + +static PyTypeObject eventregistry_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "gdb.EventRegistry", /* tp_name */ + sizeof (eventregistry_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + evregpy_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "GDB event registry object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + eventregistry_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0 /* tp_alloc */ +}; diff --git a/contrib/gdb-7/gdb/python/py-evts.c b/contrib/gdb-7/gdb/python/py-evts.c new file mode 100644 index 0000000000..50c05f3ad7 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-evts.c @@ -0,0 +1,71 @@ +/* Python interface to inferior events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-events.h" + +/* Initialize python events. */ + +static int +add_new_registry (eventregistry_object **registryp, char *name) +{ + *registryp = create_eventregistry_object (); + + if (*registryp == NULL) + goto fail; + + if (PyModule_AddObject (gdb_py_events.module, + name, + (PyObject *)(*registryp)) < 0) + goto fail; + + return 0; + + fail: + Py_XDECREF (*registryp); + return -1; +} + +void +gdbpy_initialize_py_events (void) +{ + gdb_py_events.module = Py_InitModule ("events", NULL); + + if (!gdb_py_events.module) + goto fail; + + if (add_new_registry (&gdb_py_events.stop, "stop") < 0) + goto fail; + + if (add_new_registry (&gdb_py_events.cont, "cont") < 0) + goto fail; + + if (add_new_registry (&gdb_py_events.exited, "exited") < 0) + goto fail; + + Py_INCREF (gdb_py_events.module); + if (PyModule_AddObject (gdb_module, + "events", + (PyObject *) gdb_py_events.module) < 0) + goto fail; + + return; + + fail: + gdbpy_print_stack (); +} diff --git a/contrib/gdb-7/gdb/python/py-exitedevent.c b/contrib/gdb-7/gdb/python/py-exitedevent.c new file mode 100644 index 0000000000..08150e567f --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-exitedevent.c @@ -0,0 +1,72 @@ +/* Python interface to inferior exit events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-event.h" + +static PyTypeObject exited_event_object_type; + +static PyObject * +create_exited_event_object (const LONGEST *exit_code) +{ + PyObject *exited_event; + + exited_event = create_event_object (&exited_event_object_type); + + if (!exited_event) + goto fail; + + if (exit_code + && evpy_add_attribute (exited_event, + "exit_code", + PyLong_FromLongLong (*exit_code)) < 0) + goto fail; + + return exited_event; + + fail: + Py_XDECREF (exited_event); + return NULL; +} + +/* Callback that is used when an exit event occurs. This function + will create a new Python exited event object. */ + +int +emit_exited_event (const LONGEST *exit_code) +{ + PyObject *event; + + if (evregpy_no_listeners_p (gdb_py_events.exited)) + return 0; + + event = create_exited_event_object (exit_code); + + if (event) + return evpy_emit_event (event, gdb_py_events.exited); + + return -1; +} + + +GDBPY_NEW_EVENT_TYPE (exited, + "gdb.ExitedEvent", + "ExitedEvent", + "GDB exited event object", + event_object_type, + static); diff --git a/contrib/gdb-7/gdb/python/py-frame.c b/contrib/gdb-7/gdb/python/py-frame.c new file mode 100644 index 0000000000..d7128a9dca --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-frame.c @@ -0,0 +1,706 @@ +/* Python interface to stack frames + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "charset.h" +#include "block.h" +#include "frame.h" +#include "exceptions.h" +#include "symtab.h" +#include "stack.h" +#include "value.h" +#include "python-internal.h" +#include "symfile.h" +#include "objfiles.h" + +typedef struct { + PyObject_HEAD + struct frame_id frame_id; + struct gdbarch *gdbarch; + + /* Marks that the FRAME_ID member actually holds the ID of the frame next + to this, and not this frames' ID itself. This is a hack to permit Python + frame objects which represent invalid frames (i.e., the last frame_info + in a corrupt stack). The problem arises from the fact that this code + relies on FRAME_ID to uniquely identify a frame, which is not always true + for the last "frame" in a corrupt stack (it can have a null ID, or the same + ID as the previous frame). Whenever get_prev_frame returns NULL, we + record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */ + int frame_id_is_next; +} frame_object; + +/* Require a valid frame. This must be called inside a TRY_CATCH, or + another context in which a gdb exception is allowed. */ +#define FRAPY_REQUIRE_VALID(frame_obj, frame) \ + do { \ + frame = frame_object_to_frame_info (frame_obj); \ + if (frame == NULL) \ + error (_("Frame is invalid.")); \ + } while (0) + +static PyTypeObject frame_object_type; + +/* Returns the frame_info object corresponding to the given Python Frame + object. If the frame doesn't exist anymore (the frame id doesn't + correspond to any frame in the inferior), returns NULL. */ + +static struct frame_info * +frame_object_to_frame_info (frame_object *frame_obj) +{ + struct frame_info *frame; + + frame = frame_find_by_id (frame_obj->frame_id); + if (frame == NULL) + return NULL; + + if (frame_obj->frame_id_is_next) + frame = get_prev_frame (frame); + + return frame; +} + +/* Called by the Python interpreter to obtain string representation + of the object. */ + +static PyObject * +frapy_str (PyObject *self) +{ + char *s; + PyObject *result; + struct ui_file *strfile; + + strfile = mem_fileopen (); + fprint_frame_id (strfile, ((frame_object *) self)->frame_id); + s = ui_file_xstrdup (strfile, NULL); + result = PyString_FromString (s); + xfree (s); + + return result; +} + +/* Implementation of gdb.Frame.is_valid (self) -> Boolean. + Returns True if the frame corresponding to the frame_id of this + object still exists in the inferior. */ + +static PyObject * +frapy_is_valid (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + + frame = frame_object_to_frame_info ((frame_object *) self); + if (frame == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Implementation of gdb.Frame.name (self) -> String. + Returns the name of the function corresponding to this frame. */ + +static PyObject * +frapy_name (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + char *name; + enum language lang; + PyObject *result; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + find_frame_funname (frame, &name, &lang, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (name) + result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL); + else + { + result = Py_None; + Py_INCREF (Py_None); + } + + return result; +} + +/* Implementation of gdb.Frame.type (self) -> Integer. + Returns the frame type, namely one of the gdb.*_FRAME constants. */ + +static PyObject * +frapy_type (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + type = get_frame_type (frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyInt_FromLong (type); +} + +/* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer. + Returns one of the gdb.FRAME_UNWIND_* constants. */ + +static PyObject * +frapy_unwind_stop_reason (PyObject *self, PyObject *args) +{ + struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + enum unwind_stop_reason stop_reason; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + stop_reason = get_frame_unwind_stop_reason (frame); + + return PyInt_FromLong (stop_reason); +} + +/* Implementation of gdb.Frame.pc (self) -> Long. + Returns the frame's resume address. */ + +static PyObject * +frapy_pc (PyObject *self, PyObject *args) +{ + CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */ + struct frame_info *frame; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + pc = get_frame_pc (frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return gdb_py_long_from_ulongest (pc); +} + +/* Implementation of gdb.Frame.block (self) -> gdb.Block. + Returns the frame's code block. */ + +static PyObject * +frapy_block (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + struct block *block = NULL, *fn_block; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + block = get_frame_block (frame, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + for (fn_block = block; + fn_block != NULL && BLOCK_FUNCTION (fn_block) == NULL; + fn_block = BLOCK_SUPERBLOCK (fn_block)) + ; + + if (block == NULL || fn_block == NULL || BLOCK_FUNCTION (fn_block) == NULL) + { + PyErr_SetString (PyExc_RuntimeError, + _("Cannot locate object file for block.")); + return NULL; + } + + if (block) + { + struct symtab *symt; + + symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block)); + return block_to_block_object (block, symt->objfile); + } + + Py_RETURN_NONE; +} + + +/* Implementation of gdb.Frame.function (self) -> gdb.Symbol. + Returns the symbol for the function corresponding to this frame. */ + +static PyObject * +frapy_function (PyObject *self, PyObject *args) +{ + struct symbol *sym = NULL; + struct frame_info *frame; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + sym = find_pc_function (get_frame_address_in_block (frame)); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (sym) + return symbol_to_symbol_object (sym); + + Py_RETURN_NONE; +} + +/* Convert a frame_info struct to a Python Frame object. + Sets a Python exception and returns NULL on error. */ + +PyObject * +frame_info_to_frame_object (struct frame_info *frame) +{ + frame_object *frame_obj; + + frame_obj = PyObject_New (frame_object, &frame_object_type); + if (frame_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, + _("Could not allocate frame object.")); + return NULL; + } + + /* Try to get the previous frame, to determine if this is the last frame + in a corrupt stack. If so, we need to store the frame_id of the next + frame and not of this one (which is possibly invalid). */ + if (get_prev_frame (frame) == NULL + && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON + && get_next_frame (frame) != NULL) + { + frame_obj->frame_id = get_frame_id (get_next_frame (frame)); + frame_obj->frame_id_is_next = 1; + } + else + { + frame_obj->frame_id = get_frame_id (frame); + frame_obj->frame_id_is_next = 0; + } + + frame_obj->gdbarch = get_frame_arch (frame); + + return (PyObject *) frame_obj; +} + +/* Implementation of gdb.Frame.older (self) -> gdb.Frame. + Returns the frame immediately older (outer) to this frame, or None if + there isn't one. */ + +static PyObject * +frapy_older (PyObject *self, PyObject *args) +{ + struct frame_info *frame, *prev; + volatile struct gdb_exception except; + PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */ + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + prev = get_prev_frame (frame); + if (prev) + prev_obj = (PyObject *) frame_info_to_frame_object (prev); + else + { + Py_INCREF (Py_None); + prev_obj = Py_None; + } + } + GDB_PY_HANDLE_EXCEPTION (except); + + return prev_obj; +} + +/* Implementation of gdb.Frame.newer (self) -> gdb.Frame. + Returns the frame immediately newer (inner) to this frame, or None if + there isn't one. */ + +static PyObject * +frapy_newer (PyObject *self, PyObject *args) +{ + struct frame_info *frame, *next; + volatile struct gdb_exception except; + PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */ + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + next = get_next_frame (frame); + if (next) + next_obj = (PyObject *) frame_info_to_frame_object (next); + else + { + Py_INCREF (Py_None); + next_obj = Py_None; + } + } + GDB_PY_HANDLE_EXCEPTION (except); + + return next_obj; +} + +/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line. + Returns the frame's symtab and line. */ + +static PyObject * +frapy_find_sal (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + struct symtab_and_line sal; + volatile struct gdb_exception except; + PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */ + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + find_frame_sal (frame, &sal); + sal_obj = symtab_and_line_to_sal_object (sal); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return sal_obj; +} + +/* Implementation of gdb.Frame.read_var_value (self, variable, + [block]) -> gdb.Value. If the optional block argument is provided + start the search from that block, otherwise search from the frame's + current block (determined by examining the resume address of the + frame). The variable argument must be a string or an instance of a + gdb.Symbol. The block argument must be an instance of gdb.Block. Returns + NULL on error, with a python exception set. */ +static PyObject * +frapy_read_var (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + PyObject *sym_obj, *block_obj = NULL; + struct symbol *var = NULL; /* gcc-4.3.2 false warning. */ + struct value *val = NULL; + volatile struct gdb_exception except; + + if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj)) + return NULL; + + if (PyObject_TypeCheck (sym_obj, &symbol_object_type)) + var = symbol_object_to_symbol (sym_obj); + else if (gdbpy_is_string (sym_obj)) + { + char *var_name; + struct block *block = NULL; + struct cleanup *cleanup; + volatile struct gdb_exception except; + + var_name = python_string_to_target_string (sym_obj); + if (!var_name) + return NULL; + cleanup = make_cleanup (xfree, var_name); + + if (block_obj) + { + block = block_object_to_block (block_obj); + if (!block) + { + PyErr_SetString (PyExc_RuntimeError, + _("Second argument must be block.")); + return NULL; + } + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + if (!block) + block = get_frame_block (frame, NULL); + var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (!var) + { + PyErr_Format (PyExc_ValueError, + _("Variable '%s' not found."), var_name); + do_cleanups (cleanup); + + return NULL; + } + + do_cleanups (cleanup); + } + else + { + PyErr_SetString (PyExc_TypeError, + _("Argument must be a symbol or string.")); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + val = read_var_value (var, frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (!val) + { + PyErr_Format (PyExc_ValueError, + _("Variable cannot be found for symbol '%s'."), + SYMBOL_NATURAL_NAME (var)); + return NULL; + } + + return value_to_value_object (val); +} + +/* Select this frame. */ + +static PyObject * +frapy_select (PyObject *self, PyObject *args) +{ + struct frame_info *fi; + frame_object *frame = (frame_object *) self; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID (frame, fi); + + select_frame (fi); + } + GDB_PY_HANDLE_EXCEPTION (except); + + Py_RETURN_NONE; +} + +/* Implementation of gdb.newest_frame () -> gdb.Frame. + Returns the newest frame object. */ + +PyObject * +gdbpy_newest_frame (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + PyObject *frame_obj = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + frame = get_current_frame (); + frame_obj = frame_info_to_frame_object (frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return frame_obj; +} + +/* Implementation of gdb.selected_frame () -> gdb.Frame. + Returns the selected frame object. */ + +PyObject * +gdbpy_selected_frame (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + PyObject *frame_obj = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + frame = get_selected_frame ("No frame is currently selected."); + frame_obj = frame_info_to_frame_object (frame); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return frame_obj; +} + +/* Implementation of gdb.stop_reason_string (Integer) -> String. + Return a string explaining the unwind stop reason. */ + +PyObject * +gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args) +{ + int reason; + const char *str; + + if (!PyArg_ParseTuple (args, "i", &reason)) + return NULL; + + if (reason < 0 || reason > UNWIND_NO_SAVED_PC) + { + PyErr_SetString (PyExc_ValueError, + _("Invalid frame stop reason.")); + return NULL; + } + + str = frame_stop_reason_string (reason); + return PyUnicode_Decode (str, strlen (str), host_charset (), NULL); +} + +/* Implements the equality comparison for Frame objects. + All other comparison operators will throw a TypeError Python exception, + as they aren't valid for frames. */ + +static PyObject * +frapy_richcompare (PyObject *self, PyObject *other, int op) +{ + int result; + + if (!PyObject_TypeCheck (other, &frame_object_type) + || (op != Py_EQ && op != Py_NE)) + { + Py_INCREF (Py_NotImplemented); + return Py_NotImplemented; + } + + if (frame_id_eq (((frame_object *) self)->frame_id, + ((frame_object *) other)->frame_id)) + result = Py_EQ; + else + result = Py_NE; + + if (op == result) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +/* Sets up the Frame API in the gdb module. */ + +void +gdbpy_initialize_frames (void) +{ + if (PyType_Ready (&frame_object_type) < 0) + return; + + /* Note: These would probably be best exposed as class attributes of + Frame, but I don't know how to do it except by messing with the + type's dictionary. That seems too messy. */ + PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME); + PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME); + PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME); + PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME); + PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME); + PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID); + PyModule_AddIntConstant (gdb_module, + "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC); + + Py_INCREF (&frame_object_type); + PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type); +} + + + +static PyMethodDef frame_object_methods[] = { + { "is_valid", frapy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this frame is valid, false if not." }, + { "name", frapy_name, METH_NOARGS, + "name () -> String.\n\ +Return the function name of the frame, or None if it can't be determined." }, + { "type", frapy_type, METH_NOARGS, + "type () -> Integer.\n\ +Return the type of the frame." }, + { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS, + "unwind_stop_reason () -> Integer.\n\ +Return the reason why it's not possible to find frames older than this." }, + { "pc", frapy_pc, METH_NOARGS, + "pc () -> Long.\n\ +Return the frame's resume address." }, + { "block", frapy_block, METH_NOARGS, + "block () -> gdb.Block.\n\ +Return the frame's code block." }, + { "function", frapy_function, METH_NOARGS, + "function () -> gdb.Symbol.\n\ +Returns the symbol for the function corresponding to this frame." }, + { "older", frapy_older, METH_NOARGS, + "older () -> gdb.Frame.\n\ +Return the frame that called this frame." }, + { "newer", frapy_newer, METH_NOARGS, + "newer () -> gdb.Frame.\n\ +Return the frame called by this frame." }, + { "find_sal", frapy_find_sal, METH_NOARGS, + "find_sal () -> gdb.Symtab_and_line.\n\ +Return the frame's symtab and line." }, + { "read_var", frapy_read_var, METH_VARARGS, + "read_var (variable) -> gdb.Value.\n\ +Return the value of the variable in this frame." }, + { "select", frapy_select, METH_NOARGS, + "Select this frame as the user's current frame." }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject frame_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "gdb.Frame", /* tp_name */ + sizeof (frame_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + frapy_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "GDB frame object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + frapy_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + frame_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-function.c b/contrib/gdb-7/gdb/python/py-function.c new file mode 100644 index 0000000000..0c3e6f2a46 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-function.c @@ -0,0 +1,234 @@ +/* Convenience functions implemented in Python. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbcmd.h" +#include "cli/cli-decode.h" +#include "completer.h" +#include "expression.h" +#include "language.h" + +static PyTypeObject fnpy_object_type; + + + +static PyObject * +convert_values_to_python (int argc, struct value **argv) +{ + int i; + PyObject *result = PyTuple_New (argc); + + for (i = 0; i < argc; ++i) + { + PyObject *elt = value_to_value_object (argv[i]); + if (! elt) + { + Py_DECREF (result); + error (_("Could not convert value to Python object.")); + } + PyTuple_SetItem (result, i, elt); + } + return result; +} + +/* Call a Python function object's invoke method. */ + +static struct value * +fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language, + void *cookie, int argc, struct value **argv) +{ + struct value *value = NULL; + PyObject *result, *callable, *args; + struct cleanup *cleanup; + + cleanup = ensure_python_env (gdbarch, language); + + args = convert_values_to_python (argc, argv); + + callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); + if (! callable) + { + Py_DECREF (args); + error (_("No method named 'invoke' in object.")); + } + + result = PyObject_Call (callable, args, NULL); + Py_DECREF (callable); + Py_DECREF (args); + + if (!result) + { + PyObject *ptype, *pvalue, *ptraceback; + char *msg; + + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + + /* Try to fetch an error message contained within ptype, pvalue. + When fetching the error message we need to make our own copy, + we no longer own ptype, pvalue after the call to PyErr_Restore. */ + + msg = gdbpy_exception_to_string (ptype, pvalue); + make_cleanup (xfree, msg); + + if (msg == NULL) + { + /* An error occurred computing the string representation of the + error message. This is rare, but we should inform the user. */ + + printf_filtered (_("An error occurred in a Python " + "convenience function\n" + "and then another occurred computing the " + "error message.\n")); + gdbpy_print_stack (); + } + + /* Don't print the stack for gdb.GdbError exceptions. + It is generally used to flag user errors. + + We also don't want to print "Error occurred in Python command" + for user errors. However, a missing message for gdb.GdbError + exceptions is arguably a bug, so we flag it as such. */ + + if (!PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc) + || msg == NULL || *msg == '\0') + { + PyErr_Restore (ptype, pvalue, ptraceback); + gdbpy_print_stack (); + if (msg != NULL && *msg != '\0') + error (_("Error occurred in Python convenience function: %s"), + msg); + else + error (_("Error occurred in Python convenience function.")); + } + else + { + Py_XDECREF (ptype); + Py_XDECREF (pvalue); + Py_XDECREF (ptraceback); + error ("%s", msg); + } + } + + value = convert_value_from_python (result); + if (value == NULL) + { + Py_DECREF (result); + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + + Py_DECREF (result); + do_cleanups (cleanup); + + return value; +} + +/* Initializer for a Function object. It takes one argument, the name + of the function. */ + +static int +fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) +{ + char *name, *docstring = NULL; + + if (! PyArg_ParseTuple (args, "s", &name)) + return -1; + Py_INCREF (self); + + if (PyObject_HasAttrString (self, "__doc__")) + { + PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__"); + if (ds_obj && gdbpy_is_string (ds_obj)) + { + docstring = python_string_to_host_string (ds_obj); + if (docstring == NULL) + { + Py_DECREF (self); + return -1; + } + } + } + if (! docstring) + docstring = xstrdup (_("This function is not documented.")); + + add_internal_function (name, docstring, fnpy_call, self); + return 0; +} + +/* Initialize internal function support. */ + +void +gdbpy_initialize_functions (void) +{ + if (PyType_Ready (&fnpy_object_type) < 0) + return; + + Py_INCREF (&fnpy_object_type); + PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type); +} + + + +static PyTypeObject fnpy_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Function", /*tp_name*/ + sizeof (PyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB function object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + fnpy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-inferior.c b/contrib/gdb-7/gdb/python/py-inferior.c new file mode 100644 index 0000000000..da0a4b6815 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-inferior.c @@ -0,0 +1,807 @@ +/* Python interface to inferiors. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "exceptions.h" +#include "gdbcore.h" +#include "gdbthread.h" +#include "inferior.h" +#include "observer.h" +#include "python-internal.h" +#include "arch-utils.h" +#include "language.h" +#include "gdb_signals.h" +#include "py-event.h" +#include "py-stopevent.h" + +struct threadlist_entry { + thread_object *thread_obj; + struct threadlist_entry *next; +}; + +typedef struct +{ + PyObject_HEAD + + /* The inferior we represent. */ + struct inferior *inferior; + + /* thread_object instances under this inferior. This list owns a + reference to each object it contains. */ + struct threadlist_entry *threads; + + /* Number of threads in the list. */ + int nthreads; +} inferior_object; + +static PyTypeObject inferior_object_type; + +static const struct inferior_data *infpy_inf_data_key; + +typedef struct { + PyObject_HEAD + void *buffer; + + /* These are kept just for mbpy_str. */ + CORE_ADDR addr; + CORE_ADDR length; +} membuf_object; + +static PyTypeObject membuf_object_type; + +/* Require that INFERIOR be a valid inferior ID. */ +#define INFPY_REQUIRE_VALID(Inferior) \ + do { \ + if (!Inferior->inferior) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Inferior no longer exists.")); \ + return NULL; \ + } \ + } while (0) + +static void +python_on_normal_stop (struct bpstats *bs, int print_frame) +{ + struct cleanup *cleanup; + enum target_signal stop_signal; + + if (!find_thread_ptid (inferior_ptid)) + return; + + stop_signal = inferior_thread ()->suspend.stop_signal; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (emit_stop_event (bs, stop_signal) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +static void +python_on_resume (ptid_t ptid) +{ + struct cleanup *cleanup; + + cleanup = ensure_python_env (target_gdbarch, current_language); + + if (emit_continue_event (ptid) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +static void +python_inferior_exit (struct inferior *inf) +{ + struct cleanup *cleanup; + const LONGEST *exit_code = NULL; + + cleanup = ensure_python_env (target_gdbarch, current_language); + + if (inf->has_exit_code) + exit_code = &inf->exit_code; + + if (emit_exited_event (exit_code) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +/* Return a borrowed reference to the Python object of type Inferior + representing INFERIOR. If the object has already been created, + return it, otherwise, create it. Return NULL on failure. */ +PyObject * +inferior_to_inferior_object (struct inferior *inferior) +{ + inferior_object *inf_obj; + + inf_obj = inferior_data (inferior, infpy_inf_data_key); + if (!inf_obj) + { + struct cleanup *cleanup; + cleanup = ensure_python_env (python_gdbarch, python_language); + + inf_obj = PyObject_New (inferior_object, &inferior_object_type); + if (!inf_obj) + { + do_cleanups (cleanup); + return NULL; + } + + inf_obj->inferior = inferior; + inf_obj->threads = NULL; + inf_obj->nthreads = 0; + + set_inferior_data (inferior, infpy_inf_data_key, inf_obj); + + do_cleanups (cleanup); + } + + return (PyObject *) inf_obj; +} + +/* Finds the Python Inferior object for the given PID. Returns a + borrowed reference, or NULL if PID does not match any inferior + object. */ + +PyObject * +find_inferior_object (int pid) +{ + struct inflist_entry *p; + struct inferior *inf = find_inferior_pid (pid); + + if (inf) + return inferior_to_inferior_object (inf); + + return NULL; +} + +thread_object * +find_thread_object (ptid_t ptid) +{ + int pid; + struct threadlist_entry *thread; + PyObject *inf_obj; + + pid = PIDGET (ptid); + if (pid == 0) + return NULL; + + inf_obj = find_inferior_object (pid); + + if (inf_obj) + for (thread = ((inferior_object *)inf_obj)->threads; thread; + thread = thread->next) + if (ptid_equal (thread->thread_obj->thread->ptid, ptid)) + return thread->thread_obj; + + return NULL; +} + +static void +add_thread_object (struct thread_info *tp) +{ + struct cleanup *cleanup; + thread_object *thread_obj; + inferior_object *inf_obj; + struct threadlist_entry *entry; + + cleanup = ensure_python_env (python_gdbarch, python_language); + + thread_obj = create_thread_object (tp); + if (!thread_obj) + { + gdbpy_print_stack (); + do_cleanups (cleanup); + return; + } + + inf_obj = (inferior_object *) thread_obj->inf_obj; + + entry = xmalloc (sizeof (struct threadlist_entry)); + entry->thread_obj = thread_obj; + entry->next = inf_obj->threads; + + inf_obj->threads = entry; + inf_obj->nthreads++; + + do_cleanups (cleanup); +} + +static void +delete_thread_object (struct thread_info *tp, int ignore) +{ + struct cleanup *cleanup; + inferior_object *inf_obj; + thread_object *thread_obj; + struct threadlist_entry **entry, *tmp; + + inf_obj = (inferior_object *) find_inferior_object (PIDGET(tp->ptid)); + if (!inf_obj) + return; + + /* Find thread entry in its inferior's thread_list. */ + for (entry = &inf_obj->threads; *entry != NULL; entry = + &(*entry)->next) + if ((*entry)->thread_obj->thread == tp) + break; + + if (!*entry) + return; + + cleanup = ensure_python_env (python_gdbarch, python_language); + + tmp = *entry; + tmp->thread_obj->thread = NULL; + + *entry = (*entry)->next; + inf_obj->nthreads--; + + Py_DECREF (tmp->thread_obj); + xfree (tmp); + + do_cleanups (cleanup); +} + +static PyObject * +infpy_threads (PyObject *self, PyObject *args) +{ + int i; + struct threadlist_entry *entry; + inferior_object *inf_obj = (inferior_object *) self; + PyObject *tuple; + + INFPY_REQUIRE_VALID (inf_obj); + + tuple = PyTuple_New (inf_obj->nthreads); + if (!tuple) + return NULL; + + for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads; + i++, entry = entry->next) + { + Py_INCREF (entry->thread_obj); + PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->thread_obj); + } + + return tuple; +} + +static PyObject * +infpy_get_num (PyObject *self, void *closure) +{ + inferior_object *inf = (inferior_object *) self; + + INFPY_REQUIRE_VALID (inf); + + return PyLong_FromLong (inf->inferior->num); +} + +static PyObject * +infpy_get_pid (PyObject *self, void *closure) +{ + inferior_object *inf = (inferior_object *) self; + + INFPY_REQUIRE_VALID (inf); + + return PyLong_FromLong (inf->inferior->pid); +} + +static PyObject * +infpy_get_was_attached (PyObject *self, void *closure) +{ + inferior_object *inf = (inferior_object *) self; + + INFPY_REQUIRE_VALID (inf); + if (inf->inferior->attach_flag) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +static int +build_inferior_list (struct inferior *inf, void *arg) +{ + PyObject *list = arg; + PyObject *inferior = inferior_to_inferior_object (inf); + + if (PyList_Append (list, inferior)) + return 1; + + return 0; +} + +/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...). + Returns a tuple of all inferiors. */ +PyObject * +gdbpy_inferiors (PyObject *unused, PyObject *unused2) +{ + int i = 0; + PyObject *list, *inferior; + struct inferior *inf; + + list = PyList_New (0); + if (!list) + return NULL; + + if (iterate_over_inferiors (build_inferior_list, list)) + { + Py_DECREF (list); + return NULL; + } + + return PyList_AsTuple (list); +} + +/* Membuf and memory manipulation. */ + +/* Implementation of gdb.read_memory (address, length). + Returns a Python buffer object with LENGTH bytes of the inferior's + memory at ADDRESS. Both arguments are integers. Returns NULL on error, + with a python exception set. */ +static PyObject * +infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) +{ + int error = 0; + CORE_ADDR addr, length; + void *buffer = NULL; + membuf_object *membuf_obj; + PyObject *addr_obj, *length_obj; + struct cleanup *cleanups; + volatile struct gdb_exception except; + static char *keywords[] = { "address", "length", NULL }; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, + &addr_obj, &length_obj)) + return NULL; + + cleanups = make_cleanup (null_cleanup, NULL); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (!get_addr_from_python (addr_obj, &addr) + || !get_addr_from_python (length_obj, &length)) + { + error = 1; + break; + } + + buffer = xmalloc (length); + make_cleanup (xfree, buffer); + + read_memory (addr, buffer, length); + } + if (except.reason < 0) + { + do_cleanups (cleanups); + GDB_PY_HANDLE_EXCEPTION (except); + } + + if (error) + { + do_cleanups (cleanups); + return NULL; + } + + membuf_obj = PyObject_New (membuf_object, &membuf_object_type); + if (membuf_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, + _("Could not allocate memory buffer object.")); + do_cleanups (cleanups); + return NULL; + } + + discard_cleanups (cleanups); + + membuf_obj->buffer = buffer; + membuf_obj->addr = addr; + membuf_obj->length = length; + + return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0, + Py_END_OF_BUFFER); +} + +/* Implementation of gdb.write_memory (address, buffer [, length]). + Writes the contents of BUFFER (a Python object supporting the read + buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH + bytes from BUFFER, or its entire contents if the argument is not + provided. The function returns nothing. Returns NULL on error, with + a python exception set. */ +static PyObject * +infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) +{ + int buf_len, error = 0; + const char *buffer; + CORE_ADDR addr, length; + PyObject *addr_obj, *length_obj = NULL; + volatile struct gdb_exception except; + static char *keywords[] = { "address", "buffer", "length", NULL }; + + + if (! PyArg_ParseTupleAndKeywords (args, kw, "Os#|O", keywords, + &addr_obj, &buffer, &buf_len, + &length_obj)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (!get_addr_from_python (addr_obj, &addr)) + { + error = 1; + break; + } + + if (!length_obj) + length = buf_len; + else if (!get_addr_from_python (length_obj, &length)) + { + error = 1; + break; + } + write_memory (addr, buffer, length); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (error) + return NULL; + + Py_RETURN_NONE; +} + +/* Destructor of Membuf objects. */ +static void +mbpy_dealloc (PyObject *self) +{ + xfree (((membuf_object *) self)->buffer); + self->ob_type->tp_free (self); +} + +/* Return a description of the Membuf object. */ +static PyObject * +mbpy_str (PyObject *self) +{ + membuf_object *membuf_obj = (membuf_object *) self; + + return PyString_FromFormat (_("Memory buffer for address %s, \ +which is %s bytes long."), + paddress (python_gdbarch, membuf_obj->addr), + pulongest (membuf_obj->length)); +} + +static Py_ssize_t +get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) +{ + membuf_object *membuf_obj = (membuf_object *) self; + + if (segment) + { + PyErr_SetString (PyExc_SystemError, + _("The memory buffer supports only one segment.")); + return -1; + } + + *ptrptr = membuf_obj->buffer; + + return membuf_obj->length; +} + +static Py_ssize_t +get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) +{ + return get_read_buffer (self, segment, ptrptr); +} + +static Py_ssize_t +get_seg_count (PyObject *self, Py_ssize_t *lenp) +{ + if (lenp) + *lenp = ((membuf_object *) self)->length; + + return 1; +} + +static Py_ssize_t +get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr) +{ + void *ptr = NULL; + Py_ssize_t ret; + + ret = get_read_buffer (self, segment, &ptr); + *ptrptr = (char *) ptr; + + return ret; +} + +/* Implementation of + gdb.search_memory (address, length, pattern). ADDRESS is the + address to start the search. LENGTH specifies the scope of the + search from ADDRESS. PATTERN is the pattern to search for (and + must be a Python object supporting the buffer protocol). + Returns a Python Long object holding the address where the pattern + was located, or if the pattern was not found, returns None. Returns NULL + on error, with a python exception set. */ +static PyObject * +infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) +{ + CORE_ADDR start_addr, length; + static char *keywords[] = { "address", "length", "pattern", NULL }; + PyObject *pattern, *start_addr_obj, *length_obj; + volatile struct gdb_exception except; + Py_ssize_t pattern_size; + const void *buffer; + CORE_ADDR found_addr; + int found = 0; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO", keywords, + &start_addr_obj, &length_obj, + &pattern)) + return NULL; + + if (get_addr_from_python (start_addr_obj, &start_addr) + && get_addr_from_python (length_obj, &length)) + { + if (!length) + { + PyErr_SetString (PyExc_ValueError, + _("Search range is empty.")); + return NULL; + } + /* Watch for overflows. */ + else if (length > CORE_ADDR_MAX + || (start_addr + length - 1) < start_addr) + { + PyErr_SetString (PyExc_ValueError, + _("The search range is too large.")); + + return NULL; + } + } + else + return NULL; + + if (!PyObject_CheckReadBuffer (pattern)) + { + PyErr_SetString (PyExc_RuntimeError, + _("The pattern is not a Python buffer.")); + + return NULL; + } + + if (PyObject_AsReadBuffer (pattern, &buffer, &pattern_size) == -1) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + found = target_search_memory (start_addr, length, + buffer, pattern_size, + &found_addr); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (found) + return PyLong_FromLong (found_addr); + else + Py_RETURN_NONE; +} + +/* Implementation of gdb.Inferior.is_valid (self) -> Boolean. + Returns True if this inferior object still exists in GDB. */ + +static PyObject * +infpy_is_valid (PyObject *self, PyObject *args) +{ + inferior_object *inf = (inferior_object *) self; + + if (! inf->inferior) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + + +/* Clear the INFERIOR pointer in an Inferior object and clear the + thread list. */ +static void +py_free_inferior (struct inferior *inf, void *datum) +{ + + struct cleanup *cleanup; + inferior_object *inf_obj = datum; + struct threadlist_entry *th_entry, *th_tmp; + + cleanup = ensure_python_env (python_gdbarch, python_language); + + inf_obj->inferior = NULL; + + /* Deallocate threads list. */ + for (th_entry = inf_obj->threads; th_entry != NULL;) + { + Py_DECREF (th_entry->thread_obj); + + th_tmp = th_entry; + th_entry = th_entry->next; + xfree (th_tmp); + } + + inf_obj->nthreads = 0; + + Py_DECREF ((PyObject *) inf_obj); + do_cleanups (cleanup); +} + +void +gdbpy_initialize_inferior (void) +{ + if (PyType_Ready (&inferior_object_type) < 0) + return; + + Py_INCREF (&inferior_object_type); + PyModule_AddObject (gdb_module, "Inferior", + (PyObject *) &inferior_object_type); + + infpy_inf_data_key = + register_inferior_data_with_cleanup (py_free_inferior); + + observer_attach_new_thread (add_thread_object); + observer_attach_thread_exit (delete_thread_object); + observer_attach_normal_stop (python_on_normal_stop); + observer_attach_target_resumed (python_on_resume); + observer_attach_inferior_exit (python_inferior_exit); + + if (PyType_Ready (&membuf_object_type) < 0) + return; + + Py_INCREF (&membuf_object_type); + PyModule_AddObject (gdb_module, "Membuf", (PyObject *) + &membuf_object_type); +} + +static PyGetSetDef inferior_object_getset[] = +{ + { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL }, + { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.", + NULL }, + { "was_attached", infpy_get_was_attached, NULL, + "True if the inferior was created using 'attach'.", NULL }, + { NULL } +}; + +static PyMethodDef inferior_object_methods[] = +{ + { "is_valid", infpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this inferior is valid, false if not." }, + { "threads", infpy_threads, METH_NOARGS, + "Return all the threads of this inferior." }, + { "read_memory", (PyCFunction) infpy_read_memory, + METH_VARARGS | METH_KEYWORDS, + "read_memory (address, length) -> buffer\n\ +Return a buffer object for reading from the inferior's memory." }, + { "write_memory", (PyCFunction) infpy_write_memory, + METH_VARARGS | METH_KEYWORDS, + "write_memory (address, buffer [, length])\n\ +Write the given buffer object to the inferior's memory." }, + { "search_memory", (PyCFunction) infpy_search_memory, + METH_VARARGS | METH_KEYWORDS, + "search_memory (address, length, pattern) -> long\n\ +Return a long with the address of a match, or None." }, + { NULL } +}; + +static PyTypeObject inferior_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "gdb.Inferior", /* tp_name */ + sizeof (inferior_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_flags */ + "GDB inferior object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + inferior_object_methods, /* tp_methods */ + 0, /* tp_members */ + inferior_object_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0 /* tp_alloc */ +}; + +/* Python doesn't provide a decent way to get compatibility here. */ +#if HAVE_LIBPYTHON2_4 +#define CHARBUFFERPROC_NAME getcharbufferproc +#else +#define CHARBUFFERPROC_NAME charbufferproc +#endif + +static PyBufferProcs buffer_procs = { + get_read_buffer, + get_write_buffer, + get_seg_count, + /* The cast here works around a difference between Python 2.4 and + Python 2.5. */ + (CHARBUFFERPROC_NAME) get_char_buffer +}; + +static PyTypeObject membuf_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Membuf", /*tp_name*/ + sizeof (membuf_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + mbpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + mbpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + &buffer_procs, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB memory buffer object", /*tp_doc*/ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-infthread.c b/contrib/gdb-7/gdb/python/py-infthread.c new file mode 100644 index 0000000000..b37c53ca83 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-infthread.c @@ -0,0 +1,344 @@ +/* Python interface to inferior threads. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "exceptions.h" +#include "gdbthread.h" +#include "inferior.h" +#include "python-internal.h" + +static PyTypeObject thread_object_type; + +/* Require that INFERIOR be a valid inferior ID. */ +#define THPY_REQUIRE_VALID(Thread) \ + do { \ + if (!Thread->thread) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Thread no longer exists.")); \ + return NULL; \ + } \ + } while (0) + + + +thread_object * +create_thread_object (struct thread_info *tp) +{ + thread_object *thread_obj; + + thread_obj = PyObject_New (thread_object, &thread_object_type); + if (!thread_obj) + return NULL; + + thread_obj->thread = tp; + thread_obj->inf_obj = find_inferior_object (PIDGET (tp->ptid)); + Py_INCREF (thread_obj->inf_obj); + + return thread_obj; +} + + + +static void +thpy_dealloc (PyObject *self) +{ + Py_DECREF (((thread_object *) self)->inf_obj); + self->ob_type->tp_free (self); +} + +static PyObject * +thpy_get_name (PyObject *self, void *ignore) +{ + thread_object *thread_obj = (thread_object *) self; + char *name; + + THPY_REQUIRE_VALID (thread_obj); + + name = thread_obj->thread->name; + if (name == NULL) + name = target_thread_name (thread_obj->thread); + + if (name == NULL) + Py_RETURN_NONE; + + return PyString_FromString (name); +} + +static int +thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore) +{ + thread_object *thread_obj = (thread_object *) self; + char *name; + + if (! thread_obj->thread) + { + PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists.")); + return -1; + } + + if (newvalue == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete `name' attribute.")); + return -1; + } + else if (newvalue == Py_None) + name = NULL; + else if (! gdbpy_is_string (newvalue)) + { + PyErr_SetString (PyExc_TypeError, + _("The value of `name' must be a string.")); + return -1; + } + else + { + name = python_string_to_host_string (newvalue); + if (! name) + return -1; + } + + xfree (thread_obj->thread->name); + thread_obj->thread->name = name; + + return 0; +} + +static PyObject * +thpy_get_num (PyObject *self, void *closure) +{ + thread_object *thread_obj = (thread_object *) self; + + THPY_REQUIRE_VALID (thread_obj); + + return PyLong_FromLong (thread_obj->thread->num); +} + +/* Getter for InferiorThread.ptid -> (pid, lwp, tid). + Returns a tuple with the thread's ptid components. */ +static PyObject * +thpy_get_ptid (PyObject *self, void *closure) +{ + int pid; + long tid, lwp; + thread_object *thread_obj = (thread_object *) self; + PyObject *ret; + + THPY_REQUIRE_VALID (thread_obj); + + ret = PyTuple_New (3); + if (!ret) + return NULL; + + pid = ptid_get_pid (thread_obj->thread->ptid); + lwp = ptid_get_lwp (thread_obj->thread->ptid); + tid = ptid_get_tid (thread_obj->thread->ptid); + + PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid)); + PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp)); + PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid)); + + return ret; +} + +/* Implementation of InferiorThread.switch (). + Makes this the GDB selected thread. */ +static PyObject * +thpy_switch (PyObject *self, PyObject *args) +{ + thread_object *thread_obj = (thread_object *) self; + struct cleanup *cleanup; + volatile struct gdb_exception except; + + THPY_REQUIRE_VALID (thread_obj); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + switch_to_thread (thread_obj->thread->ptid); + } + GDB_PY_HANDLE_EXCEPTION (except); + + Py_RETURN_NONE; +} + +/* Implementation of InferiorThread.is_stopped () -> Boolean. + Return whether the thread is stopped. */ +static PyObject * +thpy_is_stopped (PyObject *self, PyObject *args) +{ + thread_object *thread_obj = (thread_object *) self; + + THPY_REQUIRE_VALID (thread_obj); + + if (is_stopped (thread_obj->thread->ptid)) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implementation of InferiorThread.is_running () -> Boolean. + Return whether the thread is running. */ +static PyObject * +thpy_is_running (PyObject *self, PyObject *args) +{ + thread_object *thread_obj = (thread_object *) self; + + THPY_REQUIRE_VALID (thread_obj); + + if (is_running (thread_obj->thread->ptid)) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implementation of InferiorThread.is_exited () -> Boolean. + Return whether the thread is exited. */ +static PyObject * +thpy_is_exited (PyObject *self, PyObject *args) +{ + thread_object *thread_obj = (thread_object *) self; + + THPY_REQUIRE_VALID (thread_obj); + + if (is_exited (thread_obj->thread->ptid)) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implementation of gdb.InfThread.is_valid (self) -> Boolean. + Returns True if this inferior Thread object still exists + in GDB. */ + +static PyObject * +thpy_is_valid (PyObject *self, PyObject *args) +{ + thread_object *thread_obj = (thread_object *) self; + + if (! thread_obj->thread) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Implementation of gdb.selected_thread () -> gdb.InferiorThread. + Returns the selected thread object. */ +PyObject * +gdbpy_selected_thread (PyObject *self, PyObject *args) +{ + PyObject *thread_obj; + + thread_obj = (PyObject *) find_thread_object (inferior_ptid); + if (thread_obj) + { + Py_INCREF (thread_obj); + return thread_obj; + } + + Py_RETURN_NONE; +} + + + +void +gdbpy_initialize_thread (void) +{ + if (PyType_Ready (&thread_object_type) < 0) + return; + + Py_INCREF (&thread_object_type); + PyModule_AddObject (gdb_module, "InferiorThread", + (PyObject *) &thread_object_type); +} + + + +static PyGetSetDef thread_object_getset[] = +{ + { "name", thpy_get_name, thpy_set_name, + "The name of the thread, as set by the user or the OS.", NULL }, + { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL }, + { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.", + NULL }, + + { NULL } +}; + +static PyMethodDef thread_object_methods[] = +{ + { "is_valid", thpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this inferior thread is valid, false if not." }, + { "switch", thpy_switch, METH_NOARGS, + "switch ()\n\ +Makes this the GDB selected thread." }, + { "is_stopped", thpy_is_stopped, METH_NOARGS, + "is_stopped () -> Boolean\n\ +Return whether the thread is stopped." }, + { "is_running", thpy_is_running, METH_NOARGS, + "is_running () -> Boolean\n\ +Return whether the thread is running." }, + { "is_exited", thpy_is_exited, METH_NOARGS, + "is_exited () -> Boolean\n\ +Return whether the thread is exited." }, + + { NULL } +}; + +static PyTypeObject thread_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.InferiorThread", /*tp_name*/ + sizeof (thread_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + thpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB thread object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + thread_object_methods, /* tp_methods */ + 0, /* tp_members */ + thread_object_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0 /* tp_alloc */ +}; diff --git a/contrib/gdb-7/gdb/python/py-lazy-string.c b/contrib/gdb-7/gdb/python/py-lazy-string.c new file mode 100644 index 0000000000..940ce88cf5 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-lazy-string.c @@ -0,0 +1,244 @@ +/* Python interface to lazy strings. + + Copyright (C) 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "python-internal.h" +#include "charset.h" +#include "value.h" +#include "exceptions.h" +#include "valprint.h" +#include "language.h" +#include "gdb_assert.h" + +typedef struct { + PyObject_HEAD + /* Holds the address of the lazy string. */ + CORE_ADDR address; + + /* Holds the encoding that will be applied to the string + when the string is printed by GDB. If the encoding is set + to None then GDB will select the most appropriate + encoding when the sting is printed. */ + char *encoding; + + /* Holds the length of the string in characters. If the + length is -1, then the string will be fetched and encoded up to + the first null of appropriate width. */ + long length; + + /* This attribute holds the type that is represented by the lazy + string's type. */ + struct type *type; +} lazy_string_object; + +static PyTypeObject lazy_string_object_type; + +static PyObject * +stpy_get_address (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + + return gdb_py_long_from_ulongest (self_string->address); +} + +static PyObject * +stpy_get_encoding (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + PyObject *result; + + /* An encoding can be set to NULL by the user, so check before + attempting a Python FromString call. If NULL return Py_None. */ + if (self_string->encoding) + result = PyString_FromString (self_string->encoding); + else + { + result = Py_None; + Py_INCREF (result); + } + + return result; +} + +static PyObject * +stpy_get_length (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + + return PyLong_FromLong (self_string->length); +} + +PyObject * +stpy_get_type (PyObject *self, void *closure) +{ + lazy_string_object *str_obj = (lazy_string_object *) self; + + return type_to_type_object (str_obj->type); +} + +static PyObject * +stpy_convert_to_value (PyObject *self, PyObject *args) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + struct value *val; + + if (self_string->address == 0) + { + PyErr_SetString (PyExc_MemoryError, + _("Cannot create a value from NULL.")); + return NULL; + } + + val = value_at_lazy (self_string->type, self_string->address); + return value_to_value_object (val); +} + +static void +stpy_dealloc (PyObject *self) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + + xfree (self_string->encoding); +} + +PyObject * +gdbpy_create_lazy_string_object (CORE_ADDR address, long length, + const char *encoding, struct type *type) +{ + lazy_string_object *str_obj = NULL; + + if (address == 0 && length != 0) + { + PyErr_SetString (PyExc_MemoryError, + _("Cannot create a lazy string with address 0x0, " \ + "and a non-zero length.")); + return NULL; + } + + if (!type) + { + PyErr_SetString (PyExc_RuntimeError, + _("A lazy string's type cannot be NULL.")); + return NULL; + } + + str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type); + if (!str_obj) + return NULL; + + str_obj->address = address; + str_obj->length = length; + if (encoding == NULL || !strcmp (encoding, "")) + str_obj->encoding = NULL; + else + str_obj->encoding = xstrdup (encoding); + str_obj->type = type; + + return (PyObject *) str_obj; +} + +void +gdbpy_initialize_lazy_string (void) +{ + if (PyType_Ready (&lazy_string_object_type) < 0) + return; + + Py_INCREF (&lazy_string_object_type); +} + +/* Determine whether the printer object pointed to by OBJ is a + Python lazy string. */ +int +gdbpy_is_lazy_string (PyObject *result) +{ + return PyObject_TypeCheck (result, &lazy_string_object_type); +} + +/* Extract the parameters from the lazy string object STRING. + ENCODING will either be set to NULL, or will be allocated with + xmalloc, in which case the callers is responsible for freeing + it. */ + +void +gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, + struct type **str_type, + long *length, char **encoding) +{ + lazy_string_object *lazy; + + gdb_assert (gdbpy_is_lazy_string (string)); + + lazy = (lazy_string_object *) string; + + *addr = lazy->address; + *str_type = lazy->type; + *length = lazy->length; + *encoding = lazy->encoding ? xstrdup (lazy->encoding) : NULL; +} + + + +static PyMethodDef lazy_string_object_methods[] = { + { "value", stpy_convert_to_value, METH_NOARGS, + "Create a (lazy) value that contains a pointer to the string." }, + {NULL} /* Sentinel */ +}; + + +static PyGetSetDef lazy_string_object_getset[] = { + { "address", stpy_get_address, NULL, "Address of the string.", NULL }, + { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL }, + { "length", stpy_get_length, NULL, "Length of the string.", NULL }, + { "type", stpy_get_type, NULL, "Type associated with the string.", NULL }, + { NULL } /* Sentinel */ +}; + +static PyTypeObject lazy_string_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.LazyString", /*tp_name*/ + sizeof (lazy_string_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + stpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB lazy string object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lazy_string_object_methods, /* tp_methods */ + 0, /* tp_members */ + lazy_string_object_getset /* tp_getset */ +}; diff --git a/contrib/gdb-7/gdb/python/py-objfile.c b/contrib/gdb-7/gdb/python/py-objfile.c new file mode 100644 index 0000000000..f9821f507c --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-objfile.c @@ -0,0 +1,257 @@ +/* Python interface to objfiles. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "python-internal.h" +#include "charset.h" +#include "objfiles.h" +#include "language.h" + +typedef struct +{ + PyObject_HEAD + + /* The corresponding objfile. */ + struct objfile *objfile; + + /* The pretty-printer list of functions. */ + PyObject *printers; +} objfile_object; + +static PyTypeObject objfile_object_type; + +static const struct objfile_data *objfpy_objfile_data_key; + + + +/* An Objfile method which returns the objfile's file name, or None. */ +static PyObject * +objfpy_get_filename (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + + if (obj->objfile) + return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name), + host_charset (), NULL); + Py_RETURN_NONE; +} + +static void +objfpy_dealloc (PyObject *o) +{ + objfile_object *self = (objfile_object *) o; + + Py_XDECREF (self->printers); + self->ob_type->tp_free ((PyObject *) self); +} + +static PyObject * +objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) +{ + objfile_object *self = (objfile_object *) type->tp_alloc (type, 0); + + if (self) + { + self->objfile = NULL; + + self->printers = PyList_New (0); + if (!self->printers) + { + Py_DECREF (self); + return NULL; + } + } + return (PyObject *) self; +} + +PyObject * +objfpy_get_printers (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + + Py_INCREF (self->printers); + return self->printers; +} + +static int +objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + + if (! value) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete the pretty_printers attribute.")); + return -1; + } + + if (! PyList_Check (value)) + { + PyErr_SetString (PyExc_TypeError, + _("The pretty_printers attribute must be a list.")); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->printers; + Py_INCREF (value); + self->printers = value; + Py_XDECREF (tmp); + + return 0; +} + +/* Implementation of gdb.Objfile.is_valid (self) -> Boolean. + Returns True if this object file still exists in GDB. */ + +static PyObject * +objfpy_is_valid (PyObject *self, PyObject *args) +{ + objfile_object *obj = (objfile_object *) self; + + if (! obj->objfile) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + + + +/* Clear the OBJFILE pointer in an Objfile object and remove the + reference. */ +static void +py_free_objfile (struct objfile *objfile, void *datum) +{ + struct cleanup *cleanup; + objfile_object *object = datum; + + cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); + object->objfile = NULL; + Py_DECREF ((PyObject *) object); + do_cleanups (cleanup); +} + +/* Return a borrowed reference to the Python object of type Objfile + representing OBJFILE. If the object has already been created, + return it. Otherwise, create it. Return NULL and set the Python + error on failure. */ +PyObject * +objfile_to_objfile_object (struct objfile *objfile) +{ + objfile_object *object; + + object = objfile_data (objfile, objfpy_objfile_data_key); + if (!object) + { + object = PyObject_New (objfile_object, &objfile_object_type); + if (object) + { + object->objfile = objfile; + + object->printers = PyList_New (0); + if (!object->printers) + { + Py_DECREF (object); + return NULL; + } + + set_objfile_data (objfile, objfpy_objfile_data_key, object); + } + } + + return (PyObject *) object; +} + +void +gdbpy_initialize_objfile (void) +{ + objfpy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, py_free_objfile); + + if (PyType_Ready (&objfile_object_type) < 0) + return; + + Py_INCREF (&objfile_object_type); + PyModule_AddObject (gdb_module, "Objfile", + (PyObject *) &objfile_object_type); +} + + + +static PyMethodDef objfile_object_methods[] = +{ + { "is_valid", objfpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this object file is valid, false if not." }, + + { NULL } +}; + +static PyGetSetDef objfile_getset[] = +{ + { "filename", objfpy_get_filename, NULL, + "The objfile's filename, or None.", NULL }, + { "pretty_printers", objfpy_get_printers, objfpy_set_printers, + "Pretty printers.", NULL }, + { NULL } +}; + +static PyTypeObject objfile_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Objfile", /*tp_name*/ + sizeof (objfile_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + objfpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB objfile object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + objfile_object_methods, /* tp_methods */ + 0, /* tp_members */ + objfile_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + objfpy_new, /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-param.c b/contrib/gdb-7/gdb/python/py-param.c new file mode 100644 index 0000000000..4d873d88c3 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-param.c @@ -0,0 +1,812 @@ +/* GDB parameters implemented in Python + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbcmd.h" +#include "cli/cli-decode.h" +#include "completer.h" +#include "language.h" +#include "arch-utils.h" + +/* Parameter constants and their values. */ +struct parm_constant +{ + char *name; + int value; +}; + +struct parm_constant parm_constants[] = +{ + { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */ + { "PARAM_AUTO_BOOLEAN", var_auto_boolean }, + { "PARAM_UINTEGER", var_uinteger }, + { "PARAM_INTEGER", var_integer }, + { "PARAM_STRING", var_string }, + { "PARAM_STRING_NOESCAPE", var_string_noescape }, + { "PARAM_OPTIONAL_FILENAME", var_optional_filename }, + { "PARAM_FILENAME", var_filename }, + { "PARAM_ZINTEGER", var_zinteger }, + { "PARAM_ENUM", var_enum }, + { NULL, 0 } +}; + +/* A union that can hold anything described by enum var_types. */ +union parmpy_variable +{ + /* Hold an integer value, for boolean and integer types. */ + int intval; + + /* Hold an auto_boolean. */ + enum auto_boolean autoboolval; + + /* Hold an unsigned integer value, for uinteger. */ + unsigned int uintval; + + /* Hold a string, for the various string types. */ + char *stringval; + + /* Hold a string, for enums. */ + const char *cstringval; +}; + +/* A GDB parameter. */ +struct parmpy_object +{ + PyObject_HEAD + + /* The type of the parameter. */ + enum var_types type; + + /* The value of the parameter. */ + union parmpy_variable value; + + /* For an enum command, the possible values. The vector is + allocated with xmalloc, as is each element. It is + NULL-terminated. */ + const char **enumeration; +}; + +typedef struct parmpy_object parmpy_object; + +static PyTypeObject parmpy_object_type; + +/* Some handy string constants. */ +static PyObject *set_doc_cst; +static PyObject *show_doc_cst; + + + +/* Get an attribute. */ +static PyObject * +get_attr (PyObject *obj, PyObject *attr_name) +{ + if (PyString_Check (attr_name) + && ! strcmp (PyString_AsString (attr_name), "value")) + { + parmpy_object *self = (parmpy_object *) obj; + + return gdbpy_parameter_value (self->type, &self->value); + } + + return PyObject_GenericGetAttr (obj, attr_name); +} + +/* Set a parameter value from a Python value. Return 0 on success. Returns + -1 on error, with a python exception set. */ +static int +set_parameter_value (parmpy_object *self, PyObject *value) +{ + int cmp; + + switch (self->type) + { + case var_string: + case var_string_noescape: + case var_optional_filename: + case var_filename: + if (! gdbpy_is_string (value) + && (self->type == var_filename + || value != Py_None)) + { + PyErr_SetString (PyExc_RuntimeError, + _("String required for filename.")); + + return -1; + } + if (value == Py_None) + { + xfree (self->value.stringval); + if (self->type == var_optional_filename) + self->value.stringval = xstrdup (""); + else + self->value.stringval = NULL; + } + else + { + char *string; + + string = python_string_to_host_string (value); + if (string == NULL) + return -1; + + xfree (self->value.stringval); + self->value.stringval = string; + } + break; + + case var_enum: + { + int i; + char *str; + + if (! gdbpy_is_string (value)) + { + PyErr_SetString (PyExc_RuntimeError, + _("ENUM arguments must be a string.")); + return -1; + } + + str = python_string_to_host_string (value); + if (str == NULL) + return -1; + for (i = 0; self->enumeration[i]; ++i) + if (! strcmp (self->enumeration[i], str)) + break; + xfree (str); + if (! self->enumeration[i]) + { + PyErr_SetString (PyExc_RuntimeError, + _("The value must be member of an enumeration.")); + return -1; + } + self->value.cstringval = self->enumeration[i]; + break; + } + + case var_boolean: + if (! PyBool_Check (value)) + { + PyErr_SetString (PyExc_RuntimeError, + _("A boolean argument is required.")); + return -1; + } + cmp = PyObject_IsTrue (value); + if (cmp < 0) + return -1; + self->value.intval = cmp; + break; + + case var_auto_boolean: + if (! PyBool_Check (value) && value != Py_None) + { + PyErr_SetString (PyExc_RuntimeError, + _("A boolean or None is required")); + return -1; + } + + if (value == Py_None) + self->value.autoboolval = AUTO_BOOLEAN_AUTO; + else + { + cmp = PyObject_IsTrue (value); + if (cmp < 0 ) + return -1; + if (cmp == 1) + self->value.autoboolval = AUTO_BOOLEAN_TRUE; + else + self->value.autoboolval = AUTO_BOOLEAN_FALSE; + } + break; + + case var_integer: + case var_zinteger: + case var_uinteger: + { + long l; + int ok; + + if (! PyInt_Check (value)) + { + PyErr_SetString (PyExc_RuntimeError, + _("The value must be integer.")); + return -1; + } + + if (! gdb_py_int_as_long (value, &l)) + return -1; + + if (self->type == var_uinteger) + { + ok = (l >= 0 && l <= UINT_MAX); + if (l == 0) + l = UINT_MAX; + } + else if (self->type == var_integer) + { + ok = (l >= INT_MIN && l <= INT_MAX); + if (l == 0) + l = INT_MAX; + } + else + ok = (l >= INT_MIN && l <= INT_MAX); + + if (! ok) + { + PyErr_SetString (PyExc_RuntimeError, + _("Range exceeded.")); + return -1; + } + + self->value.intval = (int) l; + break; + } + + default: + PyErr_SetString (PyExc_RuntimeError, + _("Unhandled type in parameter value.")); + return -1; + } + + return 0; +} + +/* Set an attribute. Returns -1 on error, with a python exception set. */ +static int +set_attr (PyObject *obj, PyObject *attr_name, PyObject *val) +{ + if (PyString_Check (attr_name) + && ! strcmp (PyString_AsString (attr_name), "value")) + { + if (!val) + { + PyErr_SetString (PyExc_RuntimeError, + _("Cannot delete a parameter's value.")); + return -1; + } + return set_parameter_value ((parmpy_object *) obj, val); + } + + return PyObject_GenericSetAttr (obj, attr_name, val); +} + +/* A helper function which returns a documentation string for an + object. */ + +static char * +get_doc_string (PyObject *object, PyObject *attr) +{ + char *result = NULL; + + if (PyObject_HasAttr (object, attr)) + { + PyObject *ds_obj = PyObject_GetAttr (object, attr); + + if (ds_obj && gdbpy_is_string (ds_obj)) + { + result = python_string_to_host_string (ds_obj); + if (result == NULL) + gdbpy_print_stack (); + } + Py_XDECREF (ds_obj); + } + if (! result) + result = xstrdup (_("This command is not documented.")); + return result; +} + +/* Helper function which will execute a METHOD in OBJ passing the + argument ARG. ARG can be NULL. METHOD should return a Python + string. If this function returns NULL, there has been an error and + the appropriate exception set. */ +static char * +call_doc_function (PyObject *obj, PyObject *method, PyObject *arg) +{ + char *data = NULL; + PyObject *result = PyObject_CallMethodObjArgs (obj, method, arg, NULL); + + if (! result) + return NULL; + + if (gdbpy_is_string (result)) + { + data = python_string_to_host_string (result); + if (! data) + return NULL; + } + else + { + PyErr_SetString (PyExc_RuntimeError, + _("Parameter must return a string value.")); + return NULL; + } + + return data; +} + +/* A callback function that is registered against the respective + add_setshow_* set_doc prototype. This function will either call + the Python function "get_set_string" or extract the Python + attribute "set_doc" and return the contents as a string. If + neither exist, insert a string indicating the Parameter is not + documented. */ +static void +get_set_value (char *args, int from_tty, + struct cmd_list_element *c) +{ + PyObject *obj = (PyObject *) get_cmd_context (c); + char *set_doc_string; + struct cleanup *cleanup = ensure_python_env (get_current_arch (), + current_language); + PyObject *set_doc_func = PyString_FromString ("get_set_string"); + + if (! set_doc_func) + goto error; + + make_cleanup_py_decref (set_doc_func); + + if (PyObject_HasAttr (obj, set_doc_func)) + { + set_doc_string = call_doc_function (obj, set_doc_func, NULL); + if (! set_doc_string) + goto error; + } + else + { + /* We have to preserve the existing < GDB 7.3 API. If a + callback function does not exist, then attempt to read the + set_doc attribute. */ + set_doc_string = get_doc_string (obj, set_doc_cst); + } + + make_cleanup (xfree, set_doc_string); + fprintf_filtered (gdb_stdout, "%s\n", set_doc_string); + + do_cleanups (cleanup); + return; + + error: + gdbpy_print_stack (); + do_cleanups (cleanup); + return; +} + +/* A callback function that is registered against the respective + add_setshow_* show_doc prototype. This function will either call + the Python function "get_show_string" or extract the Python + attribute "show_doc" and return the contents as a string. If + neither exist, insert a string indicating the Parameter is not + documented. */ +static void +get_show_value (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + PyObject *obj = (PyObject *) get_cmd_context (c); + char *show_doc_string = NULL; + struct cleanup *cleanup = ensure_python_env (get_current_arch (), + current_language); + PyObject *show_doc_func = PyString_FromString ("get_show_string"); + + if (! show_doc_func) + goto error; + + make_cleanup_py_decref (show_doc_func); + + if (PyObject_HasAttr (obj, show_doc_func)) + { + PyObject *val_obj = PyString_FromString (value); + + if (! val_obj) + goto error; + + make_cleanup_py_decref (val_obj); + + show_doc_string = call_doc_function (obj, show_doc_func, val_obj); + if (! show_doc_string) + goto error; + + make_cleanup (xfree, show_doc_string); + + fprintf_filtered (file, "%s\n", show_doc_string); + } + else + { + /* We have to preserve the existing < GDB 7.3 API. If a + callback function does not exist, then attempt to read the + show_doc attribute. */ + show_doc_string = get_doc_string (obj, show_doc_cst); + make_cleanup (xfree, show_doc_string); + fprintf_filtered (file, "%s %s\n", show_doc_string, value); + } + + do_cleanups (cleanup); + return; + + error: + gdbpy_print_stack (); + do_cleanups (cleanup); + return; +} + + +/* A helper function that dispatches to the appropriate add_setshow + function. */ +static void +add_setshow_generic (int parmclass, enum command_class cmdclass, + char *cmd_name, parmpy_object *self, + char *set_doc, char *show_doc, char *help_doc, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + struct cmd_list_element *param = NULL; + char *tmp_name = NULL; + + switch (parmclass) + { + case var_boolean: + + add_setshow_boolean_cmd (cmd_name, cmdclass, + &self->value.intval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); + + break; + + case var_auto_boolean: + add_setshow_auto_boolean_cmd (cmd_name, cmdclass, + &self->value.autoboolval, + set_doc, show_doc, help_doc, + get_set_value, get_show_value, + set_list, show_list); + break; + + case var_uinteger: + add_setshow_uinteger_cmd (cmd_name, cmdclass, + &self->value.uintval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); + break; + + case var_integer: + add_setshow_integer_cmd (cmd_name, cmdclass, + &self->value.intval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); break; + + case var_string: + add_setshow_string_cmd (cmd_name, cmdclass, + &self->value.stringval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); break; + + case var_string_noescape: + add_setshow_string_noescape_cmd (cmd_name, cmdclass, + &self->value.stringval, + set_doc, show_doc, help_doc, + get_set_value, get_show_value, + set_list, show_list); + + break; + + case var_optional_filename: + add_setshow_optional_filename_cmd (cmd_name, cmdclass, + &self->value.stringval, set_doc, + show_doc, help_doc, get_set_value, + get_show_value, set_list, + show_list); + break; + + case var_filename: + add_setshow_filename_cmd (cmd_name, cmdclass, + &self->value.stringval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); break; + + case var_zinteger: + add_setshow_zinteger_cmd (cmd_name, cmdclass, + &self->value.intval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); + break; + + case var_enum: + add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration, + &self->value.cstringval, set_doc, show_doc, + help_doc, get_set_value, get_show_value, + set_list, show_list); + /* Initialize the value, just in case. */ + self->value.cstringval = self->enumeration[0]; + break; + } + + /* Lookup created parameter, and register Python object against the + parameter context. Perform this task against both lists. */ + tmp_name = cmd_name; + param = lookup_cmd (&tmp_name, *show_list, "", 0, 1); + if (param) + set_cmd_context (param, self); + + tmp_name = cmd_name; + param = lookup_cmd (&tmp_name, *set_list, "", 0, 1); + if (param) + set_cmd_context (param, self); +} + +/* A helper which computes enum values. Returns 1 on success. Returns 0 on + error, with a python exception set. */ +static int +compute_enum_values (parmpy_object *self, PyObject *enum_values) +{ + Py_ssize_t size, i; + struct cleanup *back_to; + + if (! enum_values) + { + PyErr_SetString (PyExc_RuntimeError, + _("An enumeration is required for PARAM_ENUM.")); + return 0; + } + + if (! PySequence_Check (enum_values)) + { + PyErr_SetString (PyExc_RuntimeError, + _("The enumeration is not a sequence.")); + return 0; + } + + size = PySequence_Size (enum_values); + if (size < 0) + return 0; + if (size == 0) + { + PyErr_SetString (PyExc_RuntimeError, + _("The enumeration is empty.")); + return 0; + } + + self->enumeration = xmalloc ((size + 1) * sizeof (char *)); + back_to = make_cleanup (free_current_contents, &self->enumeration); + memset (self->enumeration, 0, (size + 1) * sizeof (char *)); + + for (i = 0; i < size; ++i) + { + PyObject *item = PySequence_GetItem (enum_values, i); + + if (! item) + { + do_cleanups (back_to); + return 0; + } + if (! gdbpy_is_string (item)) + { + do_cleanups (back_to); + PyErr_SetString (PyExc_RuntimeError, + _("The enumeration item not a string.")); + return 0; + } + self->enumeration[i] = python_string_to_host_string (item); + if (self->enumeration[i] == NULL) + { + do_cleanups (back_to); + return 0; + } + make_cleanup (xfree, (char *) self->enumeration[i]); + } + + discard_cleanups (back_to); + return 1; +} + +/* Object initializer; sets up gdb-side structures for command. + + Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM]) + + NAME is the name of the parameter. It may consist of multiple + words, in which case the final word is the name of the new command, + and earlier words must be prefix commands. + + CMDCLASS is the kind of command. It should be one of the COMMAND_* + constants defined in the gdb module. + + PARMCLASS is the type of the parameter. It should be one of the + PARAM_* constants defined in the gdb module. + + If PARMCLASS is PARAM_ENUM, then the final argument should be a + collection of strings. These strings are the valid values for this + parameter. + + The documentation for the parameter is taken from the doc string + for the python class. + + Returns -1 on error, with a python exception set. */ + +static int +parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) +{ + parmpy_object *obj = (parmpy_object *) self; + char *name; + char *set_doc, *show_doc, *doc; + char *cmd_name; + int parmclass, cmdtype; + PyObject *enum_values = NULL; + struct cmd_list_element **set_list, **show_list; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass, + &enum_values)) + return -1; + + if (cmdtype != no_class && cmdtype != class_run + && cmdtype != class_vars && cmdtype != class_stack + && cmdtype != class_files && cmdtype != class_support + && cmdtype != class_info && cmdtype != class_breakpoint + && cmdtype != class_trace && cmdtype != class_obscure + && cmdtype != class_maintenance) + { + PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument.")); + return -1; + } + + if (parmclass != var_boolean /* ARI: var_boolean */ + && parmclass != var_auto_boolean + && parmclass != var_uinteger && parmclass != var_integer + && parmclass != var_string && parmclass != var_string_noescape + && parmclass != var_optional_filename && parmclass != var_filename + && parmclass != var_zinteger && parmclass != var_enum) + { + PyErr_SetString (PyExc_RuntimeError, + _("Invalid parameter class argument.")); + return -1; + } + + if (enum_values && parmclass != var_enum) + { + PyErr_SetString (PyExc_RuntimeError, + _("Only PARAM_ENUM accepts a fourth argument.")); + return -1; + } + if (parmclass == var_enum) + { + if (! compute_enum_values (obj, enum_values)) + return -1; + } + else + obj->enumeration = NULL; + obj->type = (enum var_types) parmclass; + memset (&obj->value, 0, sizeof (obj->value)); + + cmd_name = gdbpy_parse_command_name (name, &set_list, + &setlist); + + if (! cmd_name) + return -1; + xfree (cmd_name); + cmd_name = gdbpy_parse_command_name (name, &show_list, + &showlist); + if (! cmd_name) + return -1; + + set_doc = get_doc_string (self, set_doc_cst); + show_doc = get_doc_string (self, show_doc_cst); + doc = get_doc_string (self, gdbpy_doc_cst); + + Py_INCREF (self); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + add_setshow_generic (parmclass, (enum command_class) cmdtype, + cmd_name, obj, + set_doc, show_doc, + doc, set_list, show_list); + } + if (except.reason < 0) + { + xfree (cmd_name); + xfree (set_doc); + xfree (show_doc); + xfree (doc); + Py_DECREF (self); + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return -1; + } + return 0; +} + + + +/* Initialize the 'parameters' module. */ +void +gdbpy_initialize_parameters (void) +{ + int i; + + if (PyType_Ready (&parmpy_object_type) < 0) + return; + + set_doc_cst = PyString_FromString ("set_doc"); + if (! set_doc_cst) + return; + show_doc_cst = PyString_FromString ("show_doc"); + if (! show_doc_cst) + return; + + for (i = 0; parm_constants[i].name; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + parm_constants[i].name, + parm_constants[i].value) < 0) + return; + } + + Py_INCREF (&parmpy_object_type); + PyModule_AddObject (gdb_module, "Parameter", + (PyObject *) &parmpy_object_type); +} + + + +static PyTypeObject parmpy_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Parameter", /*tp_name*/ + sizeof (parmpy_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + get_attr, /*tp_getattro*/ + set_attr, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB parameter object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + parmpy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-prettyprint.c b/contrib/gdb-7/gdb/python/py-prettyprint.c index 434c8a593d..a657432504 100644 --- a/contrib/gdb-7/gdb/python/py-prettyprint.c +++ b/contrib/gdb-7/gdb/python/py-prettyprint.c @@ -1,6 +1,6 @@ /* Python pretty-printing - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +29,18 @@ #ifdef HAVE_PYTHON #include "python-internal.h" +/* Return type of print_string_repr. */ + +enum string_repr_result + { + /* The string method returned None. */ + string_repr_none, + /* The string method had an error. */ + string_repr_error, + /* Everything ok. */ + string_repr_ok + }; + /* Helper function for find_pretty_printer which iterates over a list, calls each function and inspects output. This will return a printer object if one recognizes VALUE. If no printer is found, it @@ -49,9 +61,20 @@ search_pp_list (PyObject *list, PyObject *value) return NULL; /* Skip if disabled. */ - if (PyObject_HasAttr (function, gdbpy_enabled_cst) - && ! PyObject_IsTrue (PyObject_GetAttr (function, gdbpy_enabled_cst))) - continue; + if (PyObject_HasAttr (function, gdbpy_enabled_cst)) + { + PyObject *attr = PyObject_GetAttr (function, gdbpy_enabled_cst); + int cmp; + + if (!attr) + return NULL; + cmp = PyObject_IsTrue (attr); + if (cmp == -1) + return NULL; + + if (!cmp) + continue; + } printer = PyObject_CallFunctionObjArgs (function, value, NULL); if (! printer) @@ -138,7 +161,7 @@ find_pretty_printer_from_gdb (PyObject *value) PyObject *pp_list; PyObject *function; - /* Fetch the global pretty printer dictionary. */ + /* Fetch the global pretty printer list. */ if (! PyObject_HasAttrString (gdb_module, "pretty_printers")) Py_RETURN_NONE; pp_list = PyObject_GetAttrString (gdb_module, "pretty_printers"); @@ -162,20 +185,20 @@ find_pretty_printer (PyObject *value) { PyObject *function; - /* Look at the pretty-printer dictionary for each objfile + /* Look at the pretty-printer list for each objfile in the current program-space. */ function = find_pretty_printer_from_objfiles (value); if (function == NULL || function != Py_None) return function; Py_DECREF (function); - /* Look at the pretty-printer dictionary for the current program-space. */ + /* Look at the pretty-printer list for the current program-space. */ function = find_pretty_printer_from_progspace (value); if (function == NULL || function != Py_None) return function; Py_DECREF (function); - /* Look at the pretty-printer dictionary in the gdb module. */ + /* Look at the pretty-printer list in the gdb module. */ function = find_pretty_printer_from_gdb (value); return function; } @@ -185,8 +208,8 @@ find_pretty_printer (PyObject *value) is returned. If the function returns Py_NONE that means the pretty printer returned the Python None as a value. Otherwise, if the function returns a value, *OUT_VALUE is set to the value, and NULL - is returned. On error, *OUT_VALUE is set to NULL, and NULL is - returned. */ + is returned. On error, *OUT_VALUE is set to NULL, NULL is + returned, with a python exception set. */ static PyObject * pretty_print_one_value (PyObject *printer, struct value **out_value) @@ -232,7 +255,11 @@ gdbpy_get_display_hint (PyObject *printer) if (hint) { if (gdbpy_is_string (hint)) - result = python_string_to_host_string (hint); + { + result = python_string_to_host_string (hint); + if (result == NULL) + gdbpy_print_stack (); + } Py_DECREF (hint); } else @@ -241,12 +268,40 @@ gdbpy_get_display_hint (PyObject *printer) return result; } +/* A wrapper for gdbpy_print_stack that ignores MemoryError. */ + +static void +print_stack_unless_memory_error (struct ui_file *stream) +{ + if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error)) + { + struct cleanup *cleanup; + PyObject *type, *value, *trace; + char *msg; + + PyErr_Fetch (&type, &value, &trace); + cleanup = make_cleanup_py_decref (type); + make_cleanup_py_decref (value); + make_cleanup_py_decref (trace); + + msg = gdbpy_exception_to_string (type, value); + make_cleanup (xfree, msg); + + if (msg == NULL || *msg == '\0') + fprintf_filtered (stream, _("")); + else + fprintf_filtered (stream, _(""), msg); + + do_cleanups (cleanup); + } + else + gdbpy_print_stack (); +} + /* Helper for apply_val_pretty_printer which calls to_string and - formats the result. If the value returnd is Py_None, nothing is - printed and the function returns a 1; in all other cases data is - printed as given by the pretty printer and the function returns 0. -*/ -static int + formats the result. */ + +static enum string_repr_result print_string_repr (PyObject *printer, const char *hint, struct ui_file *stream, int recurse, const struct value_print_options *options, @@ -255,58 +310,61 @@ print_string_repr (PyObject *printer, const char *hint, { struct value *replacement = NULL; PyObject *py_str = NULL; - int is_py_none = 0; + enum string_repr_result result = string_repr_ok; py_str = pretty_print_one_value (printer, &replacement); if (py_str) { + struct cleanup *cleanup = make_cleanup_py_decref (py_str); + if (py_str == Py_None) - is_py_none = 1; - else + result = string_repr_none; + else if (gdbpy_is_lazy_string (py_str)) { - gdb_byte *output = NULL; + CORE_ADDR addr; long length; struct type *type; char *encoding = NULL; - PyObject *string = NULL; - int is_lazy; + struct value_print_options local_opts = *options; - is_lazy = gdbpy_is_lazy_string (py_str); - if (is_lazy) - output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding); - else - { - string = python_string_to_target_python_string (py_str); - if (string) - { - output = PyString_AsString (string); - length = PyString_Size (string); - type = builtin_type (gdbarch)->builtin_char; - } - else - gdbpy_print_stack (); - - } - - if (output) + make_cleanup (free_current_contents, &encoding); + gdbpy_extract_lazy_string (py_str, &addr, &type, + &length, &encoding); + + local_opts.addressprint = 0; + val_print_string (type, encoding, addr, (int) length, + stream, &local_opts); + } + else + { + PyObject *string; + + string = python_string_to_target_python_string (py_str); + if (string) { - if (is_lazy || (hint && !strcmp (hint, "string"))) - LA_PRINT_STRING (stream, type, output, length, encoding, + gdb_byte *output; + long length; + struct type *type; + + make_cleanup_py_decref (string); + output = PyString_AsString (string); + length = PyString_Size (string); + type = builtin_type (gdbarch)->builtin_char; + + if (hint && !strcmp (hint, "string")) + LA_PRINT_STRING (stream, type, output, length, NULL, 0, options); else fputs_filtered (output, stream); } else - gdbpy_print_stack (); - - if (string) - Py_DECREF (string); - else - xfree (output); - - xfree (encoding); - Py_DECREF (py_str); + { + result = string_repr_error; + print_stack_unless_memory_error (stream); + } } + + do_cleanups (cleanup); } else if (replacement) { @@ -316,9 +374,12 @@ print_string_repr (PyObject *printer, const char *hint, common_val_print (replacement, stream, recurse, &opts, language); } else - gdbpy_print_stack (); + { + result = string_repr_error; + print_stack_unless_memory_error (stream); + } - return is_py_none; + return result; } static void @@ -333,7 +394,7 @@ py_restore_tstate (void *p) /* Create a dummy PyFrameObject, needed to work around a Python-2.4 bug with generators. */ static PyObject * -push_dummy_python_frame () +push_dummy_python_frame (void) { PyObject *empty_string, *null_tuple, *globals; PyCodeObject *code; @@ -424,7 +485,7 @@ print_children (PyObject *printer, const char *hint, NULL); if (! children) { - gdbpy_print_stack (); + print_stack_unless_memory_error (stream); return; } @@ -433,14 +494,22 @@ print_children (PyObject *printer, const char *hint, iter = PyObject_GetIter (children); if (!iter) { - gdbpy_print_stack (); + print_stack_unless_memory_error (stream); goto done; } make_cleanup_py_decref (iter); /* Use the prettyprint_arrays option if we are printing an array, and the pretty option otherwise. */ - pretty = is_array ? options->prettyprint_arrays : options->pretty; + if (is_array) + pretty = options->prettyprint_arrays; + else + { + if (options->pretty == Val_prettyprint) + pretty = 1; + else + pretty = options->prettyprint_structs; + } /* Manufacture a dummy Python frame to work around Python 2.4 bug, where it insists on having a non-NULL tstate->frame when @@ -463,7 +532,7 @@ print_children (PyObject *printer, const char *hint, if (! item) { if (PyErr_Occurred ()) - gdbpy_print_stack (); + print_stack_unless_memory_error (stream); /* Set a flag so we can know whether we printed all the available elements. */ else @@ -533,28 +602,32 @@ print_children (PyObject *printer, const char *hint, fputs_filtered (" = ", stream); } - if (gdbpy_is_lazy_string (py_v) || gdbpy_is_string (py_v)) + if (gdbpy_is_lazy_string (py_v)) + { + CORE_ADDR addr; + struct type *type; + long length; + char *encoding = NULL; + struct value_print_options local_opts = *options; + + make_cleanup (free_current_contents, &encoding); + gdbpy_extract_lazy_string (py_v, &addr, &type, &length, &encoding); + + local_opts.addressprint = 0; + val_print_string (type, encoding, addr, (int) length, stream, + &local_opts); + + do_cleanups (inner_cleanup); + } + else if (gdbpy_is_string (py_v)) { - gdb_byte *output = NULL; + gdb_byte *output; - if (gdbpy_is_lazy_string (py_v)) - { - struct type *type; - long length; - char *encoding = NULL; - - output = gdbpy_extract_lazy_string (py_v, &type, - &length, &encoding); - if (!output) - gdbpy_print_stack (); - LA_PRINT_STRING (stream, type, output, length, encoding, - 0, options); - xfree (encoding); - xfree (output); - } + output = python_string_to_host_string (py_v); + if (!output) + gdbpy_print_stack (); else { - output = python_string_to_host_string (py_v); fputs_filtered (output, stream); xfree (output); } @@ -616,7 +689,12 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, char *hint = NULL; struct cleanup *cleanups; int result = 0; - int is_py_none = 0; + enum string_repr_result print_result; + + /* No pretty-printer support for unavailable values. */ + if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) + return 0; + cleanups = ensure_python_env (gdbarch, language); /* Instantiate the printer. */ @@ -624,16 +702,14 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, valaddr += embedded_offset; value = value_from_contents_and_address (type, valaddr, address + embedded_offset); - if (val != NULL) - { - set_value_component_location (value, val); - /* set_value_component_location resets the address, so we may - need to set it again. */ - if (VALUE_LVAL (value) != lval_internalvar - && VALUE_LVAL (value) != lval_internalvar_component - && VALUE_LVAL (value) != lval_computed) - set_value_address (value, address + embedded_offset); - } + + set_value_component_location (value, val); + /* set_value_component_location resets the address, so we may + need to set it again. */ + if (VALUE_LVAL (value) != lval_internalvar + && VALUE_LVAL (value) != lval_internalvar_component + && VALUE_LVAL (value) != lval_computed) + set_value_address (value, address + embedded_offset); val_obj = value_to_value_object (value); if (! val_obj) @@ -651,17 +727,18 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, make_cleanup (free_current_contents, &hint); /* Print the section */ - is_py_none = print_string_repr (printer, hint, stream, recurse, - options, language, gdbarch); - print_children (printer, hint, stream, recurse, options, language, - is_py_none); + print_result = print_string_repr (printer, hint, stream, recurse, + options, language, gdbarch); + if (print_result != string_repr_error) + print_children (printer, hint, stream, recurse, options, language, + print_result == string_repr_none); result = 1; done: if (PyErr_Occurred ()) - gdbpy_print_stack (); + print_stack_unless_memory_error (stream); do_cleanups (cleanups); return result; } @@ -678,7 +755,8 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, NULL. */ PyObject * apply_varobj_pretty_printer (PyObject *printer_obj, - struct value **replacement) + struct value **replacement, + struct ui_file *stream) { PyObject *py_str = NULL; @@ -686,7 +764,7 @@ apply_varobj_pretty_printer (PyObject *printer_obj, py_str = pretty_print_one_value (printer_obj, replacement); if (*replacement == NULL && py_str == NULL) - gdbpy_print_stack (); + print_stack_unless_memory_error (stream); return py_str; } diff --git a/contrib/gdb-7/gdb/python/py-progspace.c b/contrib/gdb-7/gdb/python/py-progspace.c new file mode 100644 index 0000000000..c30b37d20f --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-progspace.c @@ -0,0 +1,244 @@ +/* Python interface to program spaces. + + Copyright (C) 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "python-internal.h" +#include "charset.h" +#include "progspace.h" +#include "objfiles.h" +#include "language.h" +#include "arch-utils.h" + +typedef struct +{ + PyObject_HEAD + + /* The corresponding pspace. */ + struct program_space *pspace; + + /* The pretty-printer list of functions. */ + PyObject *printers; +} pspace_object; + +static PyTypeObject pspace_object_type; + +static const struct program_space_data *pspy_pspace_data_key; + + + +/* An Objfile method which returns the objfile's file name, or None. */ + +static PyObject * +pspy_get_filename (PyObject *self, void *closure) +{ + pspace_object *obj = (pspace_object *) self; + + if (obj->pspace) + { + struct objfile *objfile = obj->pspace->symfile_object_file; + + if (objfile) + return PyString_Decode (objfile->name, strlen (objfile->name), + host_charset (), NULL); + } + Py_RETURN_NONE; +} + +static void +pspy_dealloc (PyObject *self) +{ + pspace_object *ps_self = (pspace_object *) self; + + Py_XDECREF (ps_self->printers); + self->ob_type->tp_free (self); +} + +static PyObject * +pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) +{ + pspace_object *self = (pspace_object *) type->tp_alloc (type, 0); + + if (self) + { + self->pspace = NULL; + + self->printers = PyList_New (0); + if (!self->printers) + { + Py_DECREF (self); + return NULL; + } + } + return (PyObject *) self; +} + +PyObject * +pspy_get_printers (PyObject *o, void *ignore) +{ + pspace_object *self = (pspace_object *) o; + + Py_INCREF (self->printers); + return self->printers; +} + +static int +pspy_set_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + pspace_object *self = (pspace_object *) o; + + if (! value) + { + PyErr_SetString (PyExc_TypeError, + "cannot delete the pretty_printers attribute"); + return -1; + } + + if (! PyList_Check (value)) + { + PyErr_SetString (PyExc_TypeError, + "the pretty_printers attribute must be a list"); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->printers; + Py_INCREF (value); + self->printers = value; + Py_XDECREF (tmp); + + return 0; +} + + + +/* Clear the PSPACE pointer in a Pspace object and remove the reference. */ + +static void +py_free_pspace (struct program_space *pspace, void *datum) +{ + struct cleanup *cleanup; + pspace_object *object = datum; + struct gdbarch *arch = get_current_arch (); + + cleanup = ensure_python_env (arch, current_language); + object->pspace = NULL; + Py_DECREF ((PyObject *) object); + do_cleanups (cleanup); +} + +/* Return a borrowed reference to the Python object of type Pspace + representing PSPACE. If the object has already been created, + return it. Otherwise, create it. Return NULL and set the Python + error on failure. */ + +PyObject * +pspace_to_pspace_object (struct program_space *pspace) +{ + pspace_object *object; + + object = program_space_data (pspace, pspy_pspace_data_key); + if (!object) + { + object = PyObject_New (pspace_object, &pspace_object_type); + if (object) + { + object->pspace = pspace; + + object->printers = PyList_New (0); + if (!object->printers) + { + Py_DECREF (object); + return NULL; + } + + set_program_space_data (pspace, pspy_pspace_data_key, object); + } + } + + return (PyObject *) object; +} + +void +gdbpy_initialize_pspace (void) +{ + pspy_pspace_data_key + = register_program_space_data_with_cleanup (py_free_pspace); + + if (PyType_Ready (&pspace_object_type) < 0) + return; + + Py_INCREF (&pspace_object_type); + PyModule_AddObject (gdb_module, "Progspace", + (PyObject *) &pspace_object_type); +} + + + +static PyGetSetDef pspace_getset[] = +{ + { "filename", pspy_get_filename, NULL, + "The progspace's main filename, or None.", NULL }, + { "pretty_printers", pspy_get_printers, pspy_set_printers, + "Pretty printers.", NULL }, + { NULL } +}; + +static PyTypeObject pspace_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Progspace", /*tp_name*/ + sizeof (pspace_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + pspy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB progspace object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + pspace_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + pspy_new, /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-signalevent.c b/contrib/gdb-7/gdb/python/py-signalevent.c new file mode 100644 index 0000000000..3d7ce3229a --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-signalevent.c @@ -0,0 +1,53 @@ +/* Python interface to inferior signal stop events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-stopevent.h" + +static PyTypeObject signal_event_object_type; + +PyObject * +create_signal_event_object (enum target_signal stop_signal) +{ + const char *signal_name; + PyObject *signal_event_obj = + create_stop_event_object (&signal_event_object_type); + + if (!signal_event_obj) + goto fail; + + signal_name = target_signal_to_name (stop_signal); + + if (evpy_add_attribute (signal_event_obj, + "stop_signal", + PyString_FromString (signal_name)) < 0) + goto fail; + + return signal_event_obj; + + fail: + Py_XDECREF (signal_event_obj); + return NULL; +} + +GDBPY_NEW_EVENT_TYPE (signal, + "gdb.SignalEvent", + "SignalEvent", + "GDB signal event object", + stop_event_object_type, + static); diff --git a/contrib/gdb-7/gdb/python/py-stopevent.c b/contrib/gdb-7/gdb/python/py-stopevent.c new file mode 100644 index 0000000000..122fe6bec3 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-stopevent.c @@ -0,0 +1,92 @@ +/* Python interface to inferior stop events. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-stopevent.h" + +PyObject * +create_stop_event_object (PyTypeObject *py_type) +{ + PyObject *stop_event_obj = create_thread_event_object (py_type); + + if (!stop_event_obj) + goto fail; + + return stop_event_obj; + + fail: + Py_XDECREF (stop_event_obj); + return NULL; +} + +/* Callback observers when a stop event occurs. This function will create a + new Python stop event object. If only a specific thread is stopped the + thread object of the event will be set to that thread. Otherwise, if all + threads are stopped thread object will be set to None. + return 0 if the event was created and emitted successfully otherwise + returns -1. */ + +int +emit_stop_event (struct bpstats *bs, enum target_signal stop_signal) +{ + PyObject *stop_event_obj = NULL; /* Appease GCC warning. */ + + if (evregpy_no_listeners_p (gdb_py_events.stop)) + return 0; + + if (bs && bs->breakpoint_at + && bs->breakpoint_at->py_bp_object) + { + stop_event_obj = create_breakpoint_event_object ((PyObject *) bs + ->breakpoint_at + ->py_bp_object); + if (!stop_event_obj) + goto fail; + } + + /* Check if the signal is "Signal 0" or "Trace/breakpoint trap". */ + if (stop_signal != TARGET_SIGNAL_0 + && stop_signal != TARGET_SIGNAL_TRAP) + { + stop_event_obj = + create_signal_event_object (stop_signal); + if (!stop_event_obj) + goto fail; + } + + /* If all fails emit an unknown stop event. All event types should + be known and this should eventually be unused. */ + if (!stop_event_obj) + { + stop_event_obj = create_stop_event_object (&stop_event_object_type); + if (!stop_event_obj) + goto fail; + } + + return evpy_emit_event (stop_event_obj, gdb_py_events.stop); + + fail: + return -1; +} + +GDBPY_NEW_EVENT_TYPE (stop, + "gdb.StopEvent", + "StopEvent", + "GDB stop event object", + thread_event_object_type, + /*no qual*/); diff --git a/contrib/gdb-7/gdb/mi/mi-main.h b/contrib/gdb-7/gdb/python/py-stopevent.h similarity index 53% copy from contrib/gdb-7/gdb/mi/mi-main.h copy to contrib/gdb-7/gdb/python/py-stopevent.h index da1dfc0593..52f3511df3 100644 --- a/contrib/gdb-7/gdb/mi/mi-main.h +++ b/contrib/gdb-7/gdb/python/py-stopevent.h @@ -1,6 +1,6 @@ -/* MI Internal Functions for GDB, the GNU debugger. +/* Python interface to inferior events. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -17,21 +17,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MI_MAIN_H -#define MI_MAIN_H +#ifndef GDB_PY_STOPEVENT_H +#define GDB_PY_STOPEVENT_H -extern void mi_load_progress (const char *section_name, - unsigned long sent_so_far, - unsigned long total_section, - unsigned long total_sent, - unsigned long grand_total); +#include "py-event.h" -extern void mi_print_timing_maybe (void); +extern PyObject *create_stop_event_object (PyTypeObject *py_type); +extern void stop_evpy_dealloc (PyObject *self); -extern char *current_token; +extern int emit_stop_event (struct bpstats *bs, + enum target_signal stop_signal); -extern int running_result_record_printed; -extern int mi_proceeded; +extern PyObject *create_breakpoint_event_object (PyObject *breakpoint); -#endif +extern PyObject *create_signal_event_object (enum target_signal stop_signal); +#endif /* GDB_PY_STOPEVENT_H */ diff --git a/contrib/gdb-7/gdb/python/py-symbol.c b/contrib/gdb-7/gdb/python/py-symbol.c new file mode 100644 index 0000000000..046d78c76a --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-symbol.c @@ -0,0 +1,477 @@ +/* Python interface to symbols. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "block.h" +#include "exceptions.h" +#include "frame.h" +#include "symtab.h" +#include "python-internal.h" +#include "objfiles.h" + +typedef struct sympy_symbol_object { + PyObject_HEAD + /* The GDB symbol structure this object is wrapping. */ + struct symbol *symbol; + /* A symbol object is associated with an objfile, so keep track with + doubly-linked list, rooted in the objfile. This lets us + invalidate the underlying struct symbol when the objfile is + deleted. */ + struct sympy_symbol_object *prev; + struct sympy_symbol_object *next; +} symbol_object; + +/* Require a valid symbol. All access to symbol_object->symbol should be + gated by this call. */ +#define SYMPY_REQUIRE_VALID(symbol_obj, symbol) \ + do { \ + symbol = symbol_object_to_symbol (symbol_obj); \ + if (symbol == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Symbol is invalid.")); \ + return NULL; \ + } \ + } while (0) + +static const struct objfile_data *sympy_objfile_data_key; + +static PyObject * +sympy_str (PyObject *self) +{ + PyObject *result; + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + result = PyString_FromString (SYMBOL_PRINT_NAME (symbol)); + + return result; +} + +static PyObject * +sympy_get_symtab (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return symtab_to_symtab_object (SYMBOL_SYMTAB (symbol)); +} + +static PyObject * +sympy_get_name (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return PyString_FromString (SYMBOL_NATURAL_NAME (symbol)); +} + +static PyObject * +sympy_get_linkage_name (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return PyString_FromString (SYMBOL_LINKAGE_NAME (symbol)); +} + +static PyObject * +sympy_get_print_name (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return sympy_str (self); +} + +static PyObject * +sympy_get_addr_class (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return PyInt_FromLong (SYMBOL_CLASS (symbol)); +} + +static PyObject * +sympy_is_argument (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + return PyBool_FromLong (SYMBOL_IS_ARGUMENT (symbol)); +} + +static PyObject * +sympy_is_constant (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + enum address_class class; + + SYMPY_REQUIRE_VALID (self, symbol); + + class = SYMBOL_CLASS (symbol); + + return PyBool_FromLong (class == LOC_CONST || class == LOC_CONST_BYTES); +} + +static PyObject * +sympy_is_function (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + enum address_class class; + + SYMPY_REQUIRE_VALID (self, symbol); + + class = SYMBOL_CLASS (symbol); + + return PyBool_FromLong (class == LOC_BLOCK); +} + +static PyObject * +sympy_is_variable (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + enum address_class class; + + SYMPY_REQUIRE_VALID (self, symbol); + + class = SYMBOL_CLASS (symbol); + + return PyBool_FromLong (!SYMBOL_IS_ARGUMENT (symbol) + && (class == LOC_LOCAL || class == LOC_REGISTER + || class == LOC_STATIC || class == LOC_COMPUTED + || class == LOC_OPTIMIZED_OUT)); +} + +/* Implementation of gdb.Symbol.is_valid (self) -> Boolean. + Returns True if this Symbol still exists in GDB. */ + +static PyObject * +sympy_is_valid (PyObject *self, PyObject *args) +{ + struct symbol *symbol = NULL; + + symbol = symbol_object_to_symbol (self); + if (symbol == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Given a symbol, and a symbol_object that has previously been + allocated and initialized, populate the symbol_object with the + struct symbol data. Also, register the symbol_object life-cycle + with the life-cycle of the object file associated with this + symbol, if needed. */ +static void +set_symbol (symbol_object *obj, struct symbol *symbol) +{ + obj->symbol = symbol; + obj->prev = NULL; + if (SYMBOL_SYMTAB (symbol)) + { + obj->next = objfile_data (SYMBOL_SYMTAB (symbol)->objfile, + sympy_objfile_data_key); + + if (obj->next) + obj->next->prev = obj; + set_objfile_data (SYMBOL_SYMTAB (symbol)->objfile, + sympy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +/* Create a new symbol object (gdb.Symbol) that encapsulates the struct + symbol object from GDB. */ +PyObject * +symbol_to_symbol_object (struct symbol *sym) +{ + symbol_object *sym_obj; + + sym_obj = PyObject_New (symbol_object, &symbol_object_type); + if (sym_obj) + set_symbol (sym_obj, sym); + + return (PyObject *) sym_obj; +} + +/* Return the symbol that is wrapped by this symbol object. */ +struct symbol * +symbol_object_to_symbol (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &symbol_object_type)) + return NULL; + return ((symbol_object *) obj)->symbol; +} + +static void +sympy_dealloc (PyObject *obj) +{ + symbol_object *sym_obj = (symbol_object *) obj; + + if (sym_obj->prev) + sym_obj->prev->next = sym_obj->next; + else if (SYMBOL_SYMTAB (sym_obj->symbol)) + { + set_objfile_data (SYMBOL_SYMTAB (sym_obj->symbol)->objfile, + sympy_objfile_data_key, sym_obj->next); + } + if (sym_obj->next) + sym_obj->next->prev = sym_obj->prev; + sym_obj->symbol = NULL; +} + +/* Implementation of + gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this) + A tuple with 2 elements is always returned. The first is the symbol + object or None, the second is a boolean with the value of + is_a_field_of_this (see comment in lookup_symbol_in_language). */ + +PyObject * +gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw) +{ + int domain = VAR_DOMAIN, is_a_field_of_this = 0; + const char *name; + static char *keywords[] = { "name", "block", "domain", NULL }; + struct symbol *symbol; + PyObject *block_obj = NULL, *ret_tuple, *sym_obj, *bool_obj; + struct block *block = NULL; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!i", keywords, &name, + &block_object_type, &block_obj, &domain)) + return NULL; + + if (block_obj) + block = block_object_to_block (block_obj); + else + { + struct frame_info *selected_frame; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + selected_frame = get_selected_frame (_("No frame selected.")); + block = get_frame_block (selected_frame, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + } + + symbol = lookup_symbol (name, block, domain, &is_a_field_of_this); + + ret_tuple = PyTuple_New (2); + if (!ret_tuple) + return NULL; + + if (symbol) + { + sym_obj = symbol_to_symbol_object (symbol); + if (!sym_obj) + { + Py_DECREF (ret_tuple); + return NULL; + } + } + else + { + sym_obj = Py_None; + Py_INCREF (Py_None); + } + PyTuple_SET_ITEM (ret_tuple, 0, sym_obj); + + bool_obj = is_a_field_of_this? Py_True : Py_False; + Py_INCREF (bool_obj); + PyTuple_SET_ITEM (ret_tuple, 1, bool_obj); + + return ret_tuple; +} + +/* Implementation of + gdb.lookup_global_symbol (name [, domain]) -> symbol or None. */ + +PyObject * +gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw) +{ + int domain = VAR_DOMAIN; + const char *name; + static char *keywords[] = { "name", "domain", NULL }; + struct symbol *symbol; + PyObject *sym_obj; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &name, + &domain)) + return NULL; + + symbol = lookup_symbol_global (name, NULL, domain); + + if (symbol) + { + sym_obj = symbol_to_symbol_object (symbol); + if (!sym_obj) + return NULL; + } + else + { + sym_obj = Py_None; + Py_INCREF (Py_None); + } + + return sym_obj; +} + +/* This function is called when an objfile is about to be freed. + Invalidate the symbol as further actions on the symbol would result + in bad data. All access to obj->symbol should be gated by + SYMPY_REQUIRE_VALID which will raise an exception on invalid + symbols. */ +static void +del_objfile_symbols (struct objfile *objfile, void *datum) +{ + symbol_object *obj = datum; + while (obj) + { + symbol_object *next = obj->next; + + obj->symbol = NULL; + obj->next = NULL; + obj->prev = NULL; + + obj = next; + } +} + +void +gdbpy_initialize_symbols (void) +{ + if (PyType_Ready (&symbol_object_type) < 0) + return; + + /* Register an objfile "free" callback so we can properly + invalidate symbol when an object file that is about to be + deleted. */ + sympy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, del_objfile_symbols); + + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST", LOC_CONST); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_STATIC", LOC_STATIC); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGISTER", LOC_REGISTER); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_ARG", LOC_ARG); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REF_ARG", LOC_REF_ARG); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL", LOC_LOCAL); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_TYPEDEF", LOC_TYPEDEF); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LABEL", LOC_LABEL); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BLOCK", LOC_BLOCK); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST_BYTES", + LOC_CONST_BYTES); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNRESOLVED", + LOC_UNRESOLVED); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_OPTIMIZED_OUT", + LOC_OPTIMIZED_OUT); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED", LOC_COMPUTED); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM_ADDR", + LOC_REGPARM_ADDR); + PyModule_AddIntConstant (gdb_module, "SYMBOL_UNDEF_DOMAIN", UNDEF_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_VAR_DOMAIN", VAR_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_STRUCT_DOMAIN", STRUCT_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LABEL_DOMAIN", LABEL_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_VARIABLES_DOMAIN", + VARIABLES_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_FUNCTIONS_DOMAIN", + FUNCTIONS_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_TYPES_DOMAIN", TYPES_DOMAIN); + + Py_INCREF (&symbol_object_type); + PyModule_AddObject (gdb_module, "Symbol", (PyObject *) &symbol_object_type); +} + + + +static PyGetSetDef symbol_object_getset[] = { + { "symtab", sympy_get_symtab, NULL, + "Symbol table in which the symbol appears.", NULL }, + { "name", sympy_get_name, NULL, + "Name of the symbol, as it appears in the source code.", NULL }, + { "linkage_name", sympy_get_linkage_name, NULL, + "Name of the symbol, as used by the linker (i.e., may be mangled).", + NULL }, + { "print_name", sympy_get_print_name, NULL, + "Name of the symbol in a form suitable for output.\n\ +This is either name or linkage_name, depending on whether the user asked GDB\n\ +to display demangled or mangled names.", NULL }, + { "addr_class", sympy_get_addr_class, NULL, "Address class of the symbol." }, + { "is_argument", sympy_is_argument, NULL, + "True if the symbol is an argument of a function." }, + { "is_constant", sympy_is_constant, NULL, + "True if the symbol is a constant." }, + { "is_function", sympy_is_function, NULL, + "True if the symbol is a function or method." }, + { "is_variable", sympy_is_variable, NULL, + "True if the symbol is a variable." }, + { NULL } /* Sentinel */ +}; + +static PyMethodDef symbol_object_methods[] = { + { "is_valid", sympy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this symbol is valid, false if not." }, + {NULL} /* Sentinel */ +}; + +PyTypeObject symbol_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symbol", /*tp_name*/ + sizeof (symbol_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + sympy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + sympy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symbol object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + symbol_object_methods, /*tp_methods */ + 0, /*tp_members */ + symbol_object_getset /*tp_getset */ +}; diff --git a/contrib/gdb-7/gdb/python/py-symtab.c b/contrib/gdb-7/gdb/python/py-symtab.c new file mode 100644 index 0000000000..107cdec6e0 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-symtab.c @@ -0,0 +1,564 @@ +/* Python interface to symbol tables. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "charset.h" +#include "symtab.h" +#include "source.h" +#include "python-internal.h" +#include "objfiles.h" + +typedef struct stpy_symtab_object { + PyObject_HEAD + /* The GDB Symbol table structure. */ + struct symtab *symtab; + /* A symtab object is associated with an objfile, so keep track with + a doubly-linked list, rooted in the objfile. This allows + invalidation of the underlying struct symtab when the objfile is + deleted. */ + struct stpy_symtab_object *prev; + struct stpy_symtab_object *next; +} symtab_object; + +static PyTypeObject symtab_object_type; +static const struct objfile_data *stpy_objfile_data_key; + +/* Require a valid symbol table. All access to symtab_object->symtab + should be gated by this call. */ +#define STPY_REQUIRE_VALID(symtab_obj, symtab) \ + do { \ + symtab = symtab_object_to_symtab (symtab_obj); \ + if (symtab == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Symbol Table is invalid.")); \ + return NULL; \ + } \ + } while (0) + +typedef struct salpy_sal_object { + PyObject_HEAD + /* The GDB Symbol table structure. */ + symtab_object *symtab; + /* The GDB Symbol table and line structure. */ + struct symtab_and_line *sal; + /* A Symtab and line object is associated with an objfile, so keep + track with a doubly-linked list, rooted in the objfile. This + allows invalidation of the underlying struct symtab_and_line + when the objfile is deleted. */ + struct salpy_sal_object *prev; + struct salpy_sal_object *next; +} sal_object; + +static PyTypeObject sal_object_type; +static const struct objfile_data *salpy_objfile_data_key; + +/* Require a valid symbol table and line object. All access to + sal_object->sal should be gated by this call. */ +#define SALPY_REQUIRE_VALID(sal_obj, sal) \ + do { \ + sal = sal_object_to_symtab_and_line (sal_obj); \ + if (sal == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Symbol Table and Line is invalid.")); \ + return NULL; \ + } \ + } while (0) + +static PyObject * +stpy_str (PyObject *self) +{ + PyObject *result; + struct symtab *symtab = NULL; + + STPY_REQUIRE_VALID (self, symtab); + + result = PyString_FromString (symtab->filename); + + return result; +} + +static PyObject * +stpy_get_filename (PyObject *self, void *closure) +{ + PyObject *str_obj; + struct symtab *symtab = NULL; + + STPY_REQUIRE_VALID (self, symtab); + + str_obj = PyString_Decode (symtab->filename, + strlen (symtab->filename), + host_charset (), NULL); + return str_obj; +} + +static PyObject * +stpy_get_objfile (PyObject *self, void *closure) +{ + struct symtab *symtab = NULL; + PyObject *result; + + STPY_REQUIRE_VALID (self, symtab); + + result = objfile_to_objfile_object (symtab->objfile); + Py_XINCREF (result); + return result; +} + +static PyObject * +stpy_fullname (PyObject *self, PyObject *args) +{ + char *fullname; + struct symtab *symtab = NULL; + + STPY_REQUIRE_VALID (self, symtab); + + fullname = symtab_to_fullname (symtab); + if (fullname) + return PyString_Decode (fullname, strlen (fullname), + host_charset (), NULL); + + Py_RETURN_NONE; +} + +/* Implementation of gdb.Symtab.is_valid (self) -> Boolean. + Returns True if this Symbol table still exists in GDB. */ + +static PyObject * +stpy_is_valid (PyObject *self, PyObject *args) +{ + struct symtab *symtab = NULL; + + symtab = symtab_object_to_symtab (self); + if (symtab == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +static PyObject * +salpy_str (PyObject *self) +{ + char *s, *filename; + sal_object *sal_obj; + PyObject *result; + struct symtab_and_line *sal = NULL; + + SALPY_REQUIRE_VALID (self, sal); + + sal_obj = (sal_object *) self; + filename = (sal_obj->symtab == (symtab_object *) Py_None) + ? "" : sal_obj->symtab->symtab->filename; + + s = xstrprintf ("symbol and line for %s, line %d", filename, + sal->line); + + result = PyString_FromString (s); + xfree (s); + + return result; +} + +static void +stpy_dealloc (PyObject *obj) +{ + symtab_object *symtab = (symtab_object *) obj; + + if (symtab->prev) + symtab->prev->next = symtab->next; + else if (symtab->symtab) + { + set_objfile_data (symtab->symtab->objfile, + stpy_objfile_data_key, symtab->next); + } + if (symtab->next) + symtab->next->prev = symtab->prev; + symtab->symtab = NULL; +} + + +static PyObject * +salpy_get_pc (PyObject *self, void *closure) +{ + struct symtab_and_line *sal = NULL; + + SALPY_REQUIRE_VALID (self, sal); + + return gdb_py_long_from_ulongest (sal->pc); +} + +static PyObject * +salpy_get_line (PyObject *self, void *closure) +{ + struct symtab_and_line *sal = NULL; + + SALPY_REQUIRE_VALID (self, sal); + + return PyInt_FromLong (sal->line); +} + +static PyObject * +salpy_get_symtab (PyObject *self, void *closure) +{ + struct symtab_and_line *sal; + sal_object *self_sal = (sal_object *) self; + + SALPY_REQUIRE_VALID (self, sal); + + Py_INCREF (self_sal->symtab); + + return (PyObject *) self_sal->symtab; +} + +/* Implementation of gdb.Symtab_and_line.is_valid (self) -> Boolean. + Returns True if this Symbol table and line object still exists GDB. */ + +static PyObject * +salpy_is_valid (PyObject *self, PyObject *args) +{ + struct symtab_and_line *sal; + + sal = sal_object_to_symtab_and_line (self); + if (sal == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +static void +salpy_dealloc (PyObject *self) +{ + sal_object *self_sal = (sal_object *) self; + + if (self_sal->prev) + self_sal->prev->next = self_sal->next; + else if (self_sal->symtab != (symtab_object * ) Py_None) + set_objfile_data (self_sal->symtab->symtab->objfile, + salpy_objfile_data_key, self_sal->next); + + if (self_sal->next) + self_sal->next->prev = self_sal->prev; + + Py_DECREF (self_sal->symtab); + xfree (self_sal->sal); + self_sal->ob_type->tp_free (self); +} + +/* Given a sal, and a sal_object that has previously been allocated + and initialized, populate the sal_object with the struct sal data. + Also, register the sal_object life-cycle with the life-cycle of the + object file associated with this sal, if needed. If a failure + occurs during the sal population, this function will return + NULL. */ +static int +set_sal (sal_object *sal_obj, struct symtab_and_line sal) +{ + symtab_object *symtab_obj; + + if (sal.symtab) + { + symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab); + /* If a symtab existed in the sal, but it cannot be duplicated, + we exit. */ + if (symtab_obj == NULL) + return 0; + } + else + { + symtab_obj = (symtab_object *) Py_None; + Py_INCREF (Py_None); + } + + sal_obj->sal = xmemdup (&sal, sizeof (struct symtab_and_line), + sizeof (struct symtab_and_line)); + sal_obj->symtab = symtab_obj; + sal_obj->prev = NULL; + + /* If the SAL does not have a symtab, we do not add it to the + objfile cleanup observer linked list. */ + if (sal_obj->symtab != (symtab_object *)Py_None) + { + sal_obj->next = objfile_data (sal_obj->symtab->symtab->objfile, + salpy_objfile_data_key); + if (sal_obj->next) + sal_obj->next->prev = sal_obj; + + set_objfile_data (sal_obj->symtab->symtab->objfile, + salpy_objfile_data_key, sal_obj); + } + else + sal_obj->next = NULL; + + return 1; +} + +/* Given a symtab, and a symtab_object that has previously been + allocated and initialized, populate the symtab_object with the + struct symtab data. Also, register the symtab_object life-cycle + with the life-cycle of the object file associated with this + symtab, if needed. */ +static void +set_symtab (symtab_object *obj, struct symtab *symtab) +{ + obj->symtab = symtab; + obj->prev = NULL; + if (symtab) + { + obj->next = objfile_data (symtab->objfile, stpy_objfile_data_key); + if (obj->next) + obj->next->prev = obj; + set_objfile_data (symtab->objfile, stpy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +/* Create a new symbol table (gdb.Symtab) object that encapsulates the + symtab structure from GDB. */ +PyObject * +symtab_to_symtab_object (struct symtab *symtab) +{ + symtab_object *symtab_obj; + + symtab_obj = PyObject_New (symtab_object, &symtab_object_type); + if (symtab_obj) + set_symtab (symtab_obj, symtab); + + return (PyObject *) symtab_obj; +} + +/* Create a new symtab and line (gdb.Symtab_and_line) object + that encapsulates the symtab_and_line structure from GDB. */ +PyObject * +symtab_and_line_to_sal_object (struct symtab_and_line sal) + +{ + sal_object *sal_obj; + int success = 0; + + sal_obj = PyObject_New (sal_object, &sal_object_type); + if (sal_obj) + { + success = set_sal (sal_obj, sal); + if (!success) + { + Py_DECREF (sal_obj); + return NULL; + } + } + + return (PyObject *) sal_obj; +} + +/* Return struct symtab_and_line reference that is wrapped by this + object. */ +struct symtab_and_line * +sal_object_to_symtab_and_line (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &sal_object_type)) + return NULL; + return ((sal_object *) obj)->sal; +} + +/* Return struct symtab reference that is wrapped by this object. */ +struct symtab * +symtab_object_to_symtab (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &symtab_object_type)) + return NULL; + return ((symtab_object *) obj)->symtab; +} + +/* This function is called when an objfile is about to be freed. + Invalidate the symbol table as further actions on the symbol table + would result in bad data. All access to obj->symtab should be + gated by STPY_REQUIRE_VALID which will raise an exception on + invalid symbol tables. */ +static void +del_objfile_symtab (struct objfile *objfile, void *datum) +{ + symtab_object *obj = datum; + + while (obj) + { + symtab_object *next = obj->next; + + obj->symtab = NULL; + obj->next = NULL; + obj->prev = NULL; + obj = next; + } +} + +/* This function is called when an objfile is about to be freed. + Invalidate the sal object as further actions on the sal + would result in bad data. All access to obj->sal should be + gated by SALPY_REQUIRE_VALID which will raise an exception on + invalid symbol table and line objects. */ +static void +del_objfile_sal (struct objfile *objfile, void *datum) +{ + sal_object *obj = datum; + + while (obj) + { + sal_object *next = obj->next; + + obj->symtab = NULL; + obj->next = NULL; + obj->prev = NULL; + xfree (obj->sal); + obj->sal = NULL; + + obj = next; + } +} + +void +gdbpy_initialize_symtabs (void) +{ + symtab_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&symtab_object_type) < 0) + return; + + sal_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&sal_object_type) < 0) + return; + + /* Register an objfile "free" callback so we can properly + invalidate symbol tables, and symbol table and line data + structures when an object file that is about to be + deleted. */ + stpy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, del_objfile_symtab); + salpy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, del_objfile_sal); + + Py_INCREF (&symtab_object_type); + PyModule_AddObject (gdb_module, "Symtab", + (PyObject *) &symtab_object_type); + + Py_INCREF (&sal_object_type); + PyModule_AddObject (gdb_module, "Symtab_and_line", + (PyObject *) &sal_object_type); +} + + + +static PyGetSetDef symtab_object_getset[] = { + { "filename", stpy_get_filename, NULL, + "The symbol table's source filename.", NULL }, + { "objfile", stpy_get_objfile, NULL, "The symtab's objfile.", + NULL }, + {NULL} /* Sentinel */ +}; + +static PyMethodDef symtab_object_methods[] = { + { "is_valid", stpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this symbol table is valid, false if not." }, + { "fullname", stpy_fullname, METH_NOARGS, + "fullname () -> String.\n\ +Return the symtab's full source filename." }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject symtab_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symtab", /*tp_name*/ + sizeof (symtab_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + stpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + stpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symtab object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + symtab_object_methods, /*tp_methods */ + 0, /*tp_members */ + symtab_object_getset /*tp_getset */ +}; + +static PyGetSetDef sal_object_getset[] = { + { "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL }, + { "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL }, + { "line", salpy_get_line, NULL, + "Return the symtab_and_line's line.", NULL }, + {NULL} /* Sentinel */ +}; + +static PyMethodDef sal_object_methods[] = { + { "is_valid", salpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this symbol table and line is valid, false if not." }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject sal_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symtab_and_line", /*tp_name*/ + sizeof (sal_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + salpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + salpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symtab_and_line object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + sal_object_methods, /*tp_methods */ + 0, /*tp_members */ + sal_object_getset /*tp_getset */ +}; diff --git a/contrib/gdb-7/gdb/python/py-threadevent.c b/contrib/gdb-7/gdb/python/py-threadevent.c new file mode 100644 index 0000000000..7963412e08 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-threadevent.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "py-event.h" + +/* thread events can either be thread specific or process wide. If gdb is + running in non-stop mode then the event is thread specific, otherwise + it is process wide. + This function returns the currently stopped thread in non-stop mode and + Py_None otherwise. */ + +static PyObject * +get_event_thread (void) +{ + PyObject *thread = NULL; + + if (non_stop) + thread = (PyObject *) find_thread_object (inferior_ptid); + else + thread = Py_None; + + if (!thread) + { + PyErr_SetString (PyExc_RuntimeError, "Could not find event thread"); + return NULL; + } + + Py_INCREF (thread); + + return thread; +} + +PyObject * +create_thread_event_object (PyTypeObject *py_type) +{ + PyObject *thread = NULL; + PyObject *thread_event_obj = NULL; + + thread_event_obj = create_event_object (py_type); + if (!thread_event_obj) + goto fail; + + thread = get_event_thread (); + if (!thread) + goto fail; + + if (evpy_add_attribute (thread_event_obj, + "inferior_thread", + thread) < 0) + goto fail; + + return thread_event_obj; + + fail: + Py_XDECREF (thread_event_obj); + return NULL; +} + +GDBPY_NEW_EVENT_TYPE (thread, + "gdb.ThreadEvent", + "ThreadEvent", + "GDB thread event object", + event_object_type, + /*no qual*/); diff --git a/contrib/gdb-7/gdb/python/py-type.c b/contrib/gdb-7/gdb/python/py-type.c new file mode 100644 index 0000000000..c010420ee3 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-type.c @@ -0,0 +1,1215 @@ +/* Python interface to types. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbtypes.h" +#include "cp-support.h" +#include "demangle.h" +#include "objfiles.h" +#include "language.h" +#include "vec.h" +#include "bcache.h" + +typedef struct pyty_type_object +{ + PyObject_HEAD + struct type *type; + + /* If a Type object is associated with an objfile, it is kept on a + doubly-linked list, rooted in the objfile. This lets us copy the + underlying struct type when the objfile is deleted. */ + struct pyty_type_object *prev; + struct pyty_type_object *next; +} type_object; + +static PyTypeObject type_object_type; + +/* A Field object. */ +typedef struct pyty_field_object +{ + PyObject_HEAD + + /* Dictionary holding our attributes. */ + PyObject *dict; +} field_object; + +static PyTypeObject field_object_type; + +/* This is used to initialize various gdb.TYPE_ constants. */ +struct pyty_code +{ + /* The code. */ + enum type_code code; + /* The name. */ + const char *name; +}; + +#define ENTRY(X) { X, #X } + +static struct pyty_code pyty_codes[] = +{ + ENTRY (TYPE_CODE_PTR), + ENTRY (TYPE_CODE_ARRAY), + ENTRY (TYPE_CODE_STRUCT), + ENTRY (TYPE_CODE_UNION), + ENTRY (TYPE_CODE_ENUM), + ENTRY (TYPE_CODE_FLAGS), + ENTRY (TYPE_CODE_FUNC), + ENTRY (TYPE_CODE_INT), + ENTRY (TYPE_CODE_FLT), + ENTRY (TYPE_CODE_VOID), + ENTRY (TYPE_CODE_SET), + ENTRY (TYPE_CODE_RANGE), + ENTRY (TYPE_CODE_STRING), + ENTRY (TYPE_CODE_BITSTRING), + ENTRY (TYPE_CODE_ERROR), + ENTRY (TYPE_CODE_METHOD), + ENTRY (TYPE_CODE_METHODPTR), + ENTRY (TYPE_CODE_MEMBERPTR), + ENTRY (TYPE_CODE_REF), + ENTRY (TYPE_CODE_CHAR), + ENTRY (TYPE_CODE_BOOL), + ENTRY (TYPE_CODE_COMPLEX), + ENTRY (TYPE_CODE_TYPEDEF), + ENTRY (TYPE_CODE_NAMESPACE), + ENTRY (TYPE_CODE_DECFLOAT), + ENTRY (TYPE_CODE_INTERNAL_FUNCTION), + { TYPE_CODE_UNDEF, NULL } +}; + + + +static void +field_dealloc (PyObject *obj) +{ + field_object *f = (field_object *) obj; + + Py_XDECREF (f->dict); + f->ob_type->tp_free (obj); +} + +static PyObject * +field_new (void) +{ + field_object *result = PyObject_New (field_object, &field_object_type); + + if (result) + { + result->dict = PyDict_New (); + if (!result->dict) + { + Py_DECREF (result); + result = NULL; + } + } + return (PyObject *) result; +} + + + +/* Return the code for this type. */ +static PyObject * +typy_get_code (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + + return PyInt_FromLong (TYPE_CODE (type)); +} + +/* Helper function for typy_fields which converts a single field to a + dictionary. Returns NULL on error. */ +static PyObject * +convert_field (struct type *type, int field) +{ + PyObject *result = field_new (); + PyObject *arg; + + if (!result) + return NULL; + + if (!field_is_static (&TYPE_FIELD (type, field))) + { + arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field)); + if (!arg) + goto fail; + + if (PyObject_SetAttrString (result, "bitpos", arg) < 0) + goto failarg; + } + + if (TYPE_FIELD_NAME (type, field)) + arg = PyString_FromString (TYPE_FIELD_NAME (type, field)); + else + { + arg = Py_None; + Py_INCREF (arg); + } + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "name", arg) < 0) + goto failarg; + + arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False; + Py_INCREF (arg); + if (PyObject_SetAttrString (result, "artificial", arg) < 0) + goto failarg; + + if (TYPE_CODE (type) == TYPE_CODE_CLASS) + arg = field < TYPE_N_BASECLASSES (type) ? Py_True : Py_False; + else + arg = Py_False; + Py_INCREF (arg); + if (PyObject_SetAttrString (result, "is_base_class", arg) < 0) + goto failarg; + + arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field)); + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "bitsize", arg) < 0) + goto failarg; + + /* A field can have a NULL type in some situations. */ + if (TYPE_FIELD_TYPE (type, field) == NULL) + { + arg = Py_None; + Py_INCREF (arg); + } + else + arg = type_to_type_object (TYPE_FIELD_TYPE (type, field)); + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "type", arg) < 0) + goto failarg; + + return result; + + failarg: + Py_DECREF (arg); + fail: + Py_DECREF (result); + return NULL; +} + +/* Return a sequence of all fields. Each field is a dictionary with + some pre-defined keys. */ +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + PyObject *result; + int i; + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + CHECK_TYPEDEF (type); + } + GDB_PY_HANDLE_EXCEPTION (except); + + /* We would like to make a tuple here, make fields immutable, and + then memoize the result (and perhaps make Field.type() lazy). + However, that can lead to cycles. */ + result = PyList_New (0); + + for (i = 0; i < TYPE_NFIELDS (type); ++i) + { + PyObject *dict = convert_field (type, i); + + if (!dict) + { + Py_DECREF (result); + return NULL; + } + if (PyList_Append (result, dict)) + { + Py_DECREF (dict); + Py_DECREF (result); + return NULL; + } + } + + return result; +} + +/* Return the type's tag, or None. */ +static PyObject * +typy_get_tag (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + + if (!TYPE_TAG_NAME (type)) + Py_RETURN_NONE; + return PyString_FromString (TYPE_TAG_NAME (type)); +} + +/* Return the type, stripped of typedefs. */ +static PyObject * +typy_strip_typedefs (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + + return type_to_type_object (check_typedef (type)); +} + +/* Return an array type. */ + +static PyObject * +typy_array (PyObject *self, PyObject *args) +{ + long n1, n2; + PyObject *n2_obj = NULL; + struct type *array = NULL; + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "l|O", &n1, &n2_obj)) + return NULL; + + if (n2_obj) + { + if (!PyInt_Check (n2_obj)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Array bound must be an integer")); + return NULL; + } + + if (! gdb_py_int_as_long (n2_obj, &n2)) + return NULL; + } + else + { + n2 = n1; + n1 = 0; + } + + if (n2 < n1) + { + PyErr_SetString (PyExc_ValueError, + _("Array length must not be negative")); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + array = lookup_array_range_type (type, n1, n2); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (array); +} + +/* Return a Type object which represents a pointer to SELF. */ +static PyObject * +typy_pointer (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = lookup_pointer_type (type); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return the range of a type represented by SELF. The return type is + a tuple. The first element of the tuple contains the low bound, + while the second element of the tuple contains the high bound. */ +static PyObject * +typy_range (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + PyObject *result; + PyObject *low_bound = NULL, *high_bound = NULL; + /* Initialize these to appease GCC warnings. */ + LONGEST low = 0, high = 0; + + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRING + && TYPE_CODE (type) != TYPE_CODE_RANGE) + { + PyErr_SetString (PyExc_RuntimeError, + _("This type does not have a range.")); + return NULL; + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_STRING: + low = TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); + high = TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (type)); + break; + case TYPE_CODE_RANGE: + low = TYPE_LOW_BOUND (type); + high = TYPE_HIGH_BOUND (type); + break; + } + + low_bound = PyLong_FromLong (low); + if (!low_bound) + goto failarg; + + high_bound = PyLong_FromLong (high); + if (!high_bound) + goto failarg; + + result = PyTuple_New (2); + if (!result) + goto failarg; + + if (PyTuple_SetItem (result, 0, low_bound) != 0) + { + Py_DECREF (result); + goto failarg; + } + if (PyTuple_SetItem (result, 1, high_bound) != 0) + { + Py_DECREF (high_bound); + Py_DECREF (result); + return NULL; + } + return result; + + failarg: + Py_XDECREF (high_bound); + Py_XDECREF (low_bound); + return NULL; +} + +/* Return a Type object which represents a reference to SELF. */ +static PyObject * +typy_reference (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = lookup_reference_type (type); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return a Type object which represents the target type of SELF. */ +static PyObject * +typy_target (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + + if (!TYPE_TARGET_TYPE (type)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Type does not have a target.")); + return NULL; + } + + return type_to_type_object (TYPE_TARGET_TYPE (type)); +} + +/* Return a const-qualified type variant. */ +static PyObject * +typy_const (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (1, 0, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return a volatile-qualified type variant. */ +static PyObject * +typy_volatile (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (0, 1, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return an unqualified type variant. */ +static PyObject * +typy_unqualified (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (0, 0, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return the size of the type represented by SELF, in bytes. */ +static PyObject * +typy_get_sizeof (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + check_typedef (type); + } + /* Ignore exceptions. */ + + return PyLong_FromLong (TYPE_LENGTH (type)); +} + +static struct type * +typy_lookup_typename (char *type_name, struct block *block) +{ + struct type *type = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (!strncmp (type_name, "struct ", 7)) + type = lookup_struct (type_name + 7, NULL); + else if (!strncmp (type_name, "union ", 6)) + type = lookup_union (type_name + 6, NULL); + else if (!strncmp (type_name, "enum ", 5)) + type = lookup_enum (type_name + 5, NULL); + else + type = lookup_typename (python_language, python_gdbarch, + type_name, block, 0); + } + if (except.reason < 0) + { + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return NULL; + } + + return type; +} + +static struct type * +typy_lookup_type (struct demangle_component *demangled, + struct block *block) +{ + struct type *type; + char *type_name; + enum demangle_component_type demangled_type; + + /* Save the type: typy_lookup_type() may (indirectly) overwrite + memory pointed by demangled. */ + demangled_type = demangled->type; + + if (demangled_type == DEMANGLE_COMPONENT_POINTER + || demangled_type == DEMANGLE_COMPONENT_REFERENCE + || demangled_type == DEMANGLE_COMPONENT_CONST + || demangled_type == DEMANGLE_COMPONENT_VOLATILE) + { + type = typy_lookup_type (demangled->u.s_binary.left, block); + if (! type) + return NULL; + + switch (demangled_type) + { + case DEMANGLE_COMPONENT_REFERENCE: + return lookup_reference_type (type); + case DEMANGLE_COMPONENT_POINTER: + return lookup_pointer_type (type); + case DEMANGLE_COMPONENT_CONST: + return make_cv_type (1, 0, type, NULL); + case DEMANGLE_COMPONENT_VOLATILE: + return make_cv_type (0, 1, type, NULL); + } + } + + type_name = cp_comp_to_string (demangled, 10); + type = typy_lookup_typename (type_name, block); + xfree (type_name); + + return type; +} + +/* This is a helper function for typy_template_argument that is used + when the type does not have template symbols attached. It works by + parsing the type name. This happens with compilers, like older + versions of GCC, that do not emit DW_TAG_template_*. */ + +static PyObject * +typy_legacy_template_argument (struct type *type, struct block *block, + int argno) +{ + int i; + struct demangle_component *demangled; + const char *err; + struct type *argtype; + + if (TYPE_NAME (type) == NULL) + { + PyErr_SetString (PyExc_RuntimeError, _("Null type name.")); + return NULL; + } + + /* Note -- this is not thread-safe. */ + demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err); + if (! demangled) + { + PyErr_SetString (PyExc_RuntimeError, err); + return NULL; + } + + /* Strip off component names. */ + while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME + || demangled->type == DEMANGLE_COMPONENT_LOCAL_NAME) + demangled = demangled->u.s_binary.right; + + if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE) + { + PyErr_SetString (PyExc_RuntimeError, _("Type is not a template.")); + return NULL; + } + + /* Skip from the template to the arguments. */ + demangled = demangled->u.s_binary.right; + + for (i = 0; demangled && i < argno; ++i) + demangled = demangled->u.s_binary.right; + + if (! demangled) + { + PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."), + argno); + return NULL; + } + + argtype = typy_lookup_type (demangled->u.s_binary.left, block); + if (! argtype) + return NULL; + + return type_to_type_object (argtype); +} + +static PyObject * +typy_template_argument (PyObject *self, PyObject *args) +{ + int argno; + struct type *type = ((type_object *) self)->type; + struct block *block = NULL; + PyObject *block_obj = NULL; + struct symbol *sym; + struct value *val = NULL; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "i|O", &argno, &block_obj)) + return NULL; + + if (block_obj) + { + block = block_object_to_block (block_obj); + if (! block) + { + PyErr_SetString (PyExc_RuntimeError, + _("Second argument must be block.")); + return NULL; + } + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = check_typedef (type); + if (TYPE_CODE (type) == TYPE_CODE_REF) + type = check_typedef (TYPE_TARGET_TYPE (type)); + } + GDB_PY_HANDLE_EXCEPTION (except); + + /* We might not have DW_TAG_template_*, so try to parse the type's + name. This is inefficient if we do not have a template type -- + but that is going to wind up as an error anyhow. */ + if (! TYPE_N_TEMPLATE_ARGUMENTS (type)) + return typy_legacy_template_argument (type, block, argno); + + if (argno >= TYPE_N_TEMPLATE_ARGUMENTS (type)) + { + PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."), + argno); + return NULL; + } + + sym = TYPE_TEMPLATE_ARGUMENT (type, argno); + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) + return type_to_type_object (SYMBOL_TYPE (sym)); + else if (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT) + { + PyErr_Format (PyExc_RuntimeError, + _("Template argument is optimized out")); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + val = value_of_variable (sym, block); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (val); +} + +static PyObject * +typy_str (PyObject *self) +{ + volatile struct gdb_exception except; + char *thetype = NULL; + long length = 0; + PyObject *result; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct cleanup *old_chain; + struct ui_file *stb; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + type_print (type_object_to_type (self), "", stb, -1); + + thetype = ui_file_xstrdup (stb, &length); + do_cleanups (old_chain); + } + if (except.reason < 0) + { + xfree (thetype); + GDB_PY_HANDLE_EXCEPTION (except); + } + + result = PyUnicode_Decode (thetype, length, host_charset (), NULL); + xfree (thetype); + + return result; +} + +/* An entry in the type-equality bcache. */ + +typedef struct type_equality_entry +{ + struct type *type1, *type2; +} type_equality_entry_d; + +DEF_VEC_O (type_equality_entry_d); + +/* A helper function to compare two strings. Returns 1 if they are + the same, 0 otherwise. Handles NULLs properly. */ + +static int +compare_strings (const char *s, const char *t) +{ + if (s == NULL && t != NULL) + return 0; + else if (s != NULL && t == NULL) + return 0; + else if (s == NULL && t== NULL) + return 1; + return strcmp (s, t) == 0; +} + +/* A helper function for typy_richcompare that checks two types for + "deep" equality. Returns Py_EQ if the types are considered the + same, Py_NE otherwise. */ + +static int +check_types_equal (struct type *type1, struct type *type2, + VEC (type_equality_entry_d) **worklist) +{ + CHECK_TYPEDEF (type1); + CHECK_TYPEDEF (type2); + + if (type1 == type2) + return Py_EQ; + + if (TYPE_CODE (type1) != TYPE_CODE (type2) + || TYPE_LENGTH (type1) != TYPE_LENGTH (type2) + || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2) + || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2) + || TYPE_VARARGS (type1) != TYPE_VARARGS (type2) + || TYPE_VECTOR (type1) != TYPE_VECTOR (type2) + || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2) + || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2) + || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2)) + return Py_NE; + + if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2))) + return Py_NE; + if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2))) + return Py_NE; + + if (TYPE_CODE (type1) == TYPE_CODE_RANGE) + { + if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2), + sizeof (*TYPE_RANGE_DATA (type1))) != 0) + return Py_NE; + } + else + { + int i; + + for (i = 0; i < TYPE_NFIELDS (type1); ++i) + { + const struct field *field1 = &TYPE_FIELD (type1, i); + const struct field *field2 = &TYPE_FIELD (type2, i); + struct type_equality_entry entry; + + if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2) + || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2) + || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2)) + return Py_NE; + if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2))) + return Py_NE; + switch (FIELD_LOC_KIND (*field1)) + { + case FIELD_LOC_KIND_BITPOS: + if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2)) + return Py_NE; + break; + case FIELD_LOC_KIND_PHYSADDR: + if (FIELD_STATIC_PHYSADDR (*field1) + != FIELD_STATIC_PHYSADDR (*field2)) + return Py_NE; + break; + case FIELD_LOC_KIND_PHYSNAME: + if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1), + FIELD_STATIC_PHYSNAME (*field2))) + return Py_NE; + break; + } + + entry.type1 = FIELD_TYPE (*field1); + entry.type2 = FIELD_TYPE (*field2); + VEC_safe_push (type_equality_entry_d, *worklist, &entry); + } + } + + if (TYPE_TARGET_TYPE (type1) != NULL) + { + struct type_equality_entry entry; + int added; + + if (TYPE_TARGET_TYPE (type2) == NULL) + return Py_NE; + + entry.type1 = TYPE_TARGET_TYPE (type1); + entry.type2 = TYPE_TARGET_TYPE (type2); + VEC_safe_push (type_equality_entry_d, *worklist, &entry); + } + else if (TYPE_TARGET_TYPE (type2) != NULL) + return Py_NE; + + return Py_EQ; +} + +/* Check types on a worklist for equality. Returns Py_NE if any pair + is not equal, Py_EQ if they are all considered equal. */ + +static int +check_types_worklist (VEC (type_equality_entry_d) **worklist, + struct bcache *cache) +{ + while (!VEC_empty (type_equality_entry_d, *worklist)) + { + struct type_equality_entry entry; + int added; + + entry = *VEC_last (type_equality_entry_d, *worklist); + VEC_pop (type_equality_entry_d, *worklist); + + /* If the type pair has already been visited, we know it is + ok. */ + bcache_full (&entry, sizeof (entry), cache, &added); + if (!added) + continue; + + if (check_types_equal (entry.type1, entry.type2, worklist) == Py_NE) + return Py_NE; + } + + return Py_EQ; +} + +/* Implement the richcompare method. */ + +static PyObject * +typy_richcompare (PyObject *self, PyObject *other, int op) +{ + int result = Py_NE; + struct type *type1 = type_object_to_type (self); + struct type *type2 = type_object_to_type (other); + volatile struct gdb_exception except; + + /* We can only compare ourselves to another Type object, and only + for equality or inequality. */ + if (type2 == NULL || (op != Py_EQ && op != Py_NE)) + { + Py_INCREF (Py_NotImplemented); + return Py_NotImplemented; + } + + if (type1 == type2) + result = Py_EQ; + else + { + struct bcache *cache; + VEC (type_equality_entry_d) *worklist = NULL; + struct type_equality_entry entry; + + cache = bcache_xmalloc (NULL, NULL); + + entry.type1 = type1; + entry.type2 = type2; + VEC_safe_push (type_equality_entry_d, worklist, &entry); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + result = check_types_worklist (&worklist, cache); + } + if (except.reason < 0) + result = Py_NE; + + bcache_xfree (cache); + VEC_free (type_equality_entry_d, worklist); + } + + if (op == result) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + + + +static const struct objfile_data *typy_objfile_data_key; + +static void +save_objfile_types (struct objfile *objfile, void *datum) +{ + type_object *obj = datum; + htab_t copied_types; + struct cleanup *cleanup; + + /* This prevents another thread from freeing the objects we're + operating on. */ + cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); + + copied_types = create_copied_types_hash (objfile); + + while (obj) + { + type_object *next = obj->next; + + htab_empty (copied_types); + + obj->type = copy_type_recursive (objfile, obj->type, copied_types); + + obj->next = NULL; + obj->prev = NULL; + + obj = next; + } + + htab_delete (copied_types); + + do_cleanups (cleanup); +} + +static void +set_type (type_object *obj, struct type *type) +{ + obj->type = type; + obj->prev = NULL; + if (type && TYPE_OBJFILE (type)) + { + struct objfile *objfile = TYPE_OBJFILE (type); + + obj->next = objfile_data (objfile, typy_objfile_data_key); + if (obj->next) + obj->next->prev = obj; + set_objfile_data (objfile, typy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +static void +typy_dealloc (PyObject *obj) +{ + type_object *type = (type_object *) obj; + + if (type->prev) + type->prev->next = type->next; + else if (type->type && TYPE_OBJFILE (type->type)) + { + /* Must reset head of list. */ + struct objfile *objfile = TYPE_OBJFILE (type->type); + + if (objfile) + set_objfile_data (objfile, typy_objfile_data_key, type->next); + } + if (type->next) + type->next->prev = type->prev; + + type->ob_type->tp_free (type); +} + +/* Create a new Type referring to TYPE. */ +PyObject * +type_to_type_object (struct type *type) +{ + type_object *type_obj; + + type_obj = PyObject_New (type_object, &type_object_type); + if (type_obj) + set_type (type_obj, type); + + return (PyObject *) type_obj; +} + +struct type * +type_object_to_type (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &type_object_type)) + return NULL; + return ((type_object *) obj)->type; +} + + + +/* Implementation of gdb.lookup_type. */ +PyObject * +gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw) +{ + static char *keywords[] = { "name", "block", NULL }; + char *type_name = NULL; + struct type *type = NULL; + PyObject *block_obj = NULL; + struct block *block = NULL; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords, + &type_name, &block_obj)) + return NULL; + + if (block_obj) + { + block = block_object_to_block (block_obj); + if (! block) + { + PyErr_SetString (PyExc_RuntimeError, + _("'block' argument must be a Block.")); + return NULL; + } + } + + type = typy_lookup_typename (type_name, block); + if (! type) + return NULL; + + return (PyObject *) type_to_type_object (type); +} + +void +gdbpy_initialize_types (void) +{ + int i; + + typy_objfile_data_key + = register_objfile_data_with_cleanup (save_objfile_types, NULL); + + if (PyType_Ready (&type_object_type) < 0) + return; + if (PyType_Ready (&field_object_type) < 0) + return; + + for (i = 0; pyty_codes[i].name; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + /* Cast needed for Python 2.4. */ + (char *) pyty_codes[i].name, + pyty_codes[i].code) < 0) + return; + } + + Py_INCREF (&type_object_type); + PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type); + + Py_INCREF (&field_object_type); + PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type); +} + + + +static PyGetSetDef type_object_getset[] = +{ + { "code", typy_get_code, NULL, + "The code for this type.", NULL }, + { "sizeof", typy_get_sizeof, NULL, + "The size of this type, in bytes.", NULL }, + { "tag", typy_get_tag, NULL, + "The tag name for this type, or None.", NULL }, + { NULL } +}; + +static PyMethodDef type_object_methods[] = +{ + { "array", typy_array, METH_VARARGS, + "array (N) -> Type\n\ +Return a type which represents an array of N objects of this type." }, + { "const", typy_const, METH_NOARGS, + "const () -> Type\n\ +Return a const variant of this type." }, + { "fields", typy_fields, METH_NOARGS, + "field () -> list\n\ +Return a sequence holding all the fields of this type.\n\ +Each field is a dictionary." }, + { "pointer", typy_pointer, METH_NOARGS, + "pointer () -> Type\n\ +Return a type of pointer to this type." }, + { "range", typy_range, METH_NOARGS, + "range () -> tuple\n\ +Return a tuple containing the lower and upper range for this type."}, + { "reference", typy_reference, METH_NOARGS, + "reference () -> Type\n\ +Return a type of reference to this type." }, + { "strip_typedefs", typy_strip_typedefs, METH_NOARGS, + "strip_typedefs () -> Type\n\ +Return a type formed by stripping this type of all typedefs."}, + { "target", typy_target, METH_NOARGS, + "target () -> Type\n\ +Return the target type of this type." }, + { "template_argument", typy_template_argument, METH_VARARGS, + "template_argument (arg, [block]) -> Type\n\ +Return the type of a template argument." }, + { "unqualified", typy_unqualified, METH_NOARGS, + "unqualified () -> Type\n\ +Return a variant of this type without const or volatile attributes." }, + { "volatile", typy_volatile, METH_NOARGS, + "volatile () -> Type\n\ +Return a volatile variant of this type" }, + { NULL } +}; + +static PyTypeObject type_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Type", /*tp_name*/ + sizeof (type_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + typy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + typy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB type object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + typy_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + type_object_methods, /* tp_methods */ + 0, /* tp_members */ + type_object_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +static PyTypeObject field_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Field", /*tp_name*/ + sizeof (field_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + field_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB field object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof (field_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-utils.c b/contrib/gdb-7/gdb/python/py-utils.c new file mode 100644 index 0000000000..601bcb05ea --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-utils.c @@ -0,0 +1,375 @@ +/* General utility routines for GDB/Python. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "charset.h" +#include "value.h" +#include "python-internal.h" + + +/* This is a cleanup function which decrements the refcount on a + Python object. */ + +static void +py_decref (void *p) +{ + PyObject *py = p; + + /* Note that we need the extra braces in this 'if' to avoid a + warning from gcc. */ + if (py) + { + Py_DECREF (py); + } +} + +/* Return a new cleanup which will decrement the Python object's + refcount when run. */ + +struct cleanup * +make_cleanup_py_decref (PyObject *py) +{ + return make_cleanup (py_decref, (void *) py); +} + +/* Converts a Python 8-bit string to a unicode string object. Assumes the + 8-bit string is in the host charset. If an error occurs during conversion, + returns NULL with a python exception set. + + As an added bonus, the functions accepts a unicode string and returns it + right away, so callers don't need to check which kind of string they've + got. + + If the given object is not one of the mentioned string types, NULL is + returned, with the TypeError python exception set. */ +PyObject * +python_string_to_unicode (PyObject *obj) +{ + PyObject *unicode_str; + + /* If obj is already a unicode string, just return it. + I wish life was always that simple... */ + if (PyUnicode_Check (obj)) + { + unicode_str = obj; + Py_INCREF (obj); + } + + else if (PyString_Check (obj)) + unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL); + else + { + PyErr_SetString (PyExc_TypeError, + _("Expected a string or unicode object.")); + unicode_str = NULL; + } + + return unicode_str; +} + +/* Returns a newly allocated string with the contents of the given unicode + string object converted to CHARSET. If an error occurs during the + conversion, NULL will be returned and a python exception will be set. + + The caller is responsible for xfree'ing the string. */ +static char * +unicode_to_encoded_string (PyObject *unicode_str, const char *charset) +{ + char *result; + PyObject *string; + + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); + if (string == NULL) + return NULL; + + result = xstrdup (PyString_AsString (string)); + + Py_DECREF (string); + + return result; +} + +/* Returns a PyObject with the contents of the given unicode string + object converted to a named charset. If an error occurs during + the conversion, NULL will be returned and a python exception will + be set. */ +static PyObject * +unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset) +{ + PyObject *string; + + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); + if (string == NULL) + return NULL; + + return string; +} + +/* Returns a newly allocated string with the contents of the given unicode + string object converted to the target's charset. If an error occurs during + the conversion, NULL will be returned and a python exception will be set. + + The caller is responsible for xfree'ing the string. */ +char * +unicode_to_target_string (PyObject *unicode_str) +{ + return unicode_to_encoded_string (unicode_str, + target_charset (python_gdbarch)); +} + +/* Returns a PyObject with the contents of the given unicode string + object converted to the target's charset. If an error occurs + during the conversion, NULL will be returned and a python exception + will be set. */ +PyObject * +unicode_to_target_python_string (PyObject *unicode_str) +{ + return unicode_to_encoded_python_string (unicode_str, + target_charset (python_gdbarch)); +} + +/* Converts a python string (8-bit or unicode) to a target string in + the target's charset. Returns NULL on error, with a python exception set. + + The caller is responsible for xfree'ing the string. */ +char * +python_string_to_target_string (PyObject *obj) +{ + PyObject *str; + char *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_target_string (str); + Py_DECREF (str); + return result; +} + +/* Converts a python string (8-bit or unicode) to a target string in the + target's charset. Returns NULL on error, with a python exception + set. */ +PyObject * +python_string_to_target_python_string (PyObject *obj) +{ + PyObject *str; + PyObject *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_target_python_string (str); + Py_DECREF (str); + return result; +} + +/* Converts a python string (8-bit or unicode) to a target string in + the host's charset. Returns NULL on error, with a python exception set. + + The caller is responsible for xfree'ing the string. */ +char * +python_string_to_host_string (PyObject *obj) +{ + PyObject *str; + char *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_encoded_string (str, host_charset ()); + Py_DECREF (str); + return result; +} + +/* Converts a target string of LENGTH bytes in the target's charset to a + Python Unicode string. If LENGTH is -1, convert until a null byte is found. + + Returns NULL on error, with a python exception set. */ +PyObject * +target_string_to_unicode (const gdb_byte *str, int length) +{ + if (length == -1) + length = strlen (str); + + return PyUnicode_Decode (str, length, target_charset (python_gdbarch), NULL); +} + +/* Return true if OBJ is a Python string or unicode object, false + otherwise. */ + +int +gdbpy_is_string (PyObject *obj) +{ + return PyString_Check (obj) || PyUnicode_Check (obj); +} + +/* Return the string representation of OBJ, i.e., str (obj). + Space for the result is malloc'd, the caller must free. + If the result is NULL a python error occurred, the caller must clear it. */ + +char * +gdbpy_obj_to_string (PyObject *obj) +{ + PyObject *str_obj = PyObject_Str (obj); + + if (str_obj != NULL) + { + char *msg = xstrdup (PyString_AsString (str_obj)); + + Py_DECREF (str_obj); + return msg; + } + + return NULL; +} + +/* Return the string representation of the exception represented by + TYPE, VALUE which is assumed to have been obtained with PyErr_Fetch, + i.e., the error indicator is currently clear. + Space for the result is malloc'd, the caller must free. + If the result is NULL a python error occurred, the caller must clear it. */ + +char * +gdbpy_exception_to_string (PyObject *ptype, PyObject *pvalue) +{ + char *str; + + /* There are a few cases to consider. + For example: + pvalue is a string when PyErr_SetString is used. + pvalue is not a string when raise "foo" is used, instead it is None + and ptype is "foo". + So the algorithm we use is to print `str (pvalue)' if it's not + None, otherwise we print `str (ptype)'. + Using str (aka PyObject_Str) will fetch the error message from + gdb.GdbError ("message"). */ + + if (pvalue && pvalue != Py_None) + str = gdbpy_obj_to_string (pvalue); + else + str = gdbpy_obj_to_string (ptype); + + return str; +} + +/* Convert a GDB exception to the appropriate Python exception. + + This sets the Python error indicator, and returns NULL. */ + +PyObject * +gdbpy_convert_exception (struct gdb_exception exception) +{ + PyObject *exc_class; + + if (exception.reason == RETURN_QUIT) + exc_class = PyExc_KeyboardInterrupt; + else if (exception.error == MEMORY_ERROR) + exc_class = gdbpy_gdb_memory_error; + else + exc_class = gdbpy_gdb_error; + + return PyErr_Format (exc_class, "%s", exception.message); +} + +/* Converts OBJ to a CORE_ADDR value. + + Returns 1 on success or 0 on failure, with a Python exception set. This + function can also throw GDB exceptions. +*/ + +int +get_addr_from_python (PyObject *obj, CORE_ADDR *addr) +{ + if (gdbpy_is_value_object (obj)) + *addr = value_as_address (value_object_to_value (obj)); + else + { + PyObject *num = PyNumber_Long (obj); + gdb_py_ulongest val; + + if (num == NULL) + return 0; + + val = gdb_py_long_as_ulongest (num); + Py_XDECREF (num); + if (PyErr_Occurred ()) + return 0; + + if (sizeof (val) > sizeof (CORE_ADDR) && ((CORE_ADDR) val) != val) + { + PyErr_SetString (PyExc_ValueError, + _("Overflow converting to address.")); + return 0; + } + + *addr = val; + } + + return 1; +} + +/* Convert a LONGEST to the appropriate Python object -- either an + integer object or a long object, depending on its value. */ + +PyObject * +gdb_py_object_from_longest (LONGEST l) +{ +#ifdef HAVE_LONG_LONG /* Defined by Python. */ + /* If we have 'long long', and the value overflows a 'long', use a + Python Long; otherwise use a Python Int. */ + if (sizeof (l) > sizeof (long) + && (l > PyInt_GetMax () || l < (- (LONGEST) PyInt_GetMax ()) - 1)) + return PyLong_FromLongLong (l); +#endif + return PyInt_FromLong (l); +} + +/* Convert a ULONGEST to the appropriate Python object -- either an + integer object or a long object, depending on its value. */ + +PyObject * +gdb_py_object_from_ulongest (ULONGEST l) +{ +#ifdef HAVE_LONG_LONG /* Defined by Python. */ + /* If we have 'long long', and the value overflows a 'long', use a + Python Long; otherwise use a Python Int. */ + if (sizeof (l) > sizeof (unsigned long) && l > PyInt_GetMax ()) + return PyLong_FromUnsignedLongLong (l); +#endif + + if (l > PyInt_GetMax ()) + return PyLong_FromUnsignedLong (l); + + return PyInt_FromLong (l); +} + +/* Like PyInt_AsLong, but returns 0 on failure, 1 on success, and puts + the value into an out parameter. */ + +int +gdb_py_int_as_long (PyObject *obj, long *result) +{ + *result = PyInt_AsLong (obj); + return ! (*result == -1 && PyErr_Occurred ()); +} diff --git a/contrib/gdb-7/gdb/python/py-value.c b/contrib/gdb-7/gdb/python/py-value.c index 2024021ac1..4381d52039 100644 --- a/contrib/gdb-7/gdb/python/py-value.c +++ b/contrib/gdb-7/gdb/python/py-value.c @@ -1,6 +1,6 @@ /* Python interface to values. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -25,13 +25,16 @@ #include "language.h" #include "dfp.h" #include "valprint.h" +#include "infcall.h" +#include "expression.h" +#include "cp-abi.h" #ifdef HAVE_PYTHON #include "python-internal.h" /* Even though Python scalar types directly map to host types, we use - target types here to remain consistent with the the values system in + target types here to remain consistent with the values system in GDB (which uses target arithmetic). */ /* Python's integer type corresponds to C's long type. */ @@ -60,6 +63,7 @@ typedef struct value_object { struct value *value; PyObject *address; PyObject *type; + PyObject *dynamic_type; } value_object; /* List of all values which are currently exposed to Python. It is @@ -99,6 +103,8 @@ valpy_dealloc (PyObject *obj) Py_DECREF (self->type); } + Py_XDECREF (self->dynamic_type); + self->ob_type->tp_free (self); } @@ -113,7 +119,8 @@ note_value (value_object *value_obj) values_in_python = value_obj; } -/* Called when a new gdb.Value object needs to be allocated. */ +/* Called when a new gdb.Value object needs to be allocated. Returns NULL on + error, with a python exception set. */ static PyObject * valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) { @@ -146,6 +153,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) value_incref (value); value_obj->address = NULL; value_obj->type = NULL; + value_obj->dynamic_type = NULL; note_value (value_obj); return (PyObject *) value_obj; @@ -216,15 +224,78 @@ valpy_get_type (PyObject *self, void *closure) { obj->type = type_to_type_object (value_type (obj->value)); if (!obj->type) - { - obj->type = Py_None; - Py_INCREF (obj->type); - } + return NULL; } Py_INCREF (obj->type); return obj->type; } +/* Return dynamic type of the value. */ + +static PyObject * +valpy_get_dynamic_type (PyObject *self, void *closure) +{ + value_object *obj = (value_object *) self; + volatile struct gdb_exception except; + struct type *type = NULL; + + if (obj->dynamic_type != NULL) + { + Py_INCREF (obj->dynamic_type); + return obj->dynamic_type; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct value *val = obj->value; + + type = value_type (val); + CHECK_TYPEDEF (type); + + if (((TYPE_CODE (type) == TYPE_CODE_PTR) + || (TYPE_CODE (type) == TYPE_CODE_REF)) + && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) + { + struct value *target; + int was_pointer = TYPE_CODE (type) == TYPE_CODE_PTR; + + target = value_ind (val); + type = value_rtti_type (target, NULL, NULL, NULL); + + if (type) + { + if (was_pointer) + type = lookup_pointer_type (type); + else + type = lookup_reference_type (type); + } + } + else if (TYPE_CODE (type) == TYPE_CODE_CLASS) + type = value_rtti_type (val, NULL, NULL, NULL); + else + { + /* Re-use object's static type. */ + type = NULL; + } + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (type == NULL) + { + /* Ensure that the TYPE field is ready. */ + if (!valpy_get_type (self, NULL)) + return NULL; + /* We don't need to incref here, because valpy_get_type already + did it for us. */ + obj->dynamic_type = obj->type; + } + else + obj->dynamic_type = type_to_type_object (type); + + Py_INCREF (obj->dynamic_type); + return obj->dynamic_type; +} + /* Implementation of gdb.Value.lazy_string ([encoding] [, length]) -> string. Return a PyObject representing a lazy_string_object type. A lazy string is a pointer to a string with an optional encoding and @@ -236,13 +307,13 @@ valpy_get_type (PyObject *self, void *closure) static PyObject * valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) { - int length = -1; + gdb_py_longest length = -1; struct value *value = ((value_object *) self)->value; const char *user_encoding = NULL; static char *keywords[] = { "encoding", "length", NULL }; PyObject *str_obj; - if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords, + if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords, &user_encoding, &length)) return NULL; @@ -250,7 +321,8 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) value = value_ind (value); str_obj = gdbpy_create_lazy_string_object (value_address (value), length, - user_encoding, value_type (value)); + user_encoding, + value_type (value)); return (PyObject *) str_obj; } @@ -294,9 +366,10 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw) return unicode; } -/* Cast a value to a given type. */ +/* A helper function that implements the various cast operators. */ + static PyObject * -valpy_cast (PyObject *self, PyObject *args) +valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op) { PyObject *type_obj; struct type *type; @@ -316,13 +389,47 @@ valpy_cast (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - res_val = value_cast (type, ((value_object *) self)->value); + struct value *val = ((value_object *) self)->value; + + if (op == UNOP_DYNAMIC_CAST) + res_val = value_dynamic_cast (type, val); + else if (op == UNOP_REINTERPRET_CAST) + res_val = value_reinterpret_cast (type, val); + else + { + gdb_assert (op == UNOP_CAST); + res_val = value_cast (type, val); + } } GDB_PY_HANDLE_EXCEPTION (except); return value_to_value_object (res_val); } +/* Implementation of the "cast" method. */ + +static PyObject * +valpy_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_CAST); +} + +/* Implementation of the "dynamic_cast" method. */ + +static PyObject * +valpy_dynamic_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_DYNAMIC_CAST); +} + +/* Implementation of the "reinterpret_cast" method. */ + +static PyObject * +valpy_reinterpret_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_REINTERPRET_CAST); +} + static Py_ssize_t valpy_length (PyObject *self) { @@ -333,7 +440,7 @@ valpy_length (PyObject *self) } /* Given string name of an element inside structure, return its value - object. */ + object. Returns NULL on error, with a python exception set. */ static PyObject * valpy_getitem (PyObject *self, PyObject *key) { @@ -372,7 +479,7 @@ valpy_getitem (PyObject *self, PyObject *key) type = check_typedef (value_type (tmp)); if (TYPE_CODE (type) != TYPE_CODE_ARRAY && TYPE_CODE (type) != TYPE_CODE_PTR) - error( _("Cannot subscript requested type.")); + error (_("Cannot subscript requested type.")); else res_val = value_subscript (tmp, value_as_long (idx)); } @@ -393,6 +500,53 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value) return -1; } +/* Called by the Python interpreter to perform an inferior function + call on the value. Returns NULL on error, with a python exception set. */ +static PyObject * +valpy_call (PyObject *self, PyObject *args, PyObject *keywords) +{ + struct value *return_value = NULL; + Py_ssize_t args_count; + volatile struct gdb_exception except; + struct value *function = ((value_object *) self)->value; + struct value **vargs = NULL; + struct type *ftype = check_typedef (value_type (function)); + + if (TYPE_CODE (ftype) != TYPE_CODE_FUNC) + { + PyErr_SetString (PyExc_RuntimeError, + _("Value is not callable (not TYPE_CODE_FUNC).")); + return NULL; + } + + args_count = PyTuple_Size (args); + if (args_count > 0) + { + int i; + + vargs = alloca (sizeof (struct value *) * args_count); + for (i = 0; i < args_count; i++) + { + PyObject *item = PyTuple_GetItem (args, i); + + if (item == NULL) + return NULL; + + vargs[i] = convert_value_from_python (item); + if (vargs[i] == NULL) + return NULL; + } + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + return_value = call_function_by_hand (function, args_count, vargs); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (return_value); +} + /* Called by the Python interpreter to obtain string representation of the object. */ static PyObject * @@ -467,7 +621,8 @@ enum valpy_opcode ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE)) /* Returns a value object which is the result of applying the operation - specified by OPCODE to the given arguments. */ + specified by OPCODE to the given arguments. Returns NULL on error, with + a python exception set. */ static PyObject * valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) { @@ -664,11 +819,8 @@ valpy_nonzero (PyObject *self) TYPE_LENGTH (type), gdbarch_byte_order (get_type_arch (type))); else - { - PyErr_SetString (PyExc_TypeError, _("Attempted truth testing on invalid " - "gdb.Value type.")); - return 0; - } + /* All other values are True. */ + return 1; } /* Implements ~ for value objects. */ @@ -722,7 +874,8 @@ valpy_xor (PyObject *self, PyObject *other) return valpy_binop (VALPY_BITXOR, self, other); } -/* Implements comparison operations for value objects. */ +/* Implements comparison operations for value objects. Returns NULL on error, + with a python exception set. */ static PyObject * valpy_richcompare (PyObject *self, PyObject *other, int op) { @@ -834,14 +987,7 @@ valpy_int (PyObject *self) } GDB_PY_HANDLE_EXCEPTION (except); -#ifdef HAVE_LONG_LONG /* Defined by Python. */ - /* If we have 'long long', and the value overflows a 'long', use a - Python Long; otherwise use a Python Int. */ - if (sizeof (l) > sizeof (long) && (l > PyInt_GetMax () - || l < (- (LONGEST) PyInt_GetMax ()) - 1)) - return PyLong_FromLongLong (l); -#endif - return PyInt_FromLong (l); + return gdb_py_object_from_longest (l); } /* Implements conversion to long. */ @@ -866,11 +1012,7 @@ valpy_long (PyObject *self) } GDB_PY_HANDLE_EXCEPTION (except); -#ifdef HAVE_LONG_LONG /* Defined by Python. */ - return PyLong_FromLongLong (l); -#else - return PyLong_FromLong (l); -#endif + return gdb_py_long_from_longest (l); } /* Implements conversion to float. */ @@ -913,6 +1055,7 @@ value_to_value_object (struct value *val) value_incref (val); val_obj->address = NULL; val_obj->type = NULL; + val_obj->dynamic_type = NULL; note_value (val_obj); } @@ -1019,13 +1162,13 @@ convert_value_from_python (PyObject *obj) else if (gdbpy_is_lazy_string (obj)) { PyObject *result; - PyObject *function = PyString_FromString ("value"); - result = PyObject_CallMethodObjArgs (obj, function, NULL); + result = PyObject_CallMethodObjArgs (obj, gdbpy_value_cst, NULL); value = value_copy (((value_object *) result)->value); } else - PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s."), + PyErr_Format (PyExc_TypeError, + _("Could not convert Python object: %s."), PyString_AsString (PyObject_Str (obj))); } if (except.reason < 0) @@ -1085,16 +1228,29 @@ static PyGetSetDef value_object_getset[] = { { "address", valpy_get_address, NULL, "The address of the value.", NULL }, { "is_optimized_out", valpy_get_is_optimized_out, NULL, - "Boolean telling whether the value is optimized out (i.e., not available).", + "Boolean telling whether the value is optimized " + "out (i.e., not available).", NULL }, { "type", valpy_get_type, NULL, "Type of the value.", NULL }, + { "dynamic_type", valpy_get_dynamic_type, NULL, + "Dynamic type of the value.", NULL }, {NULL} /* Sentinel */ }; static PyMethodDef value_object_methods[] = { { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." }, + { "dynamic_cast", valpy_dynamic_cast, METH_VARARGS, + "dynamic_cast (gdb.Type) -> gdb.Value\n\ +Cast the value to the supplied type, as if by the C++ dynamic_cast operator." + }, + { "reinterpret_cast", valpy_reinterpret_cast, METH_VARARGS, + "reinterpret_cast (gdb.Type) -> gdb.Value\n\ +Cast the value to the supplied type, as if by the C++\n\ +reinterpret_cast operator." + }, { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, - { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS, + { "lazy_string", (PyCFunction) valpy_lazy_string, + METH_VARARGS | METH_KEYWORDS, "lazy_string ([encoding] [, length]) -> lazy_string\n\ Return a lazy string representation of the value." }, { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS, @@ -1151,12 +1307,13 @@ PyTypeObject value_object_type = { 0, /*tp_as_sequence*/ &value_object_as_mapping, /*tp_as_mapping*/ valpy_hash, /*tp_hash*/ - 0, /*tp_call*/ + valpy_call, /*tp_call*/ valpy_str, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES + | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "GDB value object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ diff --git a/contrib/gdb-7/gdb/python/python-config.py b/contrib/gdb-7/gdb/python/python-config.py new file mode 100644 index 0000000000..75ed2d2183 --- /dev/null +++ b/contrib/gdb-7/gdb/python/python-config.py @@ -0,0 +1,77 @@ +# Program to fetch python compilation parameters. +# Copied from python-config of the 2.7 release. + +import sys +import os +import getopt +from distutils import sysconfig + +valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', + 'ldflags', 'help'] + +def exit_with_usage(code=1): + print >>sys.stderr, "Usage: %s [%s]" % (sys.argv[0], + '|'.join('--'+opt for opt in valid_opts)) + sys.exit(code) + +try: + opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) +except getopt.error: + exit_with_usage() + +if not opts: + exit_with_usage() + +pyver = sysconfig.get_config_var('VERSION') +getvar = sysconfig.get_config_var + +opt_flags = [flag for (flag, val) in opts] + +if '--help' in opt_flags: + exit_with_usage(code=0) + +def to_unix_path(path): + """On Windows, returns the given path with all backslashes + converted into forward slashes. This is to help prevent problems + when using the paths returned by this script with cygwin tools. + In particular, cygwin bash treats backslashes as a special character. + + On Unix systems, returns the path unchanged. + """ + if os.name == 'nt': + path = path.replace('\\', '/') + return path + +for opt in opt_flags: + if opt == '--prefix': + print to_unix_path(sysconfig.PREFIX) + + elif opt == '--exec-prefix': + print to_unix_path(sysconfig.EXEC_PREFIX) + + elif opt in ('--includes', '--cflags'): + flags = ['-I' + sysconfig.get_python_inc(), + '-I' + sysconfig.get_python_inc(plat_specific=True)] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print to_unix_path(' '.join(flags)) + + elif opt in ('--libs', '--ldflags'): + libs = [] + if getvar('LIBS') is not None: + libs.extend(getvar('LIBS').split()) + if getvar('SYSLIBS') is not None: + libs.extend(getvar('SYSLIBS').split()) + libs.append('-lpython'+pyver) + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags': + if not getvar('Py_ENABLE_SHARED'): + if getvar('LIBPL') is not None: + libs.insert(0, '-L' + getvar('LIBPL')) + elif os.name == 'nt': + libs.insert(0, '-L' + sysconfig.PREFIX + '/libs') + if getvar('LINKFORSHARED') is not None: + libs.extend(getvar('LINKFORSHARED').split()) + print to_unix_path(' '.join(libs)) + diff --git a/contrib/gdb-7/gdb/python/python-internal.h b/contrib/gdb-7/gdb/python/python-internal.h new file mode 100644 index 0000000000..d3cb78854a --- /dev/null +++ b/contrib/gdb-7/gdb/python/python-internal.h @@ -0,0 +1,289 @@ +/* Gdb/Python header for private use by Python module. + + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PYTHON_INTERNAL_H +#define GDB_PYTHON_INTERNAL_H + +#include + +/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t + needed by pyport.h. */ +#include + +/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE + if it sees _GNU_SOURCE (which config.h will define). + pyconfig.h defines _POSIX_C_SOURCE to a different value than + /usr/include/features.h does causing compilation to fail. + To work around this, undef _POSIX_C_SOURCE before we include Python.h. + + Same problem with _XOPEN_SOURCE. */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +/* On sparc-solaris, /usr/include/sys/feature_tests.h defines + _FILE_OFFSET_BITS, which pyconfig.h also defines. Same work + around technique as above. */ +#undef _FILE_OFFSET_BITS + +/* Include the Python header files using angle brackets rather than + double quotes. On case-insensitive filesystems, this prevents us + from including our python/python.h header file. */ +#include +#include +#if HAVE_LIBPYTHON2_4 +/* Py_ssize_t is not defined until 2.5. + Logical type for Py_ssize_t is Py_intptr_t, but that fails in 64-bit + compilation due to several apparent mistakes in python2.4 API, so we + use 'int' instead. */ +typedef int Py_ssize_t; +#endif + +/* If Python.h does not define WITH_THREAD, then the various + GIL-related functions will not be defined. However, + PyGILState_STATE will be. */ +#ifndef WITH_THREAD +#define PyGILState_Ensure() ((PyGILState_STATE) 0) +#define PyGILState_Release(ARG) ((void)(ARG)) +#define PyEval_InitThreads() +#define PyThreadState_Swap(ARG) ((void)(ARG)) +#define PyEval_ReleaseLock() +#endif + +/* Python supplies HAVE_LONG_LONG and some `long long' support when it + is available. These defines let us handle the differences more + cleanly. */ +#ifdef HAVE_LONG_LONG + +#define GDB_PY_LL_ARG "L" +#define GDB_PY_LLU_ARG "K" +typedef PY_LONG_LONG gdb_py_longest; +typedef unsigned PY_LONG_LONG gdb_py_ulongest; +#define gdb_py_long_from_longest PyLong_FromLongLong +#define gdb_py_long_from_ulongest PyLong_FromUnsignedLongLong +#define gdb_py_long_as_ulongest PyLong_AsUnsignedLongLong + +#else /* HAVE_LONG_LONG */ + +#define GDB_PY_LL_ARG "L" +#define GDB_PY_LLU_ARG "K" +typedef long gdb_py_longest; +typedef unsigned long gdb_py_ulongest; +#define gdb_py_long_from_longest PyLong_FromLong +#define gdb_py_long_from_ulongest PyLong_FromUnsignedLong +#define gdb_py_long_as_ulongest PyLong_AsUnsignedLong + +#endif /* HAVE_LONG_LONG */ + + +/* In order to be able to parse symtab_and_line_to_sal_object function + a real symtab_and_line structure is needed. */ +#include "symtab.h" + +/* Also needed to parse enum var_types. */ +#include "command.h" +#include "breakpoint.h" + +#include "exceptions.h" + +struct block; +struct value; +struct language_defn; +struct program_space; +struct bpstats; + +extern PyObject *gdb_module; +extern PyTypeObject value_object_type; +extern PyTypeObject block_object_type; +extern PyTypeObject symbol_object_type; +extern PyTypeObject event_object_type; +extern PyTypeObject events_object_type; +extern PyTypeObject stop_event_object_type; + +/* Defined in py-breakpoint.c */ +typedef struct breakpoint_object breakpoint_object; + +typedef struct +{ + PyObject_HEAD + + /* The thread we represent. */ + struct thread_info *thread; + + /* The Inferior object to which this thread belongs. */ + PyObject *inf_obj; +} thread_object; + +extern struct cmd_list_element *set_python_list; +extern struct cmd_list_element *show_python_list; + +PyObject *gdbpy_history (PyObject *self, PyObject *args); +PyObject *gdbpy_breakpoints (PyObject *, PyObject *); +PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); +PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); +PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, + PyObject *kw); +PyObject *gdbpy_newest_frame (PyObject *self, PyObject *args); +PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); +PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args); +PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw); +PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length, + const char *encoding, + struct type *type); +PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2); +PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args); +PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args); +PyObject *gdbpy_parameter (PyObject *self, PyObject *args); +PyObject *gdbpy_parameter_value (enum var_types type, void *var); +char *gdbpy_parse_command_name (char *text, + struct cmd_list_element ***base_list, + struct cmd_list_element **start_list); + +PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); +PyObject *symtab_to_symtab_object (struct symtab *symtab); +PyObject *symbol_to_symbol_object (struct symbol *sym); +PyObject *block_to_block_object (struct block *block, struct objfile *objfile); +PyObject *value_to_value_object (struct value *v); +PyObject *type_to_type_object (struct type *); +PyObject *frame_info_to_frame_object (struct frame_info *frame); + +PyObject *pspace_to_pspace_object (struct program_space *); +PyObject *pspy_get_printers (PyObject *, void *); + +PyObject *objfile_to_objfile_object (struct objfile *); +PyObject *objfpy_get_printers (PyObject *, void *); + +thread_object *create_thread_object (struct thread_info *tp); +thread_object *find_thread_object (ptid_t ptid); +PyObject *find_inferior_object (int pid); +PyObject *inferior_to_inferior_object (struct inferior *inferior); + +struct block *block_object_to_block (PyObject *obj); +struct symbol *symbol_object_to_symbol (PyObject *obj); +struct value *value_object_to_value (PyObject *self); +struct value *convert_value_from_python (PyObject *obj); +struct type *type_object_to_type (PyObject *obj); +struct symtab *symtab_object_to_symtab (PyObject *obj); +struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); + +void gdbpy_initialize_auto_load (void); +void gdbpy_initialize_values (void); +void gdbpy_initialize_frames (void); +void gdbpy_initialize_symtabs (void); +void gdbpy_initialize_commands (void); +void gdbpy_initialize_symbols (void); +void gdbpy_initialize_symtabs (void); +void gdbpy_initialize_blocks (void); +void gdbpy_initialize_types (void); +void gdbpy_initialize_functions (void); +void gdbpy_initialize_pspace (void); +void gdbpy_initialize_objfile (void); +void gdbpy_initialize_breakpoints (void); +void gdbpy_initialize_lazy_string (void); +void gdbpy_initialize_parameters (void); +void gdbpy_initialize_thread (void); +void gdbpy_initialize_inferior (void); +void gdbpy_initialize_eventregistry (void); +void gdbpy_initialize_event (void); +void gdbpy_initialize_py_events (void); +void gdbpy_initialize_stop_event (void); +void gdbpy_initialize_signal_event (void); +void gdbpy_initialize_breakpoint_event (void); +void gdbpy_initialize_continue_event (void); +void gdbpy_initialize_exited_event (void); +void gdbpy_initialize_thread_event (void); + +struct cleanup *make_cleanup_py_decref (PyObject *py); + +struct cleanup *ensure_python_env (struct gdbarch *gdbarch, + const struct language_defn *language); + +extern struct gdbarch *python_gdbarch; +extern const struct language_defn *python_language; + +/* Use this after a TRY_EXCEPT to throw the appropriate Python + exception. */ +#define GDB_PY_HANDLE_EXCEPTION(Exception) \ + do { \ + if (Exception.reason < 0) \ + return gdbpy_convert_exception (Exception); \ + } while (0) + +/* Use this after a TRY_EXCEPT to throw the appropriate Python + exception. This macro is for use inside setter functions. */ +#define GDB_PY_SET_HANDLE_EXCEPTION(Exception) \ + do { \ + if (Exception.reason < 0) \ + { \ + gdbpy_convert_exception (Exception); \ + return -1; \ + } \ + } while (0) + +void gdbpy_print_stack (void); + +void source_python_script_for_objfile (struct objfile *objfile, + FILE *stream, const char *file); + +PyObject *python_string_to_unicode (PyObject *obj); +char *unicode_to_target_string (PyObject *unicode_str); +char *python_string_to_target_string (PyObject *obj); +PyObject *python_string_to_target_python_string (PyObject *obj); +char *python_string_to_host_string (PyObject *obj); +PyObject *target_string_to_unicode (const gdb_byte *str, int length); +int gdbpy_is_string (PyObject *obj); +char *gdbpy_obj_to_string (PyObject *obj); +char *gdbpy_exception_to_string (PyObject *ptype, PyObject *pvalue); + +int gdbpy_is_lazy_string (PyObject *result); +void gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, + struct type **str_type, + long *length, char **encoding); + +int gdbpy_is_value_object (PyObject *obj); + +/* Note that these are declared here, and not in python.h with the + other pretty-printer functions, because they refer to PyObject. */ +PyObject *apply_varobj_pretty_printer (PyObject *print_obj, + struct value **replacement, + struct ui_file *stream); +PyObject *gdbpy_get_varobj_pretty_printer (struct value *value); +char *gdbpy_get_display_hint (PyObject *printer); +PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args); + +extern PyObject *gdbpy_doc_cst; +extern PyObject *gdbpy_children_cst; +extern PyObject *gdbpy_to_string_cst; +extern PyObject *gdbpy_display_hint_cst; +extern PyObject *gdbpy_enabled_cst; +extern PyObject *gdbpy_value_cst; + +/* Exception types. */ +extern PyObject *gdbpy_gdb_error; +extern PyObject *gdbpy_gdb_memory_error; +extern PyObject *gdbpy_gdberror_exc; + +extern PyObject *gdbpy_convert_exception (struct gdb_exception); + +int get_addr_from_python (PyObject *obj, CORE_ADDR *addr); + +PyObject *gdb_py_object_from_longest (LONGEST l); +PyObject *gdb_py_object_from_ulongest (ULONGEST l); +int gdb_py_int_as_long (PyObject *, long *); + +#endif /* GDB_PYTHON_INTERNAL_H */ diff --git a/contrib/gdb-7/gdb/python/python.c b/contrib/gdb-7/gdb/python/python.c index 7346fbaaef..8a7bc66b36 100644 --- a/contrib/gdb-7/gdb/python/python.c +++ b/contrib/gdb-7/gdb/python/python.c @@ -1,6 +1,6 @@ /* General python/gdb code - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,9 @@ #include "value.h" #include "language.h" #include "exceptions.h" +#include "event-loop.h" +#include "serial.h" +#include "python.h" #include @@ -37,12 +40,14 @@ static int gdbpy_should_print_stack = 1; #ifdef HAVE_PYTHON -#include "python.h" #include "libiberty.h" #include "cli/cli-decode.h" #include "charset.h" #include "top.h" +#include "solib.h" #include "python-internal.h" +#include "linespec.h" +#include "source.h" #include "version.h" #include "target.h" #include "gdbthread.h" @@ -57,10 +62,17 @@ PyObject *gdbpy_children_cst; PyObject *gdbpy_display_hint_cst; PyObject *gdbpy_doc_cst; PyObject *gdbpy_enabled_cst; +PyObject *gdbpy_value_cst; /* The GdbError exception. */ PyObject *gdbpy_gdberror_exc; +/* The `gdb.error' base class. */ +PyObject *gdbpy_gdb_error; + +/* The `gdb.MemoryError' exception. */ +PyObject *gdbpy_gdb_memory_error; + /* Architecture and language to be used in callbacks from the Python interpreter. */ struct gdbarch *python_gdbarch; @@ -74,6 +86,7 @@ struct python_env PyGILState_STATE state; struct gdbarch *gdbarch; const struct language_defn *language; + PyObject *error_type, *error_value, *error_traceback; }; static void @@ -81,6 +94,16 @@ restore_python_env (void *p) { struct python_env *env = (struct python_env *)p; + /* Leftover Python error is forbidden by Python Exception Handling. */ + if (PyErr_Occurred ()) + { + /* This order is similar to the one calling error afterwards. */ + gdbpy_print_stack (); + warning (_("internal error: Unhandled Python exception")); + } + + PyErr_Restore (env->error_type, env->error_value, env->error_traceback); + PyGILState_Release (env->state); python_gdbarch = env->gdbarch; python_language = env->language; @@ -103,6 +126,9 @@ ensure_python_env (struct gdbarch *gdbarch, python_gdbarch = gdbarch; python_language = language; + /* Save it and ensure ! PyErr_Occurred () afterwards. */ + PyErr_Fetch (&env->error_type, &env->error_value, &env->error_traceback); + return make_cleanup (restore_python_env, env); } @@ -350,6 +376,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) char *copy = xstrdup (arg); struct cleanup *cleanup = make_cleanup (xfree, copy); + prevent_dont_repeat (); if (to_string) result = execute_command_to_string (copy, from_tty); else @@ -374,6 +401,132 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } +/* Implementation of gdb.solib_name (Long) -> String. + Returns the name of the shared library holding a given address, or None. */ + +static PyObject * +gdbpy_solib_name (PyObject *self, PyObject *args) +{ + char *soname; + PyObject *str_obj; + gdb_py_longest pc; + + if (!PyArg_ParseTuple (args, GDB_PY_LL_ARG, &pc)) + return NULL; + + soname = solib_name_from_address (current_program_space, pc); + if (soname) + str_obj = PyString_Decode (soname, strlen (soname), host_charset (), NULL); + else + { + str_obj = Py_None; + Py_INCREF (Py_None); + } + + return str_obj; +} + +/* A Python function which is a wrapper for decode_line_1. */ + +static PyObject * +gdbpy_decode_line (PyObject *self, PyObject *args) +{ + struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to + appease gcc. */ + struct symtab_and_line sal; + char *arg = NULL; + char *copy = NULL; + struct cleanup *cleanups; + PyObject *result = NULL; + PyObject *return_result = NULL; + PyObject *unparsed = NULL; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "|s", &arg)) + return NULL; + + cleanups = ensure_python_env (get_current_arch (), current_language); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (arg) + { + arg = xstrdup (arg); + make_cleanup (xfree, arg); + copy = arg; + sals = decode_line_1 (©, 0, 0, 0, 0); + make_cleanup (xfree, sals.sals); + } + else + { + set_default_source_symtab_and_line (); + sal = get_current_source_symtab_and_line (); + sals.sals = &sal; + sals.nelts = 1; + } + } + if (except.reason < 0) + { + do_cleanups (cleanups); + /* We know this will always throw. */ + GDB_PY_HANDLE_EXCEPTION (except); + } + + if (sals.nelts) + { + int i; + + result = PyTuple_New (sals.nelts); + if (! result) + goto error; + for (i = 0; i < sals.nelts; ++i) + { + PyObject *obj; + char *str; + + obj = symtab_and_line_to_sal_object (sals.sals[i]); + if (! obj) + { + Py_DECREF (result); + goto error; + } + + PyTuple_SetItem (result, i, obj); + } + } + else + { + result = Py_None; + Py_INCREF (Py_None); + } + + return_result = PyTuple_New (2); + if (! return_result) + { + Py_DECREF (result); + goto error; + } + + if (copy && strlen (copy) > 0) + unparsed = PyString_FromString (copy); + else + { + unparsed = Py_None; + Py_INCREF (Py_None); + } + + PyTuple_SetItem (return_result, 0, unparsed); + PyTuple_SetItem (return_result, 1, result); + + do_cleanups (cleanups); + + return return_result; + + error: + do_cleanups (cleanups); + return NULL; +} + /* Parse a string and evaluate it as an expression. */ static PyObject * gdbpy_parse_and_eval (PyObject *self, PyObject *args) @@ -414,26 +567,183 @@ source_python_script (FILE *stream, const char *file) +/* Posting and handling events. */ + +/* A single event. */ +struct gdbpy_event +{ + /* The Python event. This is just a callable object. */ + PyObject *event; + /* The next event. */ + struct gdbpy_event *next; +}; + +/* All pending events. */ +static struct gdbpy_event *gdbpy_event_list; +/* The final link of the event list. */ +static struct gdbpy_event **gdbpy_event_list_end; + +/* We use a file handler, and not an async handler, so that we can + wake up the main thread even when it is blocked in poll(). */ +static struct serial *gdbpy_event_fds[2]; + +/* The file handler callback. This reads from the internal pipe, and + then processes the Python event queue. This will always be run in + the main gdb thread. */ + +static void +gdbpy_run_events (struct serial *scb, void *context) +{ + struct cleanup *cleanup; + int r; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + /* Flush the fd. Do this before flushing the events list, so that + any new event post afterwards is sure to re-awake the event + loop. */ + while (serial_readchar (gdbpy_event_fds[0], 0) >= 0) + ; + + while (gdbpy_event_list) + { + /* Dispatching the event might push a new element onto the event + loop, so we update here "atomically enough". */ + struct gdbpy_event *item = gdbpy_event_list; + gdbpy_event_list = gdbpy_event_list->next; + if (gdbpy_event_list == NULL) + gdbpy_event_list_end = &gdbpy_event_list; + + /* Ignore errors. */ + if (PyObject_CallObject (item->event, NULL) == NULL) + PyErr_Clear (); + + Py_DECREF (item->event); + xfree (item); + } + + do_cleanups (cleanup); +} + +/* Submit an event to the gdb thread. */ +static PyObject * +gdbpy_post_event (PyObject *self, PyObject *args) +{ + struct gdbpy_event *event; + PyObject *func; + int wakeup; + + if (!PyArg_ParseTuple (args, "O", &func)) + return NULL; + + if (!PyCallable_Check (func)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Posted event is not callable")); + return NULL; + } + + Py_INCREF (func); + + /* From here until the end of the function, we have the GIL, so we + can operate on our global data structures without worrying. */ + wakeup = gdbpy_event_list == NULL; + + event = XNEW (struct gdbpy_event); + event->event = func; + event->next = NULL; + *gdbpy_event_list_end = event; + gdbpy_event_list_end = &event->next; + + /* Wake up gdb when needed. */ + if (wakeup) + { + char c = 'q'; /* Anything. */ + + if (serial_write (gdbpy_event_fds[1], &c, 1)) + return PyErr_SetFromErrno (PyExc_IOError); + } + + Py_RETURN_NONE; +} + +/* Initialize the Python event handler. */ +static void +gdbpy_initialize_events (void) +{ + if (serial_pipe (gdbpy_event_fds) == 0) + { + gdbpy_event_list_end = &gdbpy_event_list; + serial_async (gdbpy_event_fds[0], gdbpy_run_events, NULL); + } +} + /* Printing. */ /* A python function to write a single string using gdb's filtered - output stream. */ + output stream . The optional keyword STREAM can be used to write + to a particular stream. The default stream is to gdb_stdout. */ + static PyObject * -gdbpy_write (PyObject *self, PyObject *args) +gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) { char *arg; - - if (! PyArg_ParseTuple (args, "s", &arg)) + static char *keywords[] = {"text", "stream", NULL }; + int stream_type = 0; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &arg, + &stream_type)) return NULL; - printf_filtered ("%s", arg); + + switch (stream_type) + { + case 1: + { + fprintf_filtered (gdb_stderr, "%s", arg); + break; + } + case 2: + { + fprintf_filtered (gdb_stdlog, "%s", arg); + break; + } + default: + fprintf_filtered (gdb_stdout, "%s", arg); + } + Py_RETURN_NONE; } -/* A python function to flush gdb's filtered output stream. */ +/* A python function to flush a gdb stream. The optional keyword + STREAM can be used to flush a particular stream. The default stream + is gdb_stdout. */ + static PyObject * -gdbpy_flush (PyObject *self, PyObject *args) +gdbpy_flush (PyObject *self, PyObject *args, PyObject *kw) { - gdb_flush (gdb_stdout); + static char *keywords[] = {"stream", NULL }; + int stream_type = 0; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "|i", keywords, + &stream_type)) + return NULL; + + switch (stream_type) + { + case 1: + { + gdb_flush (gdb_stderr); + break; + } + case 2: + { + gdb_flush (gdb_stdlog); + break; + } + default: + gdb_flush (gdb_stdout); + } + Py_RETURN_NONE; } @@ -600,6 +910,22 @@ source_python_script (FILE *stream, const char *file) _("Python scripting is not supported in this copy of GDB.")); } +int +gdbpy_should_stop (struct breakpoint_object *bp_obj) +{ + internal_error (__FILE__, __LINE__, + _("gdbpy_should_stop called when Python scripting is " \ + "not supported.")); +} + +int +gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) +{ + internal_error (__FILE__, __LINE__, + _("gdbpy_breakpoint_has_py_cond called when Python " \ + "scripting is not supported.")); +} + #endif /* HAVE_PYTHON */ @@ -692,7 +1018,17 @@ Enables or disables printing of Python stack traces."), /* The casts to (char*) are for python 2.4. */ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version); PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name); - PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name); + PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", + (char*) target_name); + + /* Add stream constants. */ + PyModule_AddIntConstant (gdb_module, "STDOUT", 0); + PyModule_AddIntConstant (gdb_module, "STDERR", 1); + PyModule_AddIntConstant (gdb_module, "STDLOG", 2); + + /* gdb.parameter ("data-directory") doesn't necessarily exist when the python + script below is run (depending on order of _initialize_* functions). + Define the initial value of gdb.PYTHONDIR here. */ { char *gdb_pythondir; @@ -701,6 +1037,13 @@ Enables or disables printing of Python stack traces."), xfree (gdb_pythondir); } + gdbpy_gdb_error = PyErr_NewException ("gdb.error", PyExc_RuntimeError, NULL); + PyModule_AddObject (gdb_module, "error", gdbpy_gdb_error); + + gdbpy_gdb_memory_error = PyErr_NewException ("gdb.MemoryError", + gdbpy_gdb_error, NULL); + PyModule_AddObject (gdb_module, "MemoryError", gdbpy_gdb_memory_error); + gdbpy_gdberror_exc = PyErr_NewException ("gdb.GdbError", NULL, NULL); PyModule_AddObject (gdb_module, "GdbError", gdbpy_gdberror_exc); @@ -720,6 +1063,17 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_lazy_string (); gdbpy_initialize_thread (); gdbpy_initialize_inferior (); + gdbpy_initialize_events (); + + gdbpy_initialize_eventregistry (); + gdbpy_initialize_py_events (); + gdbpy_initialize_event (); + gdbpy_initialize_stop_event (); + gdbpy_initialize_signal_event (); + gdbpy_initialize_breakpoint_event (); + gdbpy_initialize_continue_event (); + gdbpy_initialize_exited_event (); + gdbpy_initialize_thread_event (); PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("gdb.pretty_printers = []"); @@ -729,11 +1083,33 @@ Enables or disables printing of Python stack traces."), gdbpy_display_hint_cst = PyString_FromString ("display_hint"); gdbpy_doc_cst = PyString_FromString ("__doc__"); gdbpy_enabled_cst = PyString_FromString ("enabled"); + gdbpy_value_cst = PyString_FromString ("value"); + + /* Release the GIL while gdb runs. */ + PyThreadState_Swap (NULL); + PyEval_ReleaseLock (); + +#endif /* HAVE_PYTHON */ +} + +#ifdef HAVE_PYTHON + +/* Perform the remaining python initializations. + These must be done after GDB is at least mostly initialized. + E.g., The "info pretty-printer" command needs the "info" prefix + command installed. */ + +void +finish_python_initialization (void) +{ + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); - /* Create a couple objects which are used for Python's stdout and - stderr. */ PyRun_SimpleString ("\ +import os\n\ import sys\n\ +\n\ class GdbOutputFile:\n\ def close(self):\n\ # Do nothing.\n\ @@ -743,7 +1119,7 @@ class GdbOutputFile:\n\ return False\n\ \n\ def write(self, s):\n\ - gdb.write(s)\n\ + gdb.write(s, stream=gdb.STDOUT)\n \ \n\ def writelines(self, iterable):\n\ for line in iterable:\n\ @@ -752,34 +1128,65 @@ class GdbOutputFile:\n\ def flush(self):\n\ gdb.flush()\n\ \n\ -sys.stderr = GdbOutputFile()\n\ sys.stdout = GdbOutputFile()\n\ \n\ -# GDB's python scripts are stored inside gdb.PYTHONDIR. So insert\n\ -# that directory name at the start of sys.path to allow the Python\n\ -# interpreter to find them.\n\ -sys.path.insert(0, gdb.PYTHONDIR)\n\ +class GdbOutputErrorFile:\n\ + def close(self):\n\ + # Do nothing.\n\ + return None\n\ +\n\ + def isatty(self):\n\ + return False\n\ +\n\ + def write(self, s):\n\ + gdb.write(s, stream=gdb.STDERR)\n \ +\n\ + def writelines(self, iterable):\n\ + for line in iterable:\n\ + self.write(line)\n \ +\n\ + def flush(self):\n\ + gdb.flush()\n\ +\n\ +sys.stderr = GdbOutputErrorFile()\n\ +\n\ +# Ideally this would live in the gdb module, but it's intentionally written\n\ +# in python, and we need this to bootstrap the gdb module.\n\ +\n\ +def GdbSetPythonDirectory (dir):\n\ + \"Set gdb.PYTHONDIR and update sys.path,etc.\"\n\ + old_dir = gdb.PYTHONDIR\n\ + gdb.PYTHONDIR = dir\n\ + # GDB's python scripts are stored inside gdb.PYTHONDIR. So insert\n\ + # that directory name at the start of sys.path to allow the Python\n\ + # interpreter to find them.\n\ + if old_dir in sys.path:\n\ + sys.path.remove (old_dir)\n\ + sys.path.insert (0, gdb.PYTHONDIR)\n\ +\n\ + # Tell python where to find submodules of gdb.\n\ + gdb.__path__ = [gdb.PYTHONDIR + '/gdb']\n\ \n\ -# The gdb module is implemented in C rather than in Python. As a result,\n\ -# the associated __init.py__ script is not not executed by default when\n\ -# the gdb module gets imported. Execute that script manually if it exists.\n\ -gdb.__path__ = [gdb.PYTHONDIR + '/gdb']\n\ -from os.path import exists\n\ -ipy = gdb.PYTHONDIR + '/gdb/__init__.py'\n\ -if exists (ipy):\n\ - execfile (ipy)\n\ + # The gdb module is implemented in C rather than in Python. As a result,\n\ + # the associated __init.py__ script is not not executed by default when\n\ + # the gdb module gets imported. Execute that script manually if it\n\ + # exists.\n\ + ipy = gdb.PYTHONDIR + '/gdb/__init__.py'\n\ + if os.path.exists (ipy):\n\ + execfile (ipy)\n\ +\n\ +# Install the default gdb.PYTHONDIR.\n\ +GdbSetPythonDirectory (gdb.PYTHONDIR)\n\ "); - /* Release the GIL while gdb runs. */ - PyThreadState_Swap (NULL); - PyEval_ReleaseLock (); + do_cleanups (cleanup); +} #endif /* HAVE_PYTHON */ -} -#if HAVE_PYTHON +#ifdef HAVE_PYTHON static PyMethodDef GdbMethods[] = { @@ -806,6 +1213,9 @@ static PyMethodDef GdbMethods[] = { "objfiles", gdbpy_objfiles, METH_NOARGS, "Return a sequence of all loaded objfiles." }, + { "newest_frame", gdbpy_newest_frame, METH_NOARGS, + "newest_frame () -> gdb.Frame.\n\ +Return the newest frame object." }, { "selected_frame", gdbpy_selected_frame, METH_NOARGS, "selected_frame () -> gdb.Frame.\n\ Return the selected frame object." }, @@ -823,13 +1233,30 @@ Return a Type corresponding to the given name." }, Return a tuple with the symbol corresponding to the given name (or None) and\n\ a boolean indicating if name is a field of the current implied argument\n\ `this' (when the current language is object-oriented)." }, + { "lookup_global_symbol", (PyCFunction) gdbpy_lookup_global_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_global_symbol (name [, domain]) -> symbol\n\ +Return the symbol corresponding to the given name (or None)." }, { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, "Return the block containing the given pc value, or None." }, + { "solib_name", gdbpy_solib_name, METH_VARARGS, + "solib_name (Long) -> String.\n\ +Return the name of the shared library holding a given address, or None." }, + { "decode_line", gdbpy_decode_line, METH_VARARGS, + "decode_line (String) -> Tuple. Decode a string argument the way\n\ +that 'break' or 'edit' does. Return a tuple containing two elements.\n\ +The first element contains any unparsed portion of the String parameter\n\ +(or None if the string was fully parsed). The second element contains\n\ +a tuple that contains all the locations that match, represented as\n\ +gdb.Symtab_and_line objects (or None)."}, { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, "parse_and_eval (String) -> Value.\n\ Parse String as an expression, evaluate it, and return the result as a Value." }, + { "post_event", gdbpy_post_event, METH_VARARGS, + "Post an event into gdb's event loop." }, + { "target_charset", gdbpy_target_charset, METH_NOARGS, "target_charset () -> string.\n\ Return the name of the current target charset." }, @@ -842,10 +1269,9 @@ Return the name of the current target wide charset." }, Parse String and return an argv-like array.\n\ Arguments are separate by spaces and may be quoted." }, - - { "write", gdbpy_write, METH_VARARGS, + { "write", (PyCFunction)gdbpy_write, METH_VARARGS | METH_KEYWORDS, "Write a string using gdb's filtered stream." }, - { "flush", gdbpy_flush, METH_NOARGS, + { "flush", (PyCFunction)gdbpy_flush, METH_VARARGS | METH_KEYWORDS, "Flush gdb's filtered stdout stream." }, { "selected_thread", gdbpy_selected_thread, METH_NOARGS, "selected_thread () -> gdb.InferiorThread.\n\ diff --git a/contrib/gdb-7/gdb/python/python.h b/contrib/gdb-7/gdb/python/python.h index affd4a4384..ce0eb351f7 100644 --- a/contrib/gdb-7/gdb/python/python.h +++ b/contrib/gdb-7/gdb/python/python.h @@ -1,6 +1,6 @@ /* Python/gdb header for generic use in gdb - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -22,8 +22,12 @@ #include "value.h" +struct breakpoint_object; + extern int gdbpy_global_auto_load; +extern void finish_python_initialization (void); + void eval_python_from_control_command (struct command_line *); void source_python_script (FILE *stream, const char *file); @@ -39,4 +43,8 @@ void preserve_python_values (struct objfile *objfile, htab_t copied_types); void load_auto_scripts_for_objfile (struct objfile *objfile); +int gdbpy_should_stop (struct breakpoint_object *bp_obj); + +int gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj); + #endif /* GDB_PYTHON_H */ diff --git a/contrib/gdb-7/gdb/ravenscar-sparc-thread.c b/contrib/gdb-7/gdb/ravenscar-sparc-thread.c new file mode 100644 index 0000000000..beb6bbc1f0 --- /dev/null +++ b/contrib/gdb-7/gdb/ravenscar-sparc-thread.c @@ -0,0 +1,185 @@ +/* Ravenscar SPARC target support. + + Copyright 2004, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "sparc-tdep.h" +#include "inferior.h" +#include "ravenscar-thread.h" + +static struct ravenscar_arch_ops ravenscar_sparc_ops; + +static void ravenscar_sparc_fetch_registers (struct regcache *regcache, + int regnum); +static void ravenscar_sparc_store_registers (struct regcache *regcache, + int regnum); +static void ravenscar_sparc_prepare_to_store (struct regcache *regcache); + +/* Register offsets from a referenced address (exempli gratia the + Thread_Descriptor). The referenced address depends on the register + number. The Thread_Descriptor layout and the stack layout are documented + in the GNAT sources, in sparc-bb.h. */ + +static const int sparc_register_offsets[] = +{ + /* G0 - G7 */ + -1, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, + /* O0 - O7 */ + 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, + /* L0 - L7 */ + 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, + /* I0 - I7 */ + 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, + /* F0 - F31 */ + 0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, + 0x70, 0x74, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C, + 0x90, 0x94, 0x99, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC, + 0xB0, 0xB4, 0xBB, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC, + /* Y PSR WIM TBR PC NPC FPSR CPSR */ + 0x40, 0x20, 0x44, -1, 0x1C, -1, 0x4C, -1 +}; + +/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the + regcache. */ + +static void +supply_register_at_address (struct regcache *regcache, int regnum, + CORE_ADDR register_addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int buf_size = register_size (gdbarch, regnum); + char *buf; + + buf = (char *) alloca (buf_size); + read_memory (register_addr, buf, buf_size); + regcache_raw_supply (regcache, regnum, buf); +} + +/* Return true if, for a non-running thread, REGNUM has been saved on the + stack. */ + +static int +register_on_stack_p (int regnum) +{ + return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) + || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM); +} + +/* Return true if, for a non-running thread, REGNUM has been saved on the + Thread_Descriptor. */ + +static int +register_in_thread_descriptor_p (int regnum) +{ + return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) + || (regnum == SPARC32_PSR_REGNUM) + || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) + || (regnum == SPARC32_Y_REGNUM) + || (regnum == SPARC32_WIM_REGNUM) + || (regnum == SPARC32_FSR_REGNUM) + || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31) + || (regnum == SPARC32_PC_REGNUM); +} + +/* to_fetch_registers when inferior_ptid is different from the running + thread. */ + +static void +ravenscar_sparc_fetch_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const int sp_regnum = gdbarch_sp_regnum (gdbarch); + const int num_regs = gdbarch_num_regs (gdbarch); + int current_regnum; + CORE_ADDR current_address; + CORE_ADDR thread_descriptor_address; + ULONGEST stack_address; + + thread_descriptor_address = (CORE_ADDR) ptid_get_tid (inferior_ptid); + current_address = thread_descriptor_address + + sparc_register_offsets [sp_regnum]; + supply_register_at_address (regcache, sp_regnum, current_address); + regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address); + + for (current_regnum = 0; current_regnum < num_regs; current_regnum ++) + { + if (register_in_thread_descriptor_p (current_regnum)) + { + current_address = thread_descriptor_address + + sparc_register_offsets [current_regnum]; + supply_register_at_address (regcache, current_regnum, + current_address); + } + else if (register_on_stack_p (current_regnum)) + { + current_address = stack_address + + sparc_register_offsets [current_regnum]; + supply_register_at_address (regcache, current_regnum, + current_address); + } + } +} + +/* to_prepare_to_store when inferior_ptid is different from the running + thread. */ + +static void +ravenscar_sparc_prepare_to_store (struct regcache *regcache) +{ + /* Nothing to do. */ +} + +/* to_store_registers when inferior_ptid is different from the running + thread. */ + +static void +ravenscar_sparc_store_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int buf_size = register_size (gdbarch, regnum); + char buf [buf_size]; + ULONGEST register_address; + + if (register_in_thread_descriptor_p (regnum)) + register_address = + ptid_get_tid (inferior_ptid) + sparc_register_offsets [regnum]; + else if (register_on_stack_p (regnum)) + { + regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, + ®ister_address); + register_address += sparc_register_offsets [regnum]; + } + else + return; + + regcache_raw_collect (regcache, regnum, buf); + write_memory (register_address, + buf, + buf_size); +} + +void +_initialize_ravenscar_sparc (void) +{ + ravenscar_sparc_ops.to_fetch_registers = ravenscar_sparc_fetch_registers; + ravenscar_sparc_ops.to_store_registers = ravenscar_sparc_store_registers; + ravenscar_sparc_ops.to_prepare_to_store = ravenscar_sparc_prepare_to_store; + ravenscar_register_arch_ops (&ravenscar_sparc_ops); +} diff --git a/contrib/gdb-7/gdb/ravenscar-thread.c b/contrib/gdb-7/gdb/ravenscar-thread.c new file mode 100644 index 0000000000..173a524667 --- /dev/null +++ b/contrib/gdb-7/gdb/ravenscar-thread.c @@ -0,0 +1,453 @@ +/* Ada Ravenscar thread support. + + Copyright 2004, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "gdbthread.h" +#include "ada-lang.h" +#include "target.h" +#include "inferior.h" +#include "command.h" +#include "ravenscar-thread.h" +#include "observer.h" +#include "gdb_string.h" +#include "gdbcmd.h" +#include "top.h" +#include "regcache.h" + +/* If non-null, ravenscar task support is enabled. */ +static int ravenscar_task_support = 1; + +/* Non-null if the ravenscar thread layer has been pushed on the target + stack. */ +static int ravenscar_is_open = 0; + +/* This module's target-specific operations. */ +static struct target_ops ravenscar_ops; + +/* Some base target uses a special value for the null PID (exempli gratia + remote). */ +static ptid_t base_magic_null_ptid; + +/* Ptid of the inferior as seen by the process stratum. */ +static ptid_t base_ptid; + +static const char running_thread_name[] = "__gnat_running_thread_table"; + +static const char known_tasks_name[] = "system__tasking__debug__known_tasks"; + +static const char ravenscar_runtime_initializer[] = + "system__bb__threads__initialize"; + +static struct observer *update_target_observer = NULL; + +/* Architecture-specific hooks. */ +static struct ravenscar_arch_ops* current_arch_ops; + +static void ravenscar_find_new_threads (struct target_ops *ops); +static ptid_t ravenscar_running_thread (void); +static char *ravenscar_extra_thread_info (struct thread_info *tp); +static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid); +static void ravenscar_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum); +static void ravenscar_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum); +static void ravenscar_prepare_to_store (struct regcache *regcache); +static void ravenscar_initialize (char *name, int from_tty); +static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step, + enum target_signal siggnal); +static void ravenscar_mourn_inferior (struct target_ops *ops); +static void ravenscar_update_inferior_ptid (void); +static int has_ravenscar_runtime (void); +static int ravenscar_runtime_initialized (void); +static void ravenscar_inferior_created (struct target_ops *target, + int from_tty); + +/* Fetch the ravenscar running thread from target memory and + update inferior_ptid accordingly. */ + +static void +ravenscar_update_inferior_ptid (void) +{ + base_ptid = inferior_ptid; + + /* If the runtime has not been initialized yet, the inferior_ptid is + the only ptid that there is. */ + if (!ravenscar_runtime_initialized ()) + return; + + /* Make sure we set base_ptid before calling ravenscar_running_thread + as the latter relies on it. */ + inferior_ptid = ravenscar_running_thread (); + gdb_assert (!ptid_equal (inferior_ptid, null_ptid)); + + /* The running thread may not have been added to + system.tasking.debug's list yet; so ravenscar_find_new_threads + may not always add it to the thread list. Add it here. */ + if (!find_thread_ptid (inferior_ptid)) + add_thread (inferior_ptid); +} + +/* The Ravenscar Runtime exports a symbol which contains the ID of + the thread that is currently running. Try to locate that symbol + and return its associated minimal symbol. + Return NULL if not found. */ + +static struct minimal_symbol * +get_running_thread_msymbol (void) +{ + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol (running_thread_name, NULL, NULL); + if (!msym) + /* Older versions of the GNAT runtime were using a different + (less ideal) name for the symbol where the active thread ID + is stored. If we couldn't find the symbol using the latest + name, then try the old one. */ + msym = lookup_minimal_symbol ("running_thread", NULL, NULL); + + return msym; +} + +/* Return True if the Ada Ravenscar run-time can be found in the + application. */ + +static int +has_ravenscar_runtime (void) +{ + struct minimal_symbol *msym_ravenscar_runtime_initializer = + lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL); + struct minimal_symbol *msym_known_tasks = + lookup_minimal_symbol (known_tasks_name, NULL, NULL); + struct minimal_symbol *msym_running_thread = get_running_thread_msymbol (); + + return (msym_ravenscar_runtime_initializer + && msym_known_tasks + && msym_running_thread); +} + +/* Return True if the Ada Ravenscar run-time can be found in the + application, and if it has been initialized on target. */ + +static int +ravenscar_runtime_initialized (void) +{ + return (!(ptid_equal (ravenscar_running_thread (), null_ptid))); +} + +/* Return the ID of the thread that is currently running. + Return 0 if the ID could not be determined. */ + +static CORE_ADDR +get_running_thread_id (void) +{ + const struct minimal_symbol *object_msym = get_running_thread_msymbol (); + int object_size; + int buf_size; + char *buf; + CORE_ADDR object_addr; + struct type *builtin_type_void_data_ptr = + builtin_type (target_gdbarch)->builtin_data_ptr; + + if (!object_msym) + return 0; + + object_addr = SYMBOL_VALUE_ADDRESS (object_msym); + object_size = TYPE_LENGTH (builtin_type_void_data_ptr); + buf_size = object_size; + buf = alloca (buf_size); + read_memory (object_addr, buf, buf_size); + return extract_typed_address (buf, builtin_type_void_data_ptr); +} + +static void +ravenscar_close (int quitting) +{ + ravenscar_is_open = 0; +} + +static void +ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step, + enum target_signal siggnal) +{ + struct target_ops *beneath = find_target_beneath (ops); + + inferior_ptid = base_ptid; + beneath->to_resume (beneath, base_ptid, step, siggnal); +} + +static ptid_t +ravenscar_wait (struct target_ops *ops, ptid_t ptid, + struct target_waitstatus *status, + int options) +{ + struct target_ops *beneath = find_target_beneath (ops); + + inferior_ptid = base_ptid; + beneath->to_wait (beneath, base_ptid, status, 0); + ravenscar_find_new_threads (ops); + ravenscar_update_inferior_ptid (); + return inferior_ptid; +} + +/* Add the thread associated to the given TASK to the thread list + (if the thread has already been added, this is a no-op). */ + +static void +ravenscar_add_thread (struct ada_task_info *task) +{ + if (find_thread_ptid (task->ptid) == NULL) + add_thread (task->ptid); +} + +static void +ravenscar_find_new_threads (struct target_ops *ops) +{ + ada_build_task_list (0); + + /* Do not clear the thread list before adding the Ada task, to keep + the thread that the process stratum has included into it + (base_ptid) and the running thread, that may not have been included + to system.tasking.debug's list yet. */ + + iterate_over_live_ada_tasks (ravenscar_add_thread); +} + +static ptid_t +ravenscar_running_thread (void) +{ + CORE_ADDR tid = get_running_thread_id (); + + if (tid == 0) + return null_ptid; + else + return ptid_build (ptid_get_pid (base_ptid), 0, tid); +} + +static char * +ravenscar_extra_thread_info (struct thread_info *tp) +{ + return "Ravenscar task"; +} + +static int +ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid) +{ + /* Ravenscar tasks are non-terminating. */ + return 1; +} + +static char * +ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid) +{ + static char buf[30]; + + snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid)); + return buf; +} + +static void +ravenscar_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct target_ops *beneath = find_target_beneath (ops); + + if (!ravenscar_runtime_initialized () + || ptid_equal (inferior_ptid, base_magic_null_ptid) + || ptid_equal (inferior_ptid, ravenscar_running_thread ())) + beneath->to_fetch_registers (beneath, regcache, regnum); + else + current_arch_ops->to_fetch_registers (regcache, regnum); +} + +static void +ravenscar_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct target_ops *beneath = find_target_beneath (ops); + + if (!ravenscar_runtime_initialized () + || ptid_equal (inferior_ptid, base_magic_null_ptid) + || ptid_equal (inferior_ptid, ravenscar_running_thread ())) + beneath->to_store_registers (beneath, regcache, regnum); + else + current_arch_ops->to_store_registers (regcache, regnum); +} + +static void +ravenscar_prepare_to_store (struct regcache *regcache) +{ + struct target_ops *beneath = find_target_beneath (&ravenscar_ops); + + if (!ravenscar_runtime_initialized () + || ptid_equal (inferior_ptid, base_magic_null_ptid) + || ptid_equal (inferior_ptid, ravenscar_running_thread ())) + beneath->to_prepare_to_store (regcache); + else + current_arch_ops->to_prepare_to_store (regcache); +} + +static void +ravenscar_mourn_inferior (struct target_ops *ops) +{ + struct target_ops *beneath = find_target_beneath (&ravenscar_ops); + + base_ptid = null_ptid; + beneath->to_mourn_inferior (beneath); + unpush_target (&ravenscar_ops); +} + +/* Observer on inferior_created: push ravenscar thread stratum if needed. */ + +static void +ravenscar_inferior_created (struct target_ops *target, int from_tty) +{ + if (ravenscar_task_support + && has_ravenscar_runtime ()) + ravenscar_initialize (NULL, 0); +} + +void +ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops) +{ + /* FIXME: To be clean, we would need to handle a list of + architectures, just like in remote-wtx-hw.c. However, for now the + only Ravenscar run-time for bare board that is implemented in + GNAT is for only one architecture: erc32-elf. So no need to care about + that for now... */ + current_arch_ops = ops; +} + +/* Initialize Ravenscar support. */ + +static void +ravenscar_initialize (char *name, int from_tty) +{ + if (ravenscar_is_open) + return; + + base_magic_null_ptid = inferior_ptid; + ravenscar_update_inferior_ptid (); + push_target (&ravenscar_ops); + ravenscar_is_open = 1; +} + +static ptid_t +ravenscar_get_ada_task_ptid (long lwp, long thread) +{ + return ptid_build (ptid_get_pid (base_ptid), 0, thread); +} + +static void +init_ravenscar_thread_ops (void) +{ + ravenscar_ops.to_shortname = "ravenscar"; + ravenscar_ops.to_longname = "Ravenscar tasks."; + ravenscar_ops.to_doc = "Ravenscar tasks support."; + ravenscar_ops.to_close = ravenscar_close; + ravenscar_ops.to_resume = ravenscar_resume; + ravenscar_ops.to_wait = ravenscar_wait; + ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers; + ravenscar_ops.to_store_registers = ravenscar_store_registers; + ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store; + ravenscar_ops.to_thread_alive = ravenscar_thread_alive; + ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads; + ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str; + ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info; + ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid; + ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior; + ravenscar_ops.to_has_all_memory = default_child_has_all_memory; + ravenscar_ops.to_has_memory = default_child_has_memory; + ravenscar_ops.to_has_stack = default_child_has_stack; + ravenscar_ops.to_has_registers = default_child_has_registers; + ravenscar_ops.to_has_execution = default_child_has_execution; + ravenscar_ops.to_stratum = thread_stratum; + ravenscar_ops.to_magic = OPS_MAGIC; +} + +/* Command-list for the "set/show ravenscar" prefix command. */ +static struct cmd_list_element *set_ravenscar_list; +static struct cmd_list_element *show_ravenscar_list; + +/* Implement the "set ravenscar" prefix command. */ + +static void +set_ravenscar_command (char *arg, int from_tty) +{ + printf_unfiltered (_(\ +"\"set ravenscar\" must be followed by the name of a setting.\n")); + help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout); +} + +/* Implement the "show ravenscar" prefix command. */ + +static void +show_ravenscar_command (char *args, int from_tty) +{ + cmd_show_list (show_ravenscar_list, from_tty, ""); +} + +/* Implement the "show ravenscar task-switching" command. */ + +static void +show_ravenscar_task_switching_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + if (ravenscar_task_support) + fprintf_filtered (file, _("\ +Support for Ravenscar task/thread switching is enabled\n")); + else + fprintf_filtered (file, _("\ +Support for Ravenscar task/thread switching is disabled\n")); +} + +/* Module startup initialization function, automagically called by + init.c. */ + +void +_initialize_ravenscar (void) +{ + init_ravenscar_thread_ops (); + base_ptid = null_ptid; + + /* Notice when the inferior is created in order to push the + ravenscar ops if needed. */ + observer_attach_inferior_created (ravenscar_inferior_created); + + add_target (&ravenscar_ops); + + add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command, + _("Prefix command for changing Ravenscar-specific settings"), + &set_ravenscar_list, "set ravenscar ", 0, &setlist); + + add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command, + _("Prefix command for showing Ravenscar-specific settings"), + &show_ravenscar_list, "show ravenscar ", 0, &showlist); + + add_setshow_boolean_cmd ("task-switching", class_obscure, + &ravenscar_task_support, _("\ +Enable or disable support for GNAT Ravenscar tasks"), _("\ +Show whether support for GNAT Ravenscar tasks is enabled"), + _("\ +Enable or disable support for task/thread switching with the GNAT\n\ +Ravenscar run-time library for bareboard configuration."), + NULL, show_ravenscar_task_switching_command, + &set_ravenscar_list, &show_ravenscar_list); +} diff --git a/contrib/gdb-7/gdb/ravenscar-thread.h b/contrib/gdb-7/gdb/ravenscar-thread.h new file mode 100644 index 0000000000..0e1bfa7d7b --- /dev/null +++ b/contrib/gdb-7/gdb/ravenscar-thread.h @@ -0,0 +1,41 @@ +/* Ada Ravenscar thread support. + + Copyright 2004, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef RAVENSCAR_THREAD_H +#define RAVENSCAR_THREAD_H + +/* Architecture-specific hooks. */ + +struct ravenscar_arch_ops +{ + void (*to_fetch_registers) (struct regcache *, int); + void (*to_store_registers) (struct regcache *, int); + void (*to_prepare_to_store) (struct regcache *); +}; + +/* Register implementations for target ops to_store_registers, + to_prepare_to_store and to_fetch_registers when the inferior_ptid + is different from the running thread. In that case, the registers + are saved in a architecture-specific location. */ +/* FIXME: only one architecture can be registered for now. See + implementation. */ + +extern void ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops); + +#endif /* !defined (RAVENSCAR_THREAD_H) */ diff --git a/contrib/gdb-7/gdb/record.c b/contrib/gdb-7/gdb/record.c index 3698b586ea..65eaa111a7 100644 --- a/contrib/gdb-7/gdb/record.c +++ b/contrib/gdb-7/gdb/record.c @@ -1,6 +1,6 @@ /* Process record and replay target for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -454,7 +454,7 @@ record_get_loc (struct record_entry *rec) return rec->u.reg.u.buf; case record_end: default: - gdb_assert (0); + gdb_assert_not_reached ("unexpected record_entry type"); return NULL; } } @@ -495,7 +495,7 @@ record_arch_list_add_mem (CORE_ADDR addr, int len) "record list.\n", paddress (target_gdbarch, addr), len); - if (!addr) /* FIXME: Why? Some arch must permit it... */ + if (!addr) /* FIXME: Why? Some arch must permit it... */ return 0; rec = record_mem_alloc (addr, len); @@ -739,8 +739,8 @@ record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch, { entry->u.mem.mem_entry_not_accessible = 1; if (record_debug) - warning ("Process record: error reading memory at " - "addr = %s len = %d.", + warning (_("Process record: error reading memory at " + "addr = %s len = %d."), paddress (gdbarch, entry->u.mem.addr), entry->u.mem.len); } @@ -752,8 +752,8 @@ record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch, { entry->u.mem.mem_entry_not_accessible = 1; if (record_debug) - warning ("Process record: error writing memory at " - "addr = %s len = %d.", + warning (_("Process record: error writing memory at " + "addr = %s len = %d."), paddress (gdbarch, entry->u.mem.addr), entry->u.mem.len); } @@ -865,15 +865,20 @@ record_open_1 (char *name, int from_tty) if (!tmp_to_wait) error (_("Could not find 'to_wait' method on the target stack.")); if (!tmp_to_store_registers) - error (_("Could not find 'to_store_registers' method on the target stack.")); + error (_("Could not find 'to_store_registers' " + "method on the target stack.")); if (!tmp_to_insert_breakpoint) - error (_("Could not find 'to_insert_breakpoint' method on the target stack.")); + error (_("Could not find 'to_insert_breakpoint' " + "method on the target stack.")); if (!tmp_to_remove_breakpoint) - error (_("Could not find 'to_remove_breakpoint' method on the target stack.")); + error (_("Could not find 'to_remove_breakpoint' " + "method on the target stack.")); if (!tmp_to_stopped_by_watchpoint) - error (_("Could not find 'to_stopped_by_watchpoint' method on the target stack.")); + error (_("Could not find 'to_stopped_by_watchpoint' " + "method on the target stack.")); if (!tmp_to_stopped_data_address) - error (_("Could not find 'to_stopped_data_address' method on the target stack.")); + error (_("Could not find 'to_stopped_data_address' " + "method on the target stack.")); push_target (&record_ops); } @@ -962,7 +967,7 @@ record_open (char *name, int from_tty) record_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint; record_beneath_to_stopped_data_address = tmp_to_stopped_data_address; - if (current_target.to_stratum == core_stratum) + if (core_bfd) record_core_open_1 (name, from_tty); else record_open_1 (name, from_tty); @@ -1011,9 +1016,43 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step, if (!RECORD_IS_REPLAY) { + struct gdbarch *gdbarch = target_thread_architecture (ptid); + record_message (get_current_regcache (), signal); - record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1, - signal); + + if (!step) + { + /* This is not hard single step. */ + if (!gdbarch_software_single_step_p (gdbarch)) + { + /* This is a normal continue. */ + step = 1; + } + else + { + /* This arch support soft sigle step. */ + if (single_step_breakpoints_inserted ()) + { + /* This is a soft single step. */ + record_resume_step = 1; + } + else + { + /* This is a continue. + Try to insert a soft single step breakpoint. */ + if (!gdbarch_software_single_step (gdbarch, + get_current_frame ())) + { + /* This system don't want use soft single step. + Use hard sigle step. */ + step = 1; + } + } + } + } + + record_beneath_to_resume (record_beneath_to_resume_ops, + ptid, step, signal); } } @@ -1089,12 +1128,16 @@ record_wait (struct target_ops *ops, /* This is not a single step. */ ptid_t ret; CORE_ADDR tmp_pc; + struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid); while (1) { ret = record_beneath_to_wait (record_beneath_to_wait_ops, ptid, status, options); + if (single_step_breakpoints_inserted ()) + remove_single_step_breakpoints (); + if (record_resume_step) return ret; @@ -1124,7 +1167,8 @@ record_wait (struct target_ops *ops, handle it. */ if (software_breakpoint_inserted_here_p (aspace, tmp_pc)) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch + = get_regcache_arch (regcache); CORE_ADDR decr_pc_after_break = gdbarch_decr_pc_after_break (gdbarch); if (decr_pc_after_break) @@ -1134,8 +1178,12 @@ record_wait (struct target_ops *ops, } else { - /* This must be a single-step trap. Record the - insn and issue another step. */ + /* This is a single-step trap. Record the + insn and issue another step. + FIXME: this part can be a random SIGTRAP too. + But GDB cannot handle it. */ + int step = 1; + if (!record_message_wrapper_safe (regcache, TARGET_SIGNAL_0)) { @@ -1144,8 +1192,20 @@ record_wait (struct target_ops *ops, break; } + if (gdbarch_software_single_step_p (gdbarch)) + { + /* Try to insert the software single step breakpoint. + If insert success, set step to 0. */ + set_executing (inferior_ptid, 0); + reinit_frame_cache (); + if (gdbarch_software_single_step (gdbarch, + get_current_frame ())) + step = 0; + set_executing (inferior_ptid, 1); + } + record_beneath_to_resume (record_beneath_to_resume_ops, - ptid, 1, + ptid, step, TARGET_SIGNAL_0); continue; } @@ -1279,8 +1339,9 @@ record_wait (struct target_ops *ops, if (record_hw_watchpoint) { if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ -Process record: hit hw watchpoint.\n"); + fprintf_unfiltered (gdb_stdlog, + "Process record: hit hw " + "watchpoint.\n"); continue_flag = 0; } /* Check target signal */ @@ -1862,8 +1923,8 @@ record_core_remove_breakpoint (struct gdbarch *gdbarch, /* "to_has_execution" method for prec over corefile. */ -int -record_core_has_execution (struct target_ops *ops) +static int +record_core_has_execution (struct target_ops *ops, ptid_t the_ptid) { return 1; } @@ -1975,8 +2036,8 @@ static struct cmd_list_element *record_cmdlist, *set_record_cmdlist, static void set_record_command (char *args, int from_tty) { - printf_unfiltered (_("\ -\"set record\" must be followed by an apporpriate subcommand.\n")); + printf_unfiltered (_("\"set record\" must be followed " + "by an apporpriate subcommand.\n")); help_list (set_record_cmdlist, "set record ", all_commands, gdb_stdout); } @@ -2093,7 +2154,7 @@ bfdcore_read (bfd *obfd, asection *osec, void *buf, int len, int *offset) if (ret) *offset += len; else - error (_("Failed to read %d bytes from core file %s ('%s').\n"), + error (_("Failed to read %d bytes from core file %s ('%s')."), len, bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ())); } @@ -2153,12 +2214,12 @@ record_restore (void) /* Now need to find our special note section. */ osec = bfd_get_section_by_name (core_bfd, "null0"); - osec_size = bfd_section_size (core_bfd, osec); if (record_debug) fprintf_unfiltered (gdb_stdlog, "Find precord section %s.\n", osec ? "succeeded" : "failed"); if (osec == NULL) return; + osec_size = bfd_section_size (core_bfd, osec); if (record_debug) fprintf_unfiltered (gdb_stdlog, "%s", bfd_section_name (core_bfd, osec)); @@ -2168,8 +2229,9 @@ record_restore (void) error (_("Version mis-match or file format error in core file %s."), bfd_get_filename (core_bfd)); if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Reading 4-byte magic cookie RECORD_FILE_MAGIC (0x%s)\n", + fprintf_unfiltered (gdb_stdlog, + " Reading 4-byte magic cookie " + "RECORD_FILE_MAGIC (0x%s)\n", phex_nz (netorder32 (magic), 4)); /* Restore the entries in recfd into record_arch_list_head and @@ -2206,8 +2268,9 @@ record_restore (void) rec->u.reg.len, &bfd_offset); if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Reading register %d (1 plus %lu plus %d bytes)\n", + fprintf_unfiltered (gdb_stdlog, + " Reading register %d (1 " + "plus %lu plus %d bytes)\n", rec->u.reg.num, (unsigned long) sizeof (regnum), rec->u.reg.len); @@ -2231,8 +2294,9 @@ record_restore (void) rec->u.mem.len, &bfd_offset); if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Reading memory %s (1 plus %lu plus %lu plus %d bytes)\n", + fprintf_unfiltered (gdb_stdlog, + " Reading memory %s (1 plus " + "%lu plus %lu plus %d bytes)\n", paddress (get_current_arch (), rec->u.mem.addr), (unsigned long) sizeof (addr), @@ -2257,8 +2321,9 @@ record_restore (void) rec->u.end.insn_num = count; record_insn_count = count + 1; if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Reading record_end (1 + %lu + %lu bytes), offset == %s\n", + fprintf_unfiltered (gdb_stdlog, + " Reading record_end (1 + " + "%lu + %lu bytes), offset == %s\n", (unsigned long) sizeof (signal), (unsigned long) sizeof (count), paddress (get_current_arch (), @@ -2308,7 +2373,7 @@ bfdcore_write (bfd *obfd, asection *osec, void *buf, int len, int *offset) if (ret) *offset += len; else - error (_("Failed to write %d bytes to core file %s ('%s').\n"), + error (_("Failed to write %d bytes to core file %s ('%s')."), len, bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ())); } @@ -2435,8 +2500,9 @@ cmd_record_save (char *args, int from_tty) /* Write the magic code. */ magic = RECORD_FILE_MAGIC; if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Writing 4-byte magic cookie RECORD_FILE_MAGIC (0x%s)\n", + fprintf_unfiltered (gdb_stdlog, + " Writing 4-byte magic cookie " + "RECORD_FILE_MAGIC (0x%s)\n", phex_nz (magic, 4)); bfdcore_write (obfd, osec, &magic, sizeof (magic), &bfd_offset); @@ -2459,8 +2525,9 @@ cmd_record_save (char *args, int from_tty) { case record_reg: /* reg */ if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Writing register %d (1 plus %lu plus %d bytes)\n", + fprintf_unfiltered (gdb_stdlog, + " Writing register %d (1 " + "plus %lu plus %d bytes)\n", record_list->u.reg.num, (unsigned long) sizeof (regnum), record_list->u.reg.len); @@ -2477,8 +2544,9 @@ cmd_record_save (char *args, int from_tty) case record_mem: /* mem */ if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Writing memory %s (1 plus %lu plus %lu plus %d bytes)\n", + fprintf_unfiltered (gdb_stdlog, + " Writing memory %s (1 plus " + "%lu plus %lu plus %d bytes)\n", paddress (gdbarch, record_list->u.mem.addr), (unsigned long) sizeof (addr), @@ -2501,8 +2569,9 @@ cmd_record_save (char *args, int from_tty) case record_end: if (record_debug) - fprintf_unfiltered (gdb_stdlog, "\ - Writing record_end (1 + %lu + %lu bytes)\n", + fprintf_unfiltered (gdb_stdlog, + " Writing record_end (1 + " + "%lu + %lu bytes)\n", (unsigned long) sizeof (signal), (unsigned long) sizeof (count)); /* Write signal value. */ @@ -2714,8 +2783,8 @@ Argument is filename. File must be created with 'record save'."), add_setshow_boolean_cmd ("stop-at-limit", no_class, &record_stop_at_limit, _("\ Set whether record/replay stops when record/replay buffer becomes full."), _("\ -Show whether record/replay stops when record/replay buffer becomes full."), _("\ -Default is ON.\n\ +Show whether record/replay stops when record/replay buffer becomes full."), + _("Default is ON.\n\ When ON, if the record/replay buffer becomes full, ask user what to do.\n\ When OFF, if the record/replay buffer becomes full,\n\ delete the oldest recorded instruction to make room for each new one."), diff --git a/contrib/gdb-7/gdb/record.h b/contrib/gdb-7/gdb/record.h index a4b20d2ec2..7ddf548a8a 100644 --- a/contrib/gdb-7/gdb/record.h +++ b/contrib/gdb-7/gdb/record.h @@ -1,6 +1,6 @@ /* Process record and replay target for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/regcache.c b/contrib/gdb-7/gdb/regcache.c index 5342586759..8b4d77ccc0 100644 --- a/contrib/gdb-7/gdb/regcache.c +++ b/contrib/gdb-7/gdb/regcache.c @@ -1,7 +1,7 @@ /* Cache and manage the values of registers for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001, - 2002, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +29,7 @@ #include "gdb_string.h" #include "gdbcmd.h" /* For maintenanceprintlist. */ #include "observer.h" +#include "exceptions.h" /* * DATA STRUCTURE @@ -37,7 +38,7 @@ */ /* Per-architecture object describing the layout of a register cache. - Computed once when the architecture is created */ + Computed once when the architecture is created. */ struct gdbarch_data *regcache_descr_handle; @@ -53,7 +54,7 @@ struct regcache_descr cache. */ int nr_raw_registers; long sizeof_raw_registers; - long sizeof_raw_register_valid_p; + long sizeof_raw_register_status; /* The cooked register space. Each cooked register in the range [0..NR_RAW_REGISTERS) is direct-mapped onto the corresponding raw @@ -63,14 +64,12 @@ struct regcache_descr gdbarch_pseudo_register_read and gdbarch_pseudo_register_write. */ int nr_cooked_registers; long sizeof_cooked_registers; - long sizeof_cooked_register_valid_p; + long sizeof_cooked_register_status; /* Offset and size (in 8 bit bytes), of reach register in the register cache. All registers (including those in the range - [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an offset. - Assigning all registers an offset makes it possible to keep - legacy code, such as that found in read_register_bytes() and - write_register_bytes() working. */ + [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an + offset. */ long *register_offset; long *sizeof_register; @@ -94,25 +93,20 @@ init_regcache_descr (struct gdbarch *gdbarch) either mapped onto raw-registers or memory. */ descr->nr_cooked_registers = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); - descr->sizeof_cooked_register_valid_p = gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs - (gdbarch); + descr->sizeof_cooked_register_status + = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); /* Fill in a table of register types. */ descr->register_type - = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, struct type *); + = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, + struct type *); for (i = 0; i < descr->nr_cooked_registers; i++) descr->register_type[i] = gdbarch_register_type (gdbarch, i); /* Construct a strictly RAW register cache. Don't allow pseudo's into the register cache. */ descr->nr_raw_registers = gdbarch_num_regs (gdbarch); - - /* FIXME: cagney/2002-08-13: Overallocate the register_valid_p - array. This pretects GDB from erant code that accesses elements - of the global register_valid_p[] array in the range - [gdbarch_num_regs .. gdbarch_num_regs + gdbarch_num_pseudo_regs). */ - descr->sizeof_raw_register_valid_p = descr->sizeof_cooked_register_valid_p; + descr->sizeof_raw_register_status = gdbarch_num_regs (gdbarch); /* Lay out the register cache. @@ -128,24 +122,27 @@ init_regcache_descr (struct gdbarch *gdbarch) = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long); descr->register_offset = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long); - for (i = 0; i < descr->nr_cooked_registers; i++) + for (i = 0; i < descr->nr_raw_registers; i++) { descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]); descr->register_offset[i] = offset; offset += descr->sizeof_register[i]; gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]); } - /* Set the real size of the register cache buffer. */ + /* Set the real size of the raw register cache buffer. */ + descr->sizeof_raw_registers = offset; + + for (; i < descr->nr_cooked_registers; i++) + { + descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]); + descr->register_offset[i] = offset; + offset += descr->sizeof_register[i]; + gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]); + } + /* Set the real size of the readonly register cache buffer. */ descr->sizeof_cooked_registers = offset; } - /* FIXME: cagney/2002-05-22: Should only need to allocate space for - the raw registers. Unfortunately some code still accesses the - register array directly using the global registers[]. Until that - code has been purged, play safe and over allocating the register - buffer. Ulgh! */ - descr->sizeof_raw_registers = descr->sizeof_cooked_registers; - return descr; } @@ -197,11 +194,8 @@ struct regcache full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a read/write register cache can only hold [0 .. gdbarch_num_regs). */ gdb_byte *registers; - /* Register cache status: - register_valid_p[REG] == 0 if REG value is not in the cache - > 0 if REG value is in the cache - < 0 if REG value is permanently unavailable */ - signed char *register_valid_p; + /* Register cache status. */ + signed char *register_status; /* Is this a read-only cache? A read-only cache is used for saving the target's register state (e.g, across an inferior function call or just before forcing a function return). A read-only @@ -214,8 +208,9 @@ struct regcache ptid_t ptid; }; -struct regcache * -regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace) +static struct regcache * +regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace, + int readonly_p) { struct regcache_descr *descr; struct regcache *regcache; @@ -224,23 +219,39 @@ regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace) descr = regcache_descr (gdbarch); regcache = XMALLOC (struct regcache); regcache->descr = descr; - regcache->registers - = XCALLOC (descr->sizeof_raw_registers, gdb_byte); - regcache->register_valid_p - = XCALLOC (descr->sizeof_raw_register_valid_p, gdb_byte); + regcache->readonly_p = readonly_p; + if (readonly_p) + { + regcache->registers + = XCALLOC (descr->sizeof_cooked_registers, gdb_byte); + regcache->register_status + = XCALLOC (descr->sizeof_cooked_register_status, gdb_byte); + } + else + { + regcache->registers + = XCALLOC (descr->sizeof_raw_registers, gdb_byte); + regcache->register_status + = XCALLOC (descr->sizeof_raw_register_status, gdb_byte); + } regcache->aspace = aspace; - regcache->readonly_p = 1; regcache->ptid = minus_one_ptid; return regcache; } +struct regcache * +regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace) +{ + return regcache_xmalloc_1 (gdbarch, aspace, 1); +} + void regcache_xfree (struct regcache *regcache) { if (regcache == NULL) return; xfree (regcache->registers); - xfree (regcache->register_valid_p); + xfree (regcache->register_status); xfree (regcache); } @@ -292,7 +303,8 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, gdb_assert (dst->readonly_p); /* Clear the dest. */ memset (dst->registers, 0, dst->descr->sizeof_cooked_registers); - memset (dst->register_valid_p, 0, dst->descr->sizeof_cooked_register_valid_p); + memset (dst->register_status, 0, + dst->descr->sizeof_cooked_register_status); /* Copy over any registers (identified by their membership in the save_reggroup) and mark them as valid. The full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) range is checked since some architectures need @@ -301,14 +313,19 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, { if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup)) { - int valid = cooked_read (src, regnum, buf); + enum register_status status = cooked_read (src, regnum, buf); - if (valid) + if (status == REG_VALID) + memcpy (register_buffer (dst, regnum), buf, + register_size (gdbarch, regnum)); + else { - memcpy (register_buffer (dst, regnum), buf, + gdb_assert (status != REG_UNKNOWN); + + memset (register_buffer (dst, regnum), 0, register_size (gdbarch, regnum)); - dst->register_valid_p[regnum] = 1; } + dst->register_status[regnum] = status; } } } @@ -341,21 +358,14 @@ regcache_restore (struct regcache *dst, } } -static int +static enum register_status do_cooked_read (void *src, int regnum, gdb_byte *buf) { struct regcache *regcache = src; - if (!regcache->register_valid_p[regnum] && regcache->readonly_p) - /* Don't even think about fetching a register from a read-only - cache when the register isn't yet valid. There isn't a target - from which the register value can be fetched. */ - return 0; - regcache_cooked_read (regcache, regnum, buf); - return 1; + return regcache_cooked_read (regcache, regnum, buf); } - void regcache_cpy (struct regcache *dst, struct regcache *src) { @@ -378,13 +388,15 @@ regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src) gdb_assert (src != NULL && dst != NULL); gdb_assert (src->descr->gdbarch == dst->descr->gdbarch); /* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough - move of data into the current regcache. Doing this would be - silly - it would mean that valid_p would be completely invalid. */ - gdb_assert (dst->readonly_p); - - memcpy (dst->registers, src->registers, dst->descr->sizeof_raw_registers); - memcpy (dst->register_valid_p, src->register_valid_p, - dst->descr->sizeof_raw_register_valid_p); + move of data into a thread's regcache. Doing this would be silly + - it would mean that regcache->register_status would be + completely invalid. */ + gdb_assert (dst->readonly_p && src->readonly_p); + + memcpy (dst->registers, src->registers, + dst->descr->sizeof_cooked_registers); + memcpy (dst->register_status, src->register_status, + dst->descr->sizeof_cooked_register_status); } struct regcache * @@ -397,18 +409,8 @@ regcache_dup (struct regcache *src) return newbuf; } -struct regcache * -regcache_dup_no_passthrough (struct regcache *src) -{ - struct regcache *newbuf; - - newbuf = regcache_xmalloc (src->descr->gdbarch, get_regcache_aspace (src)); - regcache_cpy_no_passthrough (newbuf, src); - return newbuf; -} - int -regcache_valid_p (const struct regcache *regcache, int regnum) +regcache_register_status (const struct regcache *regcache, int regnum) { gdb_assert (regcache != NULL); gdb_assert (regnum >= 0); @@ -417,7 +419,7 @@ regcache_valid_p (const struct regcache *regcache, int regnum) else gdb_assert (regnum < regcache->descr->nr_raw_registers); - return regcache->register_valid_p[regnum]; + return regcache->register_status[regnum]; } void @@ -427,7 +429,7 @@ regcache_invalidate (struct regcache *regcache, int regnum) gdb_assert (regnum >= 0); gdb_assert (!regcache->readonly_p); gdb_assert (regnum < regcache->descr->nr_raw_registers); - regcache->register_valid_p[regnum] = 0; + regcache->register_status[regnum] = REG_UNKNOWN; } @@ -451,17 +453,25 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) { struct regcache_list *list; struct regcache *new_regcache; + struct address_space *aspace; for (list = current_regcache; list; list = list->next) if (ptid_equal (list->regcache->ptid, ptid) && get_regcache_arch (list->regcache) == gdbarch) return list->regcache; - new_regcache = regcache_xmalloc (gdbarch, - target_thread_address_space (ptid)); - new_regcache->readonly_p = 0; + /* For the benefit of "maint print registers" & co when debugging an + executable, allow dumping the regcache even when there is no + thread selected (target_thread_address_space internal-errors if + no address space is found). Note that normal user commands will + fail higher up on the call stack due to no + target_has_registers. */ + aspace = (ptid_equal (null_ptid, ptid) + ? NULL + : target_thread_address_space (ptid)); + + new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0); new_regcache->ptid = ptid; - gdb_assert (new_regcache->aspace != NULL); list = xmalloc (sizeof (struct regcache_list)); list->regcache = new_regcache; @@ -528,6 +538,7 @@ void registers_changed_ptid (ptid_t ptid) { struct regcache_list *list, **list_link; + int wildcard = ptid_equal (ptid, minus_one_ptid); list = current_regcache; list_link = ¤t_regcache; @@ -548,13 +559,24 @@ registers_changed_ptid (ptid_t ptid) list = *list_link; } - current_regcache = NULL; + if (wildcard || ptid_equal (ptid, current_thread_ptid)) + { + current_thread_ptid = null_ptid; + current_thread_arch = NULL; + } - current_thread_ptid = null_ptid; - current_thread_arch = NULL; + if (wildcard || ptid_equal (ptid, inferior_ptid)) + { + /* We just deleted the regcache of the current thread. Need to + forget about any frames we have cached, too. */ + reinit_frame_cache (); + } +} - /* Need to forget about any frames we have cached, too. */ - reinit_frame_cache (); +void +registers_changed (void) +{ + registers_changed_ptid (minus_one_ptid); /* Force cleanup of any alloca areas if using C alloca instead of a builtin alloca. This particular call is used to clean up @@ -564,13 +586,7 @@ registers_changed_ptid (ptid_t ptid) alloca (0); } -void -registers_changed (void) -{ - registers_changed_ptid (minus_one_ptid); -} - -void +enum register_status regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf) { gdb_assert (regcache != NULL && buf != NULL); @@ -579,58 +595,68 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf) to the current thread. This switching shouldn't be necessary only there is still only one target side register cache. Sigh! On the bright side, at least there is a regcache object. */ - if (!regcache->readonly_p) + if (!regcache->readonly_p + && regcache_register_status (regcache, regnum) == REG_UNKNOWN) { - if (!regcache_valid_p (regcache, regnum)) - { - struct cleanup *old_chain = save_inferior_ptid (); + struct cleanup *old_chain = save_inferior_ptid (); - inferior_ptid = regcache->ptid; - target_fetch_registers (regcache, regnum); - do_cleanups (old_chain); - } -#if 0 - /* FIXME: cagney/2004-08-07: At present a number of targets - forget (or didn't know that they needed) to set this leading to - panics. Also is the problem that targets need to indicate - that a register is in one of the possible states: valid, - undefined, unknown. The last of which isn't yet - possible. */ - gdb_assert (regcache_valid_p (regcache, regnum)); -#endif + inferior_ptid = regcache->ptid; + target_fetch_registers (regcache, regnum); + do_cleanups (old_chain); + + /* A number of targets can't access the whole set of raw + registers (because the debug API provides no means to get at + them). */ + if (regcache->register_status[regnum] == REG_UNKNOWN) + regcache->register_status[regnum] = REG_UNAVAILABLE; } - /* Copy the value directly into the register cache. */ - memcpy (buf, register_buffer (regcache, regnum), - regcache->descr->sizeof_register[regnum]); + + if (regcache->register_status[regnum] != REG_VALID) + memset (buf, 0, regcache->descr->sizeof_register[regnum]); + else + memcpy (buf, register_buffer (regcache, regnum), + regcache->descr->sizeof_register[regnum]); + + return regcache->register_status[regnum]; } -void +enum register_status regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val) { gdb_byte *buf; + enum register_status status; gdb_assert (regcache != NULL); gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers); buf = alloca (regcache->descr->sizeof_register[regnum]); - regcache_raw_read (regcache, regnum, buf); - (*val) = extract_signed_integer - (buf, regcache->descr->sizeof_register[regnum], - gdbarch_byte_order (regcache->descr->gdbarch)); + status = regcache_raw_read (regcache, regnum, buf); + if (status == REG_VALID) + *val = extract_signed_integer + (buf, regcache->descr->sizeof_register[regnum], + gdbarch_byte_order (regcache->descr->gdbarch)); + else + *val = 0; + return status; } -void +enum register_status regcache_raw_read_unsigned (struct regcache *regcache, int regnum, ULONGEST *val) { gdb_byte *buf; + enum register_status status; gdb_assert (regcache != NULL); gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers); buf = alloca (regcache->descr->sizeof_register[regnum]); - regcache_raw_read (regcache, regnum, buf); - (*val) = extract_unsigned_integer - (buf, regcache->descr->sizeof_register[regnum], - gdbarch_byte_order (regcache->descr->gdbarch)); + status = regcache_raw_read (regcache, regnum, buf); + if (status == REG_VALID) + *val = extract_unsigned_integer + (buf, regcache->descr->sizeof_register[regnum], + gdbarch_byte_order (regcache->descr->gdbarch)); + else + *val = 0; + return status; } void @@ -660,52 +686,71 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum, regcache_raw_write (regcache, regnum, buf); } -void +enum register_status regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf) { gdb_assert (regnum >= 0); gdb_assert (regnum < regcache->descr->nr_cooked_registers); if (regnum < regcache->descr->nr_raw_registers) - regcache_raw_read (regcache, regnum, buf); + return regcache_raw_read (regcache, regnum, buf); else if (regcache->readonly_p - && regnum < regcache->descr->nr_cooked_registers - && regcache->register_valid_p[regnum]) - /* Read-only register cache, perhaps the cooked value was cached? */ - memcpy (buf, register_buffer (regcache, regnum), - regcache->descr->sizeof_register[regnum]); + && regcache->register_status[regnum] != REG_UNKNOWN) + { + /* Read-only register cache, perhaps the cooked value was + cached? */ + struct gdbarch *gdbarch = regcache->descr->gdbarch; + + if (regcache->register_status[regnum] == REG_VALID) + memcpy (buf, register_buffer (regcache, regnum), + regcache->descr->sizeof_register[regnum]); + else + memset (buf, 0, regcache->descr->sizeof_register[regnum]); + + return regcache->register_status[regnum]; + } else - gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache, - regnum, buf); + return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache, + regnum, buf); } -void +enum register_status regcache_cooked_read_signed (struct regcache *regcache, int regnum, LONGEST *val) { + enum register_status status; gdb_byte *buf; gdb_assert (regcache != NULL); gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers); buf = alloca (regcache->descr->sizeof_register[regnum]); - regcache_cooked_read (regcache, regnum, buf); - (*val) = extract_signed_integer - (buf, regcache->descr->sizeof_register[regnum], - gdbarch_byte_order (regcache->descr->gdbarch)); + status = regcache_cooked_read (regcache, regnum, buf); + if (status == REG_VALID) + *val = extract_signed_integer + (buf, regcache->descr->sizeof_register[regnum], + gdbarch_byte_order (regcache->descr->gdbarch)); + else + *val = 0; + return status; } -void +enum register_status regcache_cooked_read_unsigned (struct regcache *regcache, int regnum, ULONGEST *val) { + enum register_status status; gdb_byte *buf; gdb_assert (regcache != NULL); gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers); buf = alloca (regcache->descr->sizeof_register[regnum]); - regcache_cooked_read (regcache, regnum, buf); - (*val) = extract_unsigned_integer - (buf, regcache->descr->sizeof_register[regnum], - gdbarch_byte_order (regcache->descr->gdbarch)); + status = regcache_cooked_read (regcache, regnum, buf); + if (status == REG_VALID) + *val = extract_unsigned_integer + (buf, regcache->descr->sizeof_register[regnum], + gdbarch_byte_order (regcache->descr->gdbarch)); + else + *val = 0; + return status; } void @@ -752,8 +797,8 @@ regcache_raw_write (struct regcache *regcache, int regnum, return; /* If we have a valid copy of the register, and new value == old - value, then don't bother doing the actual store. */ - if (regcache_valid_p (regcache, regnum) + value, then don't bother doing the actual store. */ + if (regcache_register_status (regcache, regnum) == REG_VALID && (memcmp (register_buffer (regcache, regnum), buf, regcache->descr->sizeof_register[regnum]) == 0)) return; @@ -764,7 +809,7 @@ regcache_raw_write (struct regcache *regcache, int regnum, target_prepare_to_store (regcache); memcpy (register_buffer (regcache, regnum), buf, regcache->descr->sizeof_register[regnum]); - regcache->register_valid_p[regnum] = 1; + regcache->register_status[regnum] = REG_VALID; target_store_registers (regcache, regnum); do_cleanups (old_chain); @@ -791,11 +836,12 @@ typedef void (regcache_read_ftype) (struct regcache *regcache, int regnum, typedef void (regcache_write_ftype) (struct regcache *regcache, int regnum, const void *buf); -static void +static enum register_status regcache_xfer_part (struct regcache *regcache, int regnum, int offset, int len, void *in, const void *out, - void (*read) (struct regcache *regcache, int regnum, - gdb_byte *buf), + enum register_status (*read) (struct regcache *regcache, + int regnum, + gdb_byte *buf), void (*write) (struct regcache *regcache, int regnum, const gdb_byte *buf)) { @@ -806,16 +852,20 @@ regcache_xfer_part (struct regcache *regcache, int regnum, gdb_assert (len >= 0 && offset + len <= descr->sizeof_register[regnum]); /* Something to do? */ if (offset + len == 0) - return; - /* Read (when needed) ... */ + return REG_VALID; + /* Read (when needed) ... */ if (in != NULL || offset > 0 || offset + len < descr->sizeof_register[regnum]) { + enum register_status status; + gdb_assert (read != NULL); - read (regcache, regnum, reg); + status = read (regcache, regnum, reg); + if (status != REG_VALID) + return status; } - /* ... modify ... */ + /* ... modify ... */ if (in != NULL) memcpy (in, reg + offset, len); if (out != NULL) @@ -826,17 +876,19 @@ regcache_xfer_part (struct regcache *regcache, int regnum, gdb_assert (write != NULL); write (regcache, regnum, reg); } + + return REG_VALID; } -void +enum register_status regcache_raw_read_part (struct regcache *regcache, int regnum, int offset, int len, gdb_byte *buf) { struct regcache_descr *descr = regcache->descr; gdb_assert (regnum >= 0 && regnum < descr->nr_raw_registers); - regcache_xfer_part (regcache, regnum, offset, len, buf, NULL, - regcache_raw_read, regcache_raw_write); + return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL, + regcache_raw_read, regcache_raw_write); } void @@ -850,15 +902,15 @@ regcache_raw_write_part (struct regcache *regcache, int regnum, regcache_raw_read, regcache_raw_write); } -void +enum register_status regcache_cooked_read_part (struct regcache *regcache, int regnum, int offset, int len, gdb_byte *buf) { struct regcache_descr *descr = regcache->descr; gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers); - regcache_xfer_part (regcache, regnum, offset, len, buf, NULL, - regcache_cooked_read, regcache_cooked_write); + return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL, + regcache_cooked_read, regcache_cooked_write); } void @@ -888,12 +940,18 @@ regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf) size = regcache->descr->sizeof_register[regnum]; if (buf) - memcpy (regbuf, buf, size); + { + memcpy (regbuf, buf, size); + regcache->register_status[regnum] = REG_VALID; + } else - memset (regbuf, 0, size); - - /* Mark the register as cached. */ - regcache->register_valid_p[regnum] = 1; + { + /* This memset not strictly necessary, but better than garbage + in case the register value manages to escape somewhere (due + to a bug, no less). */ + memset (regbuf, 0, size); + regcache->register_status[regnum] = REG_UNAVAILABLE; + } } /* Collect register REGNUM from REGCACHE and store its contents in BUF. */ @@ -929,9 +987,11 @@ regcache_read_pc (struct regcache *regcache) { ULONGEST raw_val; - regcache_cooked_read_unsigned (regcache, - gdbarch_pc_regnum (gdbarch), - &raw_val); + if (regcache_cooked_read_unsigned (regcache, + gdbarch_pc_regnum (gdbarch), + &raw_val) == REG_UNAVAILABLE) + throw_error (NOT_AVAILABLE_ERROR, _("PC register is not available")); + pc_val = gdbarch_addr_bits_remove (gdbarch, raw_val); } else @@ -992,7 +1052,8 @@ dump_endian_bytes (struct ui_file *file, enum bfd_endian endian, enum regcache_dump_what { - regcache_dump_none, regcache_dump_raw, regcache_dump_cooked, regcache_dump_groups + regcache_dump_none, regcache_dump_raw, + regcache_dump_cooked, regcache_dump_groups }; static void @@ -1016,8 +1077,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, regcache->descr->nr_cooked_registers); fprintf_unfiltered (file, "sizeof_raw_registers %ld\n", regcache->descr->sizeof_raw_registers); - fprintf_unfiltered (file, "sizeof_raw_register_valid_p %ld\n", - regcache->descr->sizeof_raw_register_valid_p); + fprintf_unfiltered (file, "sizeof_raw_register_status %ld\n", + regcache->descr->sizeof_raw_register_status); fprintf_unfiltered (file, "gdbarch_num_regs %d\n", gdbarch_num_regs (gdbarch)); fprintf_unfiltered (file, "gdbarch_num_pseudo_regs %d\n", @@ -1128,8 +1189,10 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, fprintf_unfiltered (file, "Raw value"); else if (regnum >= regcache->descr->nr_raw_registers) fprintf_unfiltered (file, ""); - else if (!regcache_valid_p (regcache, regnum)) + else if (regcache_register_status (regcache, regnum) == REG_UNKNOWN) fprintf_unfiltered (file, ""); + else if (regcache_register_status (regcache, regnum) == REG_UNAVAILABLE) + fprintf_unfiltered (file, ""); else { regcache_raw_read (regcache, regnum, buf); @@ -1147,11 +1210,20 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, fprintf_unfiltered (file, "Cooked value"); else { - regcache_cooked_read (regcache, regnum, buf); - fprintf_unfiltered (file, "0x"); - dump_endian_bytes (file, - gdbarch_byte_order (gdbarch), buf, - regcache->descr->sizeof_register[regnum]); + enum register_status status; + + status = regcache_cooked_read (regcache, regnum, buf); + if (status == REG_UNKNOWN) + fprintf_unfiltered (file, ""); + else if (status == REG_UNAVAILABLE) + fprintf_unfiltered (file, ""); + else + { + fprintf_unfiltered (file, "0x"); + dump_endian_bytes (file, + gdbarch_byte_order (gdbarch), buf, + regcache->descr->sizeof_register[regnum]); + } } } @@ -1171,7 +1243,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, { if (gdbarch_register_reggroup_p (gdbarch, regnum, group)) { - fprintf_unfiltered (file, "%s%s", sep, reggroup_name (group)); + fprintf_unfiltered (file, + "%s%s", sep, reggroup_name (group)); sep = ","; } } @@ -1241,7 +1314,8 @@ extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */ void _initialize_regcache (void) { - regcache_descr_handle = gdbarch_data_register_post_init (init_regcache_descr); + regcache_descr_handle + = gdbarch_data_register_post_init (init_regcache_descr); observer_attach_target_changed (regcache_observer_target_changed); observer_attach_thread_ptid_changed (regcache_thread_ptid_changed); @@ -1249,21 +1323,24 @@ _initialize_regcache (void) add_com ("flushregs", class_maintenance, reg_flush_command, _("Force gdb to flush its register cache (maintainer command)")); - add_cmd ("registers", class_maintenance, maintenance_print_registers, _("\ -Print the internal register configuration.\n\ -Takes an optional file parameter."), &maintenanceprintlist); + add_cmd ("registers", class_maintenance, maintenance_print_registers, + _("Print the internal register configuration.\n" + "Takes an optional file parameter."), &maintenanceprintlist); add_cmd ("raw-registers", class_maintenance, - maintenance_print_raw_registers, _("\ -Print the internal register configuration including raw values.\n\ -Takes an optional file parameter."), &maintenanceprintlist); + maintenance_print_raw_registers, + _("Print the internal register configuration " + "including raw values.\n" + "Takes an optional file parameter."), &maintenanceprintlist); add_cmd ("cooked-registers", class_maintenance, - maintenance_print_cooked_registers, _("\ -Print the internal register configuration including cooked values.\n\ -Takes an optional file parameter."), &maintenanceprintlist); + maintenance_print_cooked_registers, + _("Print the internal register configuration " + "including cooked values.\n" + "Takes an optional file parameter."), &maintenanceprintlist); add_cmd ("register-groups", class_maintenance, - maintenance_print_register_groups, _("\ -Print the internal register configuration including each register's group.\n\ -Takes an optional file parameter."), + maintenance_print_register_groups, + _("Print the internal register configuration " + "including each register's group.\n" + "Takes an optional file parameter."), &maintenanceprintlist); } diff --git a/contrib/gdb-7/gdb/regcache.h b/contrib/gdb-7/gdb/regcache.h index 8cd40fa88a..3708c86d64 100644 --- a/contrib/gdb-7/gdb/regcache.h +++ b/contrib/gdb-7/gdb/regcache.h @@ -1,7 +1,7 @@ /* Cache and manage the values of registers for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001, - 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -40,54 +40,77 @@ extern struct gdbarch *get_regcache_arch (const struct regcache *regcache); /* Return REGCACHE's address space. */ -extern struct address_space *get_regcache_aspace (const struct regcache *regcache); +extern struct address_space *get_regcache_aspace (const struct regcache *); + +enum register_status + { + /* The register value is not in the cache, and we don't know yet + whether it's available in the target (or traceframe). */ + REG_UNKNOWN = 0, + + /* The register value is valid and cached. */ + REG_VALID = 1, + + /* The register value is unavailable. E.g., we're inspecting a + traceframe, and this register wasn't collected. Note that this + is different a different "unavailable" from saying the register + does not exist in the target's architecture --- in that case, + the target should have given us a target description that does + not include the register in the first place. */ + REG_UNAVAILABLE = -1 + }; + +enum register_status regcache_register_status (const struct regcache *regcache, + int regnum); /* Transfer a raw register [0..NUM_REGS) between core-gdb and the - regcache. */ + regcache. The read variants return the status of the register. */ -void regcache_raw_read (struct regcache *regcache, int rawnum, gdb_byte *buf); +enum register_status regcache_raw_read (struct regcache *regcache, + int rawnum, gdb_byte *buf); void regcache_raw_write (struct regcache *regcache, int rawnum, const gdb_byte *buf); -extern void regcache_raw_read_signed (struct regcache *regcache, - int regnum, LONGEST *val); -extern void regcache_raw_read_unsigned (struct regcache *regcache, - int regnum, ULONGEST *val); +extern enum register_status + regcache_raw_read_signed (struct regcache *regcache, + int regnum, LONGEST *val); +extern enum register_status + regcache_raw_read_unsigned (struct regcache *regcache, + int regnum, ULONGEST *val); extern void regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val); extern void regcache_raw_write_unsigned (struct regcache *regcache, int regnum, ULONGEST val); -/* Partial transfer of a raw registers. These perform read, modify, - write style operations. */ +/* Partial transfer of raw registers. These perform read, modify, + write style operations. The read variant returns the status of the + register. */ -void regcache_raw_read_part (struct regcache *regcache, int regnum, - int offset, int len, gdb_byte *buf); +extern enum register_status + regcache_raw_read_part (struct regcache *regcache, int regnum, + int offset, int len, gdb_byte *buf); void regcache_raw_write_part (struct regcache *regcache, int regnum, int offset, int len, const gdb_byte *buf); -int regcache_valid_p (const struct regcache *regcache, int regnum); - void regcache_invalidate (struct regcache *regcache, int regnum); +/* Transfer of pseudo-registers. The read variants return a register + status, as an indication of when a ``cooked'' register was + constructed from valid, invalid or unavailable ``raw'' + registers. */ + /* Transfer a cooked register [0..NUM_REGS+NUM_PSEUDO_REGS). */ -void regcache_cooked_read (struct regcache *regcache, int rawnum, - gdb_byte *buf); +enum register_status regcache_cooked_read (struct regcache *regcache, + int rawnum, gdb_byte *buf); void regcache_cooked_write (struct regcache *regcache, int rawnum, const gdb_byte *buf); -/* NOTE: cagney/2002-08-13: At present GDB has no reliable mechanism - for indicating when a ``cooked'' register was constructed from - invalid or unavailable ``raw'' registers. One fairly easy way of - adding such a mechanism would be for the cooked functions to return - a register valid indication. Given the possibility of such a - change, the extract functions below use a reference parameter, - rather than a function result. */ - /* Read a register as a signed/unsigned quantity. */ -extern void regcache_cooked_read_signed (struct regcache *regcache, - int regnum, LONGEST *val); -extern void regcache_cooked_read_unsigned (struct regcache *regcache, - int regnum, ULONGEST *val); +extern enum register_status + regcache_cooked_read_signed (struct regcache *regcache, + int regnum, LONGEST *val); +extern enum register_status + regcache_cooked_read_unsigned (struct regcache *regcache, + int regnum, ULONGEST *val); extern void regcache_cooked_write_signed (struct regcache *regcache, int regnum, LONGEST val); extern void regcache_cooked_write_unsigned (struct regcache *regcache, @@ -96,8 +119,9 @@ extern void regcache_cooked_write_unsigned (struct regcache *regcache, /* Partial transfer of a cooked register. These perform read, modify, write style operations. */ -void regcache_cooked_read_part (struct regcache *regcache, int regnum, - int offset, int len, gdb_byte *buf); +enum register_status regcache_cooked_read_part (struct regcache *regcache, + int regnum, int offset, + int len, gdb_byte *buf); void regcache_cooked_write_part (struct regcache *regcache, int regnum, int offset, int len, const gdb_byte *buf); @@ -134,8 +158,9 @@ extern int register_size (struct gdbarch *gdbarch, int regnum); restore_reggroup respectively. COOKED_READ returns zero iff the register's value can't be returned. */ -typedef int (regcache_cooked_read_ftype) (void *src, int regnum, - gdb_byte *buf); +typedef enum register_status (regcache_cooked_read_ftype) (void *src, + int regnum, + gdb_byte *buf); extern void regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, @@ -154,9 +179,9 @@ extern void regcache_restore (struct regcache *dst, only transfer values already in the cache. */ extern struct regcache *regcache_dup (struct regcache *regcache); -extern struct regcache *regcache_dup_no_passthrough (struct regcache *regcache); extern void regcache_cpy (struct regcache *dest, struct regcache *src); -extern void regcache_cpy_no_passthrough (struct regcache *dest, struct regcache *src); +extern void regcache_cpy_no_passthrough (struct regcache *dest, + struct regcache *src); extern void registers_changed (void); extern void registers_changed_ptid (ptid_t); diff --git a/contrib/gdb-7/gdb/regformats/reg-bfin.dat b/contrib/gdb-7/gdb/regformats/reg-bfin.dat new file mode 100644 index 0000000000..9db4a8d68d --- /dev/null +++ b/contrib/gdb-7/gdb/regformats/reg-bfin.dat @@ -0,0 +1,56 @@ +name:bfin +expedite:pc,sp,fp +32:r0 +32:r1 +32:r2 +32:r3 +32:r4 +32:r5 +32:r6 +32:r7 +32:p0 +32:p1 +32:p2 +32:p3 +32:p4 +32:p5 +32:sp +32:fp +32:i0 +32:i1 +32:i2 +32:i3 +32:m0 +32:m1 +32:m2 +32:m3 +32:b0 +32:b1 +32:b2 +32:b3 +32:l0 +32:l1 +32:l2 +32:l3 +32:a0x +32:a0w +32:a1x +32:a1w +32:astat +32:rets +32:lc0 +32:lt0 +32:lb0 +32:lc1 +32:lt1 +32:lb1 +32:cycles +32:cycles2 +32:usp +32:seqstat +32:syscfg +32:reti +32:retx +32:retn +32:rete +32:pc diff --git a/contrib/gdb-7/gdb/regformats/regdat.sh b/contrib/gdb-7/gdb/regformats/regdat.sh index ee15f8de96..5d3cc3bdb5 100755 --- a/contrib/gdb-7/gdb/regformats/regdat.sh +++ b/contrib/gdb-7/gdb/regformats/regdat.sh @@ -1,7 +1,8 @@ #!/bin/sh -u # Register protocol definitions for GDB, the GNU debugger. -# Copyright 2001, 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# Copyright 2001, 2002, 2007, 2008, 2009, 2010, 2011 +# Free Software Foundation, Inc. # # This file is part of GDB. # diff --git a/contrib/gdb-7/gdb/regformats/regdef.h b/contrib/gdb-7/gdb/regformats/regdef.h index a71cdc7f06..378a827f11 100644 --- a/contrib/gdb-7/gdb/regformats/regdef.h +++ b/contrib/gdb-7/gdb/regformats/regdef.h @@ -1,5 +1,6 @@ /* Register protocol definition structures for the GNU Debugger - Copyright 2001, 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright 2001, 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/reggroups.c b/contrib/gdb-7/gdb/reggroups.c index fdc0575472..846b1baf9b 100644 --- a/contrib/gdb-7/gdb/reggroups.c +++ b/contrib/gdb-7/gdb/reggroups.c @@ -1,6 +1,6 @@ /* Register groupings for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Red Hat. diff --git a/contrib/gdb-7/gdb/reggroups.h b/contrib/gdb-7/gdb/reggroups.h index f963192fa2..8e009b3463 100644 --- a/contrib/gdb-7/gdb/reggroups.h +++ b/contrib/gdb-7/gdb/reggroups.h @@ -1,6 +1,7 @@ /* Register groupings for GDB, the GNU debugger. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat. diff --git a/contrib/gdb-7/gdb/regset.c b/contrib/gdb-7/gdb/regset.c index 8906a97f23..6dfbc8ab23 100644 --- a/contrib/gdb-7/gdb/regset.c +++ b/contrib/gdb-7/gdb/regset.c @@ -1,6 +1,7 @@ /* Manage register sets. - Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/regset.h b/contrib/gdb-7/gdb/regset.h index 9a21ced768..e378f29dec 100644 --- a/contrib/gdb-7/gdb/regset.h +++ b/contrib/gdb-7/gdb/regset.h @@ -1,6 +1,6 @@ /* Manage register sets. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/remote-fileio.c b/contrib/gdb-7/gdb/remote-fileio.c index 82a4fe920d..68298e7862 100644 --- a/contrib/gdb-7/gdb/remote-fileio.c +++ b/contrib/gdb-7/gdb/remote-fileio.c @@ -1,6 +1,6 @@ /* Remote File-I/O communications - Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* See the GDB User Guide for details of the GDB remote protocol. */ +/* See the GDB User Guide for details of the GDB remote protocol. */ #include "defs.h" #include "gdb_string.h" @@ -30,6 +30,8 @@ #include "exceptions.h" #include "remote-fileio.h" #include "event-loop.h" +#include "target.h" +#include "filenames.h" #include #include @@ -151,7 +153,7 @@ remote_fileio_oflags_to_host (long flags) if (flags & FILEIO_O_RDWR) hflags |= O_RDWR; /* On systems supporting binary and text mode, always open files in - binary mode. */ + binary mode. */ #ifdef O_BINARY hflags |= O_BINARY; #endif @@ -390,7 +392,7 @@ remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length) return 0; } -/* Convert to big endian */ +/* Convert to big endian. */ static void remote_fileio_to_be (LONGEST num, char *buf, int bytes) { @@ -435,7 +437,7 @@ remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst) { LONGEST blksize; - /* `st_dev' is set in the calling function */ + /* `st_dev' is set in the calling function. */ remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino); remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode); remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink); @@ -578,8 +580,8 @@ remote_fileio_badfd (void) static void remote_fileio_return_errno (int retcode) { - remote_fileio_reply (retcode, - retcode < 0 ? remote_fileio_errno_to_target (errno) : 0); + remote_fileio_reply (retcode, retcode < 0 + ? remote_fileio_errno_to_target (errno) : 0); } static void @@ -588,36 +590,18 @@ remote_fileio_return_success (int retcode) remote_fileio_reply (retcode, 0); } -/* Wrapper function for remote_write_bytes() which has the disadvantage to - write only one packet, regardless of the requested number of bytes to - transfer. This wrapper calls remote_write_bytes() as often as needed. */ -static int -remote_fileio_write_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) -{ - int ret = 0, written; - - while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0) - { - len -= written; - memaddr += written; - myaddr += written; - ret += written; - } - return ret; -} - static void remote_fileio_func_open (char *buf) { CORE_ADDR ptrval; - int length, retlength; + int length; long num; int flags, fd; mode_t mode; char *pathname; struct stat st; - /* 1. Parameter: Ptr to pathname / length incl. trailing zero */ + /* 1. Parameter: Ptr to pathname / length incl. trailing zero. */ if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) { remote_fileio_ioerror (); @@ -638,10 +622,9 @@ remote_fileio_func_open (char *buf) } mode = remote_fileio_mode_to_host (num, 1); - /* Request pathname using 'm' packet */ + /* Request pathname. */ pathname = alloca (length); - retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length); - if (retlength != length) + if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0) { remote_fileio_ioerror (); return; @@ -649,7 +632,7 @@ remote_fileio_func_open (char *buf) /* Check if pathname exists and is not a regular file or directory. If so, return an appropriate error code. Same for trying to open directories - for writing. */ + for writing. */ if (!stat (pathname, &st)) { if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) @@ -810,7 +793,7 @@ remote_fileio_func_read (char *buf) { new_offset = lseek (fd, 0, SEEK_CUR); /* If some data has been read, return the number of bytes read. - The Ctrl-C flag is set in remote_fileio_reply() anyway */ + The Ctrl-C flag is set in remote_fileio_reply() anyway. */ if (old_offset != new_offset) ret = new_offset - old_offset; } @@ -819,9 +802,9 @@ remote_fileio_func_read (char *buf) if (ret > 0) { - retlength = remote_fileio_write_bytes (ptrval, buffer, ret); - if (retlength != ret) - ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */ + errno = target_write_memory (ptrval, buffer, ret); + if (errno != 0) + ret = -1; } if (ret < 0) @@ -838,7 +821,7 @@ remote_fileio_func_write (char *buf) long target_fd, num; LONGEST lnum; CORE_ADDR ptrval; - int fd, ret, retlength; + int fd, ret; gdb_byte *buffer; size_t length; @@ -870,8 +853,7 @@ remote_fileio_func_write (char *buf) length = (size_t) num; buffer = (gdb_byte *) xmalloc (length); - retlength = remote_read_bytes (ptrval, buffer, length); - if (retlength != length) + if (target_read_memory (ptrval, buffer, length) != 0) { xfree (buffer); remote_fileio_ioerror (); @@ -894,7 +876,8 @@ remote_fileio_func_write (char *buf) default: ret = write (fd, buffer, length); if (ret < 0 && errno == EACCES) - errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/ + errno = EBADF; /* Cygwin returns EACCESS when writing to a + R/O file. */ break; } @@ -964,7 +947,7 @@ static void remote_fileio_func_rename (char *buf) { CORE_ADDR old_ptr, new_ptr; - int old_len, new_len, retlength; + int old_len, new_len; char *oldpath, *newpath; int ret, of, nf; struct stat ost, nst; @@ -985,8 +968,7 @@ remote_fileio_func_rename (char *buf) /* Request oldpath using 'm' packet */ oldpath = alloca (old_len); - retlength = remote_read_bytes (old_ptr, (gdb_byte *) oldpath, old_len); - if (retlength != old_len) + if (target_read_memory (old_ptr, (gdb_byte *) oldpath, old_len) != 0) { remote_fileio_ioerror (); return; @@ -994,14 +976,13 @@ remote_fileio_func_rename (char *buf) /* Request newpath using 'm' packet */ newpath = alloca (new_len); - retlength = remote_read_bytes (new_ptr, (gdb_byte *) newpath, new_len); - if (retlength != new_len) + if (target_read_memory (new_ptr, (gdb_byte *) newpath, new_len) != 0) { remote_fileio_ioerror (); return; } - /* Only operate on regular files and directories */ + /* Only operate on regular files and directories. */ of = stat (oldpath, &ost); nf = stat (newpath, &nst); if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode)) @@ -1018,11 +999,11 @@ remote_fileio_func_rename (char *buf) { /* Special case: newpath is a non-empty directory. Some systems return ENOTEMPTY, some return EEXIST. We coerce that to be - always EEXIST. */ + always EEXIST. */ if (errno == ENOTEMPTY) errno = EEXIST; #ifdef __CYGWIN__ - /* Workaround some Cygwin problems with correct errnos. */ + /* Workaround some Cygwin problems with correct errnos. */ if (errno == EACCES) { if (!of && !nf && S_ISDIR (nst.st_mode)) @@ -1040,8 +1021,8 @@ remote_fileio_func_rename (char *buf) cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath, newfullpath, PATH_MAX); len = strlen (oldfullpath); - if (newfullpath[len] == '/' - && !strncmp (oldfullpath, newfullpath, len)) + if (IS_DIR_SEPARATOR (newfullpath[len]) + && !filename_ncmp (oldfullpath, newfullpath, len)) errno = EINVAL; else errno = EEXIST; @@ -1060,7 +1041,7 @@ static void remote_fileio_func_unlink (char *buf) { CORE_ADDR ptrval; - int length, retlength; + int length; char *pathname; int ret; struct stat st; @@ -1073,15 +1054,14 @@ remote_fileio_func_unlink (char *buf) } /* Request pathname using 'm' packet */ pathname = alloca (length); - retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length); - if (retlength != length) + if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0) { remote_fileio_ioerror (); return; } /* Only operate on regular files (and directories, which allows to return - the correct return code) */ + the correct return code). */ if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) { remote_fileio_reply (-1, FILEIO_ENODEV); @@ -1101,7 +1081,7 @@ static void remote_fileio_func_stat (char *buf) { CORE_ADDR statptr, nameptr; - int ret, namelength, retlength; + int ret, namelength; char *pathname; LONGEST lnum; struct stat st; @@ -1124,8 +1104,7 @@ remote_fileio_func_stat (char *buf) /* Request pathname using 'm' packet */ pathname = alloca (namelength); - retlength = remote_read_bytes (nameptr, (gdb_byte *) pathname, namelength); - if (retlength != namelength) + if (target_read_memory (nameptr, (gdb_byte *) pathname, namelength) != 0) { remote_fileio_ioerror (); return; @@ -1139,7 +1118,7 @@ remote_fileio_func_stat (char *buf) remote_fileio_return_errno (-1); return; } - /* Only operate on regular files and directories */ + /* Only operate on regular files and directories. */ if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) { remote_fileio_reply (-1, FILEIO_EACCES); @@ -1149,10 +1128,9 @@ remote_fileio_func_stat (char *buf) { remote_fileio_to_fio_stat (&st, &fst); remote_fileio_to_fio_uint (0, fst.fst_dev); - - retlength = remote_fileio_write_bytes (statptr, - (gdb_byte *) &fst, sizeof fst); - if (retlength != sizeof fst) + + errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst); + if (errno != 0) { remote_fileio_return_errno (-1); return; @@ -1196,20 +1174,15 @@ remote_fileio_func_fstat (char *buf) if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT) { remote_fileio_to_fio_uint (1, fst.fst_dev); + memset (&st, 0, sizeof (st)); st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR); st.st_nlink = 1; #ifdef HAVE_GETUID st.st_uid = getuid (); -#else - st.st_uid = 0; #endif #ifdef HAVE_GETGID st.st_gid = getgid (); -#else - st.st_gid = 0; #endif - st.st_rdev = 0; - st.st_size = 0; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE st.st_blksize = 512; #endif @@ -1234,8 +1207,8 @@ remote_fileio_func_fstat (char *buf) { remote_fileio_to_fio_stat (&st, &fst); - retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &fst, sizeof fst); - if (retlength != sizeof fst) + errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst); + if (errno != 0) { remote_fileio_return_errno (-1); return; @@ -1260,13 +1233,13 @@ remote_fileio_func_gettimeofday (char *buf) return; } ptrval = (CORE_ADDR) lnum; - /* 2. Parameter: some pointer value... */ + /* 2. Parameter: some pointer value... */ if (remote_fileio_extract_long (&buf, &lnum)) { remote_fileio_ioerror (); return; } - /* ...which has to be NULL */ + /* ...which has to be NULL. */ if (lnum) { remote_fileio_reply (-1, FILEIO_EINVAL); @@ -1286,8 +1259,8 @@ remote_fileio_func_gettimeofday (char *buf) { remote_fileio_to_fio_timeval (&tv, &ftv); - retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &ftv, sizeof ftv); - if (retlength != sizeof ftv) + errno = target_write_memory (ptrval, (gdb_byte *) &ftv, sizeof ftv); + if (errno != 0) { remote_fileio_return_errno (-1); return; @@ -1332,8 +1305,7 @@ remote_fileio_func_system (char *buf) { /* Request commandline using 'm' packet */ cmdline = alloca (length); - retlength = remote_read_bytes (ptrval, (gdb_byte *) cmdline, length); - if (retlength != length) + if (target_read_memory (ptrval, (gdb_byte *) cmdline, length) != 0) { remote_fileio_ioerror (); return; @@ -1400,7 +1372,7 @@ do_remote_fileio_request (struct ui_out *uiout, void *buf_arg) for (idx = 0; remote_fio_func_map[idx].name; ++idx) if (!strcmp (remote_fio_func_map[idx].name, buf)) break; - if (!remote_fio_func_map[idx].name) /* ERROR: No such function. */ + if (!remote_fio_func_map[idx].name) /* ERROR: No such function. */ return RETURN_ERROR; remote_fio_func_map[idx].func (c); return 0; @@ -1428,8 +1400,8 @@ remote_fileio_reset (void) } } -/* Handle a file I/O request. BUF points to the packet containing the - request. CTRLC_PENDING_P should be nonzero if the target has not +/* Handle a file I/O request. BUF points to the packet containing the + request. CTRLC_PENDING_P should be nonzero if the target has not acknowledged the Ctrl-C sent asynchronously earlier. */ void @@ -1492,7 +1464,8 @@ static void show_system_call_allowed (char *args, int from_tty) { if (args) - error (_("Garbage after \"show remote system-call-allowed\" command: `%s'"), args); + error (_("Garbage after \"show remote " + "system-call-allowed\" command: `%s'"), args); printf_unfiltered ("Calling host system(3) call from target is %sallowed\n", remote_fio_system_call_allowed ? "" : "not "); } diff --git a/contrib/gdb-7/gdb/remote-fileio.h b/contrib/gdb-7/gdb/remote-fileio.h index b295987bf0..2f9558968e 100644 --- a/contrib/gdb-7/gdb/remote-fileio.h +++ b/contrib/gdb-7/gdb/remote-fileio.h @@ -1,6 +1,7 @@ /* Remote File-I/O communications - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -17,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* See the GDB User Guide for details of the GDB remote protocol. */ +/* See the GDB User Guide for details of the GDB remote protocol. */ #ifndef REMOTE_FILEIO_H #define REMOTE_FILEIO_H @@ -25,13 +26,13 @@ struct cmd_list_element; /* Unified interface to remote fileio, called in remote.c from - remote_wait () and remote_async_wait () */ + remote_wait () and remote_async_wait (). */ extern void remote_fileio_request (char *buf, int ctrlc_pending_p); /* Cleanup any remote fileio state. */ extern void remote_fileio_reset (void); -/* Called from _initialize_remote () */ +/* Called from _initialize_remote (). */ extern void initialize_remote_fileio ( struct cmd_list_element *remote_set_cmdlist, struct cmd_list_element *remote_show_cmdlist); diff --git a/contrib/gdb-7/gdb/remote.c b/contrib/gdb-7/gdb/remote.c index e03a611288..243bdd764f 100644 --- a/contrib/gdb-7/gdb/remote.c +++ b/contrib/gdb-7/gdb/remote.c @@ -2,7 +2,7 @@ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -68,7 +68,7 @@ #include "ax.h" #include "ax-gdb.h" -/* temp hacks for tracepoint encoding migration */ +/* Temp hacks for tracepoint encoding migration. */ static char *target_buf; static long target_buf_size; /*static*/ void @@ -435,7 +435,7 @@ remote_get_noisy_reply (char **buf_p, { char *buf; - QUIT; /* allow user to bail out with ^C */ + QUIT; /* Allow user to bail out with ^C. */ getpkt (buf_p, sizeof_buf, 0); buf = *buf_p; if (buf[0] == 'E') @@ -455,7 +455,7 @@ remote_get_noisy_reply (char **buf_p, from = ul; p = pp + 1; - pp = unpack_varlen_hex (p, &ul); + unpack_varlen_hex (p, &ul); to = ul; org_to = to; @@ -492,7 +492,7 @@ remote_get_noisy_reply (char **buf_p, else if (buf[0] == 'O' && buf[1] != 'K') remote_console_output (buf + 1); /* 'O' message from stub */ else - return buf; /* here's the actual reply */ + return buf; /* Here's the actual reply. */ } while (1); } @@ -589,7 +589,7 @@ init_remote_state (struct gdbarch *gdbarch) to be smaller. */ rsa->sizeof_g_packet = offset; - /* Default maximum number of characters in a packet body. Many + /* Default maximum number of characters in a packet body. Many remote stubs have a hardwired buffer size of 400 bytes (c.f. BUFMAX in m68k-stub.c and i386-stub.c). BUFMAX-1 is used as the maximum packet-size to ensure that the packet and an extra @@ -602,9 +602,9 @@ init_remote_state (struct gdbarch *gdbarch) rsa->actual_register_packet_size = 0; /* Should rsa->sizeof_g_packet needs more space than the - default, adjust the size accordingly. Remember that each byte is - encoded as two characters. 32 is the overhead for the packet - header / footer. NOTE: cagney/1999-10-26: I suspect that 8 + default, adjust the size accordingly. Remember that each byte is + encoded as two characters. 32 is the overhead for the packet + header / footer. NOTE: cagney/1999-10-26: I suspect that 8 (``$NN:G...#NN'') is a better guess, the below has been padded a little. */ if (rsa->sizeof_g_packet > ((rsa->remote_packet_size - 32) / 2)) @@ -768,7 +768,7 @@ static struct serial *remote_desc = NULL; /* This variable sets the number of bits in an address that are to be sent in a memory ("M" or "m") packet. Normally, after stripping - leading zeros, the entire address would be sent. This variable + leading zeros, the entire address would be sent. This variable restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The initial implementation of remote.c restricted the address sent in memory packets to ``host::sizeof long'' bytes - (typically 32 @@ -864,7 +864,7 @@ get_memory_packet_size (struct memory_packet_config *config) return what_they_get; } -/* Update the size of a read/write packet. If they user wants +/* Update the size of a read/write packet. If they user wants something really big then do a sanity check. */ static void @@ -977,7 +977,7 @@ get_memory_read_packet_size (void) /* Generic configuration support for packets the stub optionally - supports. Allows the user to specify the use of the packet as well + supports. Allows the user to specify the use of the packet as well as allowing GDB to auto-detect support in the remote stub. */ enum packet_support @@ -1042,7 +1042,8 @@ show_packet_config_cmd (struct packet_config *config) switch (config->detect) { case AUTO_BOOLEAN_AUTO: - printf_filtered (_("Support for the `%s' packet is auto-detected, currently %s.\n"), + printf_filtered (_("Support for the `%s' packet " + "is auto-detected, currently %s.\n"), config->name, support); break; case AUTO_BOOLEAN_TRUE: @@ -1067,12 +1068,14 @@ add_packet_config_cmd (struct packet_config *config, const char *name, config->support = PACKET_SUPPORT_UNKNOWN; set_doc = xstrprintf ("Set use of remote protocol `%s' (%s) packet", name, title); - show_doc = xstrprintf ("Show current use of remote protocol `%s' (%s) packet", + show_doc = xstrprintf ("Show current use of remote " + "protocol `%s' (%s) packet", name, title); /* set/show TITLE-packet {auto,on,off} */ cmd_name = xstrprintf ("%s-packet", title); add_setshow_auto_boolean_cmd (cmd_name, class_obscure, - &config->detect, set_doc, show_doc, NULL, /* help_doc */ + &config->detect, set_doc, + show_doc, NULL, /* help_doc */ set_remote_protocol_packet_cmd, show_remote_protocol_packet_cmd, &remote_set_cmdlist, &remote_show_cmdlist); @@ -1202,6 +1205,7 @@ enum { PACKET_qXfer_osdata, PACKET_qXfer_threads, PACKET_qXfer_statictrace_read, + PACKET_qXfer_traceframe_info, PACKET_qGetTIBAddr, PACKET_qGetTLSAddr, PACKET_qSupported, @@ -1242,7 +1246,7 @@ set_remote_protocol_packet_cmd (char *args, int from_tty, return; } } - internal_error (__FILE__, __LINE__, "Could not find config for %s", + internal_error (__FILE__, __LINE__, _("Could not find config for %s"), c->name); } @@ -1263,7 +1267,7 @@ show_remote_protocol_packet_cmd (struct ui_file *file, int from_tty, return; } } - internal_error (__FILE__, __LINE__, "Could not find config for %s", + internal_error (__FILE__, __LINE__, _("Could not find config for %s"), c->name); } @@ -1349,6 +1353,10 @@ static ptid_t any_thread_ptid; static ptid_t general_thread; static ptid_t continue_thread; +/* This the traceframe which we last selected on the remote system. + It will be -1 if no traceframe is selected. */ +static int remote_traceframe_number = -1; + /* Find out if the stub attached to PID (and hence GDB should offer to detach instead of killing it when bailing out). */ @@ -1537,8 +1545,7 @@ demand_private_info (ptid_t ptid) /* Call this function as a result of 1) A halt indication (T packet) containing a thread id 2) A direct query of currthread - 3) Successful execution of set thread - */ + 3) Successful execution of set thread */ static void record_currthread (ptid_t currthread) @@ -1725,12 +1732,11 @@ remote_thread_alive (struct target_ops *ops, ptid_t ptid) typedef unsigned char threadref[OPAQUETHREADBYTES]; /* WARNING: This threadref data structure comes from the remote O.S., - libstub protocol encoding, and remote.c. it is not particularly + libstub protocol encoding, and remote.c. It is not particularly changable. */ /* Right now, the internal structure is int. We want it to be bigger. - Plan to fix this. - */ + Plan to fix this. */ typedef int gdb_threadref; /* Internal GDB thread reference. */ @@ -1752,8 +1758,7 @@ struct gdb_ext_thread_info /* The volume of remote transfers can be limited by submitting a mask containing bits specifying the desired information. Use a union of these values as the 'selection' parameter to - get_thread_info. FIXME: Make these TAG names more thread specific. - */ + get_thread_info. FIXME: Make these TAG names more thread specific. */ #define TAG_THREADID 1 #define TAG_EXISTS 2 @@ -1871,7 +1876,7 @@ read_ptid (char *buf, char **obuf) /* Multi-process ptid. */ pp = unpack_varlen_hex (p + 1, &pid); if (*pp != '.') - error (_("invalid remote ptid: %s\n"), p); + error (_("invalid remote ptid: %s"), p); p = pp; pp = unpack_varlen_hex (p + 1, &tid); @@ -2080,7 +2085,7 @@ unpack_threadid (char *inbuf, threadref *id) } /* Externally, threadrefs are 64 bits but internally, they are still - ints. This is due to a mismatch of specifications. We would like + ints. This is due to a mismatch of specifications. We would like to use 64bit thread references internally. This is an adapter function. */ @@ -2345,7 +2350,8 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit, int result = 1; /* Trancate result limit to be smaller than the packet size. */ - if ((((result_limit + 1) * BUF_THREAD_ID_SIZE) + 10) >= get_remote_packet_size ()) + if ((((result_limit + 1) * BUF_THREAD_ID_SIZE) + 10) + >= get_remote_packet_size ()) result_limit = (get_remote_packet_size () / BUF_THREAD_ID_SIZE) - 2; pack_threadlist_request (rs->buf, startflag, result_limit, nextthread); @@ -2353,7 +2359,7 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit, getpkt (&rs->buf, &rs->buf_size, 0); if (*rs->buf == '\0') - *result_count = 0; + return 0; else *result_count = parse_threadlist_response (rs->buf + 2, result_limit, &echo_nextthread, @@ -2504,12 +2510,14 @@ start_thread (struct gdb_xml_parser *parser, struct thread_item item; char *id; + struct gdb_xml_value *attr; - id = VEC_index (gdb_xml_value_s, attributes, 0)->value; + id = xml_find_attribute (attributes, "id")->value; item.ptid = read_ptid (id, NULL); - if (VEC_length (gdb_xml_value_s, attributes) > 1) - item.core = *(ULONGEST *) VEC_index (gdb_xml_value_s, attributes, 1)->value; + attr = xml_find_attribute (attributes, "core"); + if (attr != NULL) + item.core = *(ULONGEST *) attr->value; else item.core = -1; @@ -2593,30 +2601,23 @@ remote_threads_info (struct target_ops *ops) TARGET_OBJECT_THREADS, NULL); struct cleanup *back_to = make_cleanup (xfree, xml); + if (xml && *xml) { - struct gdb_xml_parser *parser; struct threads_parsing_context context; - struct cleanup *clear_parsing_context; - context.items = 0; - /* Note: this parser cleanup is already guarded by BACK_TO - above. */ - parser = gdb_xml_create_parser_and_cleanup (_("threads"), - threads_elements, - &context); + context.items = NULL; + make_cleanup (clear_threads_parsing_context, &context); - gdb_xml_use_dtd (parser, "threads.dtd"); - - clear_parsing_context - = make_cleanup (clear_threads_parsing_context, &context); - - if (gdb_xml_parse (parser, xml) == 0) + if (gdb_xml_parse_quick (_("threads"), "threads.dtd", + threads_elements, xml, &context) == 0) { int i; struct thread_item *item; - for (i = 0; VEC_iterate (thread_item_t, context.items, i, item); ++i) + for (i = 0; + VEC_iterate (thread_item_t, context.items, i, item); + ++i) { if (!ptid_equal (item->ptid, null_ptid)) { @@ -2636,8 +2637,6 @@ remote_threads_info (struct target_ops *ops) } } } - - do_cleanups (clear_parsing_context); } do_cleanups (back_to); @@ -2909,9 +2908,11 @@ remote_close (int quitting) remote_desc = NULL; /* We don't have a connection to the remote stub anymore. Get rid - of all the inferiors and their threads we were controlling. */ - discard_all_inferiors (); + of all the inferiors and their threads we were controlling. + Reset inferior_ptid to null_ptid first, as otherwise has_stack_frame + will be unable to find the thread corresponding to (pid, 0, 0). */ inferior_ptid = null_ptid; + discard_all_inferiors (); /* We're no longer interested in any of these events. */ discard_pending_stop_replies (-1); @@ -3055,7 +3056,8 @@ get_offsets (void) offs, num_segments, segments); if (ret == 0 && !do_sections) - error (_("Can not handle qOffsets TextSeg response with this symbol file")); + error (_("Can not handle qOffsets TextSeg " + "response with this symbol file")); if (ret > 0) do_sections = 0; @@ -3068,9 +3070,10 @@ get_offsets (void) { offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr; - /* This is a temporary kludge to force data and bss to use the same offsets - because that's what nlmconv does now. The real solution requires changes - to the stub and remote.c that I don't have time to do right now. */ + /* This is a temporary kludge to force data and bss to use the + same offsets because that's what nlmconv does now. The real + solution requires changes to the stub and remote.c that I + don't have time to do right now. */ offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr; offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr; @@ -3109,7 +3112,7 @@ struct start_remote_args /* Send interrupt_sequence to remote target. */ static void -send_interrupt_sequence () +send_interrupt_sequence (void) { if (interrupt_sequence_mode == interrupt_sequence_control_c) serial_write (remote_desc, "\x03", 1); @@ -3136,12 +3139,12 @@ remote_start_remote (struct ui_out *uiout, void *opaque) immediate_quit++; /* Allow user to interrupt it. */ - /* Ack any packet which the remote side has already sent. */ - serial_write (remote_desc, "+", 1); - if (interrupt_on_connect) send_interrupt_sequence (); + /* Ack any packet which the remote side has already sent. */ + serial_write (remote_desc, "+", 1); + /* The first packet we send to the target is the optional "supported packets" request. If the target can answer this, it will tell us which later probes to skip. */ @@ -3199,13 +3202,14 @@ remote_start_remote (struct ui_out *uiout, void *opaque) if (non_stop) { if (!rs->non_stop_aware) - error (_("Non-stop mode requested, but remote does not support non-stop")); + error (_("Non-stop mode requested, but remote " + "does not support non-stop")); putpkt ("QNonStop:1"); getpkt (&rs->buf, &rs->buf_size, 0); if (strcmp (rs->buf, "OK") != 0) - error ("Remote refused setting non-stop mode with: %s", rs->buf); + error (_("Remote refused setting non-stop mode with: %s"), rs->buf); /* Find about threads and processes the stub is already controlling. We default to adding them in the running state. @@ -3221,7 +3225,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) getpkt (&rs->buf, &rs->buf_size, 0); if (strcmp (rs->buf, "OK") != 0) - error ("Remote refused setting all-stop mode with: %s", rs->buf); + error (_("Remote refused setting all-stop mode with: %s"), rs->buf); } /* Check whether the target is running now. */ @@ -3431,10 +3435,19 @@ remote_check_symbols (struct objfile *objfile) struct minimal_symbol *sym; int end; + /* The remote side has no concept of inferiors that aren't running + yet, it only knows about running processes. If we're connected + but our current inferior is not running, we should not invite the + remote target to request symbol lookups related to its + (unrelated) current process. */ + if (!target_has_execution) + return; + if (remote_protocol_packets[PACKET_qSymbol].support == PACKET_DISABLE) return; - /* Make sure the remote is pointing at the right process. */ + /* Make sure the remote is pointing at the right process. Note + there's no way to select "no process". */ set_general_process (); /* Allocate a message buffer. We can't reuse the input buffer in RS, @@ -3488,9 +3501,9 @@ remote_serial_open (char *name) to be. */ if (!udp_warning && strncmp (name, "udp:", 4) == 0) { - warning (_("\ -The remote protocol may be unreliable over UDP.\n\ -Some events may be lost, rendering further debugging impossible.")); + warning (_("The remote protocol may be unreliable over UDP.\n" + "Some events may be lost, rendering further debugging " + "impossible.")); udp_warning = 1; } @@ -3524,7 +3537,7 @@ remote_set_permissions (void) /* If the target didn't like the packet, warn the user. Do not try to undo the user's settings, that would just be maddening. */ if (strcmp (rs->buf, "OK") != 0) - warning ("Remote refused setting permissions with: %s", rs->buf); + warning (_("Remote refused setting permissions with: %s"), rs->buf); } /* This type describes each known response to the qSupported @@ -3686,6 +3699,8 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_qXfer_osdata }, { "qXfer:threads:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_threads }, + { "qXfer:traceframe-info:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_traceframe_info }, { "QPassSignals", PACKET_DISABLE, remote_supported_packet, PACKET_QPassSignals }, { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet, @@ -3859,7 +3874,8 @@ remote_query_supported (void) break; default: - warning (_("unrecognized item \"%s\" in \"qSupported\" response"), p); + warning (_("unrecognized item \"%s\" " + "in \"qSupported\" response"), p); continue; } end[-1] = '\0'; @@ -3900,7 +3916,8 @@ remote_query_supported (void) static void -remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended_p) +remote_open_1 (char *name, int from_tty, + struct target_ops *target, int extended_p) { struct remote_state *rs = get_remote_state (); @@ -4000,6 +4017,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended general_thread = not_sent_ptid; continue_thread = not_sent_ptid; + remote_traceframe_number = -1; /* Probe for ability to use "ThreadInfo" query, as required. */ use_threadinfo_query = 1; @@ -4012,9 +4030,9 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended /* FIXME: cagney/1999-09-23: During the initial connection it is assumed that the target is already ready and able to respond to - requests. Unfortunately remote_start_remote() eventually calls + requests. Unfortunately remote_start_remote() eventually calls wait_for_inferior() with no timeout. wait_forever_enabled_p gets - around this. Eventually a mechanism that allows + around this. Eventually a mechanism that allows wait_for_inferior() to expect/get timeouts will be implemented. */ wait_forever_enabled_p = 0; @@ -4168,7 +4186,8 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) putpkt (rs->buf); getpkt (&rs->buf, &rs->buf_size, 0); - if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vAttach]) == PACKET_OK) + if (packet_ok (rs->buf, + &remote_protocol_packets[PACKET_vAttach]) == PACKET_OK) { if (from_tty) printf_unfiltered (_("Attached to %s\n"), @@ -4454,7 +4473,7 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) so we don't have any TID numbers the inferior will understand. Make sure to only send forms that do not specify a TID. */ - p = append_resumption (p, endp, minus_one_ptid, step, siggnal); + append_resumption (p, endp, minus_one_ptid, step, siggnal); } else if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) { @@ -4469,12 +4488,12 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) } /* And continue others without a signal. */ - p = append_resumption (p, endp, ptid, /*step=*/ 0, TARGET_SIGNAL_0); + append_resumption (p, endp, ptid, /*step=*/ 0, TARGET_SIGNAL_0); } else { /* Scheduler locking; resume only PTID. */ - p = append_resumption (p, endp, ptid, step, siggnal); + append_resumption (p, endp, ptid, step, siggnal); } gdb_assert (strlen (rs->buf) < get_remote_packet_size ()); @@ -4530,7 +4549,7 @@ remote_resume (struct target_ops *ops, { /* We don't pass signals to the target in reverse exec mode. */ if (info_verbose && siggnal != TARGET_SIGNAL_0) - warning (" - Can't pass signal %d to target in reverse: ignored.\n", + warning (_(" - Can't pass signal %d to target in reverse: ignored."), siggnal); if (step @@ -4556,8 +4575,8 @@ remote_resume (struct target_ops *ops, done: /* We are about to start executing the inferior, let's register it - with the event loop. NOTE: this is the one place where all the - execution commands end up. We could alternatively do this in each + with the event loop. NOTE: this is the one place where all the + execution commands end up. We could alternatively do this in each of the execution commands in infcmd.c. */ /* FIXME: ezannoni 1999-09-28: We may need to move this out of here into infcmd.c in order to allow inferior function calls to work @@ -4614,7 +4633,7 @@ async_remote_interrupt (gdb_client_data arg) target_stop (inferior_ptid); } -/* Perform interrupt, if the first attempt did not succeed. Just give +/* Perform interrupt, if the first attempt did not succeed. Just give up on the target alltogether. */ void async_remote_interrupt_twice (gdb_client_data arg) @@ -4637,9 +4656,9 @@ cleanup_sigint_signal_handler (void *dummy) packet. */ static void (*ofunc) (int); -/* The command line interface's stop routine. This function is installed - as a signal handler for SIGINT. The first time a user requests a - stop, we call remote_stop to send a break or ^C. If there is no +/* The command line interface's stop routine. This function is installed + as a signal handler for SIGINT. The first time a user requests a + stop, we call remote_stop to send a break or ^C. If there is no response from the target (it didn't stop when the user requested it), we ask the user if he'd like to detach from the target. */ static void @@ -4701,7 +4720,7 @@ remote_stop_ns (ptid_t ptid) nptid = ptid; } - p = write_ptid (p, endp, nptid); + write_ptid (p, endp, nptid); } /* In non-stop, we get an immediate OK reply. The stop reply will @@ -4733,7 +4752,7 @@ remote_stop_as (ptid_t ptid) send_interrupt_sequence (); } -/* This is the generic stop called via the target vector. When a target +/* This is the generic stop called via the target vector. When a target interrupt is requested, either by the command line or the GUI, we will eventually end up here. */ @@ -5727,7 +5746,7 @@ process_g_packet (struct regcache *regcache) if (p[0] == 0 || p[1] == 0) /* This shouldn't happen - we adjusted sizeof_g_packet above. */ internal_error (__FILE__, __LINE__, - "unexpected end of 'g' packet reply"); + _("unexpected end of 'g' packet reply")); if (p[0] == 'x' && p[1] == 'x') regs[i] = 0; /* 'x' */ @@ -5745,7 +5764,7 @@ process_g_packet (struct regcache *regcache) if (r->offset * 2 >= strlen (rs->buf)) /* This shouldn't happen - we adjusted in_g_packet above. */ internal_error (__FILE__, __LINE__, - "unexpected end of 'g' packet reply"); + _("unexpected end of 'g' packet reply")); else if (rs->buf[r->offset * 2] == 'x') { gdb_assert (r->offset * 2 < strlen (rs->buf)); @@ -5767,6 +5786,28 @@ fetch_registers_using_g (struct regcache *regcache) process_g_packet (regcache); } +/* Make the remote selected traceframe match GDB's selected + traceframe. */ + +static void +set_remote_traceframe (void) +{ + int newnum; + + if (remote_traceframe_number == get_traceframe_number ()) + return; + + /* Avoid recursion, remote_trace_find calls us again. */ + remote_traceframe_number = get_traceframe_number (); + + newnum = target_trace_find (tfind_number, + get_traceframe_number (), 0, 0, NULL); + + /* Should not happen. If it does, all bets are off. */ + if (newnum != get_traceframe_number ()) + warning (_("could not set remote traceframe")); +} + static void remote_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regnum) @@ -5774,6 +5815,7 @@ remote_fetch_registers (struct target_ops *ops, struct remote_arch_state *rsa = get_remote_arch_state (); int i; + set_remote_traceframe (); set_general_thread (inferior_ptid); if (regnum >= 0) @@ -5931,6 +5973,7 @@ remote_store_registers (struct target_ops *ops, struct remote_arch_state *rsa = get_remote_arch_state (); int i; + set_remote_traceframe (); set_general_thread (inferior_ptid); if (regnum >= 0) @@ -5949,7 +5992,7 @@ remote_store_registers (struct target_ops *ops, /* For now, don't complain if we have no way to write the register. GDB loses track of unavailable registers too easily. Some day, this may be an error. We don't have - any way to read the register, either... */ + any way to read the register, either... */ if (!reg->in_g_packet) return; @@ -6126,7 +6169,7 @@ remote_unescape_input (const gdb_byte *buffer, int len, remote_write_bytes. NOTE: This can still lose if the serial line is not eight-bit - clean. In cases like this, the user should clear "remote + clean. In cases like this, the user should clear "remote X-packet". */ static void @@ -6159,7 +6202,8 @@ check_binary_download (CORE_ADDR addr) { if (remote_debug) fprintf_unfiltered (gdb_stdlog, - "binary downloading NOT suppported by target\n"); + "binary downloading NOT " + "supported by target\n"); remote_protocol_packets[PACKET_X].support = PACKET_DISABLE; } else @@ -6211,7 +6255,7 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, if (packet_format != 'X' && packet_format != 'M') internal_error (__FILE__, __LINE__, - "remote_write_bytes_aux: bad packet format"); + _("remote_write_bytes_aux: bad packet format")); if (len <= 0) return 0; @@ -6223,11 +6267,11 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, rs->buf[0] = '\0'; /* Compute the size of the actual payload by subtracting out the - packet header and footer overhead: "$M,:...#nn". - */ + packet header and footer overhead: "$M,:...#nn". */ + payload_size -= strlen ("$,:#NN"); if (!use_length) - /* The comma won't be used. */ + /* The comma won't be used. */ payload_size += 1; header_length = strlen (header); payload_size -= header_length; @@ -6356,7 +6400,7 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, Returns number of bytes transferred, or 0 (setting errno) for error. Only transfer a single packet. */ -int +static int remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) { char *packet_format = 0; @@ -6391,19 +6435,14 @@ remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) Returns number of bytes transferred, or 0 for error. */ -/* NOTE: cagney/1999-10-18: This function (and its siblings in other - remote targets) shouldn't attempt to read the entire buffer. - Instead it should read a single packet worth of data and then - return the byte size of that packet to the caller. The caller (its - caller and its callers caller ;-) already contains code for - handling partial reads. */ - -int +static int remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) { struct remote_state *rs = get_remote_state (); int max_buf_size; /* Max size of packet output buffer. */ - int origlen; + char *p; + int todo; + int i; if (len <= 0) return 0; @@ -6412,56 +6451,37 @@ remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) /* The packet buffer will be large enough for the payload; get_memory_packet_size ensures this. */ - origlen = len; - while (len > 0) - { - char *p; - int todo; - int i; - - todo = min (len, max_buf_size / 2); /* num bytes that will fit */ + /* Number if bytes that will fit. */ + todo = min (len, max_buf_size / 2); - /* construct "m"","" */ - /* sprintf (rs->buf, "m%lx,%x", (unsigned long) memaddr, todo); */ - memaddr = remote_address_masked (memaddr); - p = rs->buf; - *p++ = 'm'; - p += hexnumstr (p, (ULONGEST) memaddr); - *p++ = ','; - p += hexnumstr (p, (ULONGEST) todo); - *p = '\0'; - - putpkt (rs->buf); - getpkt (&rs->buf, &rs->buf_size, 0); - - if (rs->buf[0] == 'E' - && isxdigit (rs->buf[1]) && isxdigit (rs->buf[2]) - && rs->buf[3] == '\0') - { - /* There is no correspondance between what the remote - protocol uses for errors and errno codes. We would like - a cleaner way of representing errors (big enough to - include errno codes, bfd_error codes, and others). But - for now just return EIO. */ - errno = EIO; - return 0; - } - - /* Reply describes memory byte by byte, - each byte encoded as two hex characters. */ - - p = rs->buf; - if ((i = hex2bin (p, myaddr, todo)) < todo) - { - /* Reply is short. This means that we were able to read - only part of what we wanted to. */ - return i + (origlen - len); - } - myaddr += todo; - memaddr += todo; - len -= todo; + /* Construct "m"","". */ + memaddr = remote_address_masked (memaddr); + p = rs->buf; + *p++ = 'm'; + p += hexnumstr (p, (ULONGEST) memaddr); + *p++ = ','; + p += hexnumstr (p, (ULONGEST) todo); + *p = '\0'; + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + if (rs->buf[0] == 'E' + && isxdigit (rs->buf[1]) && isxdigit (rs->buf[2]) + && rs->buf[3] == '\0') + { + /* There is no correspondance between what the remote protocol + uses for errors and errno codes. We would like a cleaner way + of representing errors (big enough to include errno codes, + bfd_error codes, and others). But for now just return + EIO. */ + errno = EIO; + return 0; } - return origlen; + /* Reply describes memory byte by byte, each byte encoded as two hex + characters. */ + p = rs->buf; + i = hex2bin (p, myaddr, todo); + /* Return what we have. Let higher layers handle partial reads. */ + return i; } @@ -6522,6 +6542,7 @@ remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len, { int res; + set_remote_traceframe (); set_general_thread (inferior_ptid); if (should_write) @@ -6547,7 +6568,7 @@ remote_send_printf (const char *format, ...) rs->buf[0] = '\0'; if (vsnprintf (rs->buf, max_size, format, ap) >= max_size) - internal_error (__FILE__, __LINE__, "Too long remote packet."); + internal_error (__FILE__, __LINE__, _("Too long remote packet.")); if (putpkt (rs->buf) < 0) error (_("Communication problem with target.")); @@ -6668,7 +6689,8 @@ readchar (int timeout) /* no return */ case SERIAL_ERROR: pop_target (); - perror_with_name (_("Remote communication error. Target disconnected.")); + perror_with_name (_("Remote communication error. " + "Target disconnected.")); /* no return */ case SERIAL_TIMEOUT: break; @@ -6835,6 +6857,7 @@ putpkt_binary (char *buf, int cnt) case '-': if (remote_debug) fprintf_unfiltered (gdb_stdlog, "Nak\n"); + /* FALLTHROUGH */ case SERIAL_TIMEOUT: tcount++; if (tcount > 3) @@ -7045,8 +7068,8 @@ read_frame (char **buf_p, str = escape_buffer (buf, bc); old_chain = make_cleanup (xfree, str); fprintf_unfiltered (gdb_stdlog, - "\ -Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", + "Bad checksum, sentsum=0x%x, " + "csum=0x%x, buf=%s\n", pktcsum, csum, str); do_cleanups (old_chain); } @@ -7411,9 +7434,10 @@ extended_remote_mourn_1 (struct target_ops *target) if (rs->buf[0] == 'S' || rs->buf[0] == 'T') { - /* Assume that the target has been restarted. Set inferior_ptid - so that bits of core GDB realizes there's something here, e.g., - so that the user can say "kill" again. */ + /* Assume that the target has been restarted. Set + inferior_ptid so that bits of core GDB realizes + there's something here, e.g., so that the user can + say "kill" again. */ inferior_ptid = magic_null_ptid; } } @@ -7927,17 +7951,17 @@ compare_sections_command (char *args, int from_tty) for (s = exec_bfd->sections; s; s = s->next) { if (!(s->flags & SEC_LOAD)) - continue; /* skip non-loadable section */ + continue; /* Skip non-loadable section. */ size = bfd_get_section_size (s); if (size == 0) - continue; /* skip zero-length section */ + continue; /* Skip zero-length section. */ sectname = bfd_get_section_name (exec_bfd, s); if (args && strcmp (args, sectname) != 0) - continue; /* not the section selected by user */ + continue; /* Not the section selected by user. */ - matched = 1; /* do this section */ + matched = 1; /* Do this section. */ lma = s->lma; sectdata = xmalloc (size); @@ -8102,6 +8126,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, char *p2; char query_type; + set_remote_traceframe (); set_general_thread (inferior_ptid); rs = get_remote_state (); @@ -8132,7 +8157,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return -1; } - /* Handle SPU memory using qxfer packets. */ + /* Handle SPU memory using qxfer packets. */ if (object == TARGET_OBJECT_SPU) { if (readbuf) @@ -8153,7 +8178,8 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, &remote_protocol_packets [PACKET_qXfer_siginfo_read]); else - return remote_write_qxfer (ops, "siginfo", annex, writebuf, offset, len, + return remote_write_qxfer (ops, "siginfo", annex, + writebuf, offset, len, &remote_protocol_packets [PACKET_qXfer_siginfo_write]); } @@ -8161,7 +8187,8 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, if (object == TARGET_OBJECT_STATIC_TRACE_DATA) { if (readbuf) - return remote_read_qxfer (ops, "statictrace", annex, readbuf, offset, len, + return remote_read_qxfer (ops, "statictrace", annex, + readbuf, offset, len, &remote_protocol_packets [PACKET_qXfer_statictrace_read]); else @@ -8230,6 +8257,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_threads]); + case TARGET_OBJECT_TRACEFRAME_INFO: + gdb_assert (annex == NULL); + return remote_read_qxfer + (ops, "traceframe-info", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_traceframe_info]); default: return -1; } @@ -8238,7 +8270,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, buffer size. */ if (offset == 0 && len == 0) return (get_remote_packet_size ()); - /* Minimum outbuf size is get_remote_packet_size (). If LEN is not + /* Minimum outbuf size is get_remote_packet_size (). If LEN is not large enough let the caller deal with it. */ if (len < get_remote_packet_size ()) return -1; @@ -8292,10 +8324,10 @@ remote_search_memory (struct target_ops* ops, int max_size = get_memory_write_packet_size (); struct packet_config *packet = &remote_protocol_packets[PACKET_qSearch_memory]; - /* number of packet bytes used to encode the pattern, - this could be more than PATTERN_LEN due to escape characters */ + /* Number of packet bytes used to encode the pattern; + this could be more than PATTERN_LEN due to escape characters. */ int escaped_pattern_len; - /* amount of pattern that was encodable in the packet */ + /* Amount of pattern that was encodable in the packet. */ int used_pattern_len; int i; int found; @@ -8337,7 +8369,7 @@ remote_search_memory (struct target_ops* ops, /* Bail if the pattern is too large. */ if (used_pattern_len != pattern_len) - error ("Pattern is too large to transmit to remote target."); + error (_("Pattern is too large to transmit to remote target.")); if (putpkt_binary (rs->buf, i + escaped_pattern_len) < 0 || getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0 @@ -8387,7 +8419,8 @@ remote_rcmd (char *command, strcpy (rs->buf, "qRcmd,"); p = strchr (rs->buf, '\0'); - if ((strlen (rs->buf) + strlen (command) * 2 + 8/*misc*/) > get_remote_packet_size ()) + if ((strlen (rs->buf) + strlen (command) * 2 + 8/*misc*/) + > get_remote_packet_size ()) error (_("\"monitor\" command ``%s'' is too long."), command); /* Encode the actual command. */ @@ -8602,8 +8635,9 @@ threadlist_update_test_cmd (char *cmd, int tty) static void init_remote_threadtests (void) { - add_com ("tlist", class_obscure, threadlist_test_cmd, _("\ -Fetch and print the remote list of thread identifiers, one pkt only")); + add_com ("tlist", class_obscure, threadlist_test_cmd, + _("Fetch and print the remote list of " + "thread identifiers, one pkt only")); add_com ("tinfo", class_obscure, threadinfo_test_cmd, _("Fetch and display info about one thread")); add_com ("tset", class_obscure, threadset_test_cmd, @@ -8685,7 +8719,8 @@ remote_get_thread_local_address (struct target_ops *ops, putpkt (rs->buf); getpkt (&rs->buf, &rs->buf_size, 0); - result = packet_ok (rs->buf, &remote_protocol_packets[PACKET_qGetTLSAddr]); + result = packet_ok (rs->buf, + &remote_protocol_packets[PACKET_qGetTLSAddr]); if (result == PACKET_OK) { ULONGEST result; @@ -8792,7 +8827,7 @@ register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes, ix++) if (guess->bytes == bytes) internal_error (__FILE__, __LINE__, - "Duplicate g packet description added for size %d", + _("Duplicate g packet description added for size %d"), bytes); new_guess.bytes = bytes; @@ -9378,7 +9413,8 @@ remote_file_put (const char *local_file, const char *remote_file, int from_tty) { if (!saw_eof) { - bytes = fread (buffer + bytes_in_buffer, 1, io_size - bytes_in_buffer, + bytes = fread (buffer + bytes_in_buffer, 1, + io_size - bytes_in_buffer, file); if (bytes == 0) { @@ -9400,7 +9436,8 @@ remote_file_put (const char *local_file, const char *remote_file, int from_tty) bytes += bytes_in_buffer; bytes_in_buffer = 0; - retcode = remote_hostio_pwrite (fd, buffer, bytes, offset, &remote_errno); + retcode = remote_hostio_pwrite (fd, buffer, bytes, + offset, &remote_errno); if (retcode < 0) remote_hostio_error (remote_errno); @@ -9651,7 +9688,7 @@ remote_download_command_source (int num, ULONGEST addr, for (cmd = cmds; cmd; cmd = cmd->next) { - QUIT; /* allow user to bail out with ^C */ + QUIT; /* Allow user to bail out with ^C. */ strcpy (rs->buf, "QTDPsrc:"); encode_source_string (num, addr, "cmd", cmd->line, rs->buf + strlen (rs->buf), @@ -9666,7 +9703,7 @@ remote_download_command_source (int num, ULONGEST addr, { remote_download_command_source (num, addr, *cmd->body_list); - QUIT; /* allow user to bail out with ^C */ + QUIT; /* Allow user to bail out with ^C. */ strcpy (rs->buf, "QTDPsrc:"); encode_source_string (num, addr, "cmd", "end", rs->buf + strlen (rs->buf), @@ -9702,7 +9739,8 @@ remote_download_tracepoint (struct breakpoint *t) encode_actions (t, loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); - (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions); + (void) make_cleanup (free_actions_list_cleanup_wrapper, + stepping_actions); tpaddr = loc->address; sprintf_vma (addrbuf, tpaddr); @@ -9728,13 +9766,15 @@ remote_download_tracepoint (struct breakpoint *t) /* If it passed validation at definition but fails now, something is very wrong. */ internal_error (__FILE__, __LINE__, - "Fast tracepoint not valid during download"); + _("Fast tracepoint not " + "valid during download")); } else /* Fast tracepoints are functionally identical to regular tracepoints, so don't take lack of support as a reason to give up on the trace run. */ - warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number); + warning (_("Target does not support fast tracepoints, " + "downloading %d as regular tracepoint"), t->number); } else if (t->type == bp_static_tracepoint) { @@ -9747,7 +9787,7 @@ remote_download_tracepoint (struct breakpoint *t) if (target_static_tracepoint_marker_at (tpaddr, &marker)) strcat (buf, ":S"); else - error ("Static tracepoint not valid during download"); + error (_("Static tracepoint not valid during download")); } else /* Fast tracepoints are functionally identical to regular @@ -9773,7 +9813,8 @@ remote_download_tracepoint (struct breakpoint *t) do_cleanups (aexpr_chain); } else - warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number); + warning (_("Target does not support conditional tracepoints, " + "ignoring tp %d cond"), t->number); } if (t->commands || *default_collect) @@ -9788,7 +9829,7 @@ remote_download_tracepoint (struct breakpoint *t) { for (ndx = 0; tdp_actions[ndx]; ndx++) { - QUIT; /* allow user to bail out with ^C */ + QUIT; /* Allow user to bail out with ^C. */ sprintf (buf, "QTDP:-%x:%s:%s%c", t->number, addrbuf, /* address */ tdp_actions[ndx], @@ -9805,7 +9846,7 @@ remote_download_tracepoint (struct breakpoint *t) { for (ndx = 0; stepping_actions[ndx]; ndx++) { - QUIT; /* allow user to bail out with ^C */ + QUIT; /* Allow user to bail out with ^C. */ sprintf (buf, "QTDP:-%x:%s:%s%s%s", t->number, addrbuf, /* address */ ((ndx == 0) ? "S" : ""), @@ -9819,7 +9860,8 @@ remote_download_tracepoint (struct breakpoint *t) } } - if (remote_protocol_packets[PACKET_TracepointSource].support == PACKET_ENABLE) + if (remote_protocol_packets[PACKET_TracepointSource].support + == PACKET_ENABLE) { if (t->addr_string) { @@ -9878,8 +9920,9 @@ remote_trace_set_readonly_regions (void) { asection *s; bfd_size_type size; - bfd_vma lma; + bfd_vma vma; int anysecs = 0; + int offset = 0; if (!exec_bfd) return; /* No information to give. */ @@ -9888,19 +9931,29 @@ remote_trace_set_readonly_regions (void) for (s = exec_bfd->sections; s; s = s->next) { char tmp1[40], tmp2[40]; + int sec_length; if ((s->flags & SEC_LOAD) == 0 || - /* (s->flags & SEC_CODE) == 0 || */ + /* (s->flags & SEC_CODE) == 0 || */ (s->flags & SEC_READONLY) == 0) continue; anysecs = 1; - lma = s->lma; + vma = bfd_get_section_vma (,s); size = bfd_get_section_size (s); - sprintf_vma (tmp1, lma); - sprintf_vma (tmp2, lma + size); - sprintf (target_buf + strlen (target_buf), - ":%s,%s", tmp1, tmp2); + sprintf_vma (tmp1, vma); + sprintf_vma (tmp2, vma + size); + sec_length = 1 + strlen (tmp1) + 1 + strlen (tmp2); + if (offset + sec_length + 1 > target_buf_size) + { + if (remote_protocol_packets[PACKET_qXfer_traceframe_info].support + != PACKET_ENABLE) + warning (_("\ +Too many sections for read-only sections definition packet.")); + break; + } + sprintf (target_buf + offset, ":%s,%s", tmp1, tmp2); + offset += sec_length; } if (anysecs) { @@ -9923,14 +9976,25 @@ remote_trace_start (void) static int remote_get_trace_status (struct trace_status *ts) { - char *p; - /* FIXME we need to get register block size some other way */ + /* Initialize it just to avoid a GCC false warning. */ + char *p = NULL; + /* FIXME we need to get register block size some other way. */ extern int trace_regblock_size; + volatile struct gdb_exception ex; trace_regblock_size = get_remote_arch_state ()->sizeof_g_packet; putpkt ("qTStatus"); - p = remote_get_noisy_reply (&target_buf, &target_buf_size); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + p = remote_get_noisy_reply (&target_buf, &target_buf_size); + } + if (ex.reason < 0) + { + exception_fprintf (gdb_stderr, ex, "qTStatus: "); + return -1; + } /* If the remote target doesn't do tracing, flag it. */ if (*p == '\0') @@ -9973,6 +10037,12 @@ remote_trace_find (enum trace_find_type type, int num, char *p, *reply; int target_frameno = -1, target_tracept = -1; + /* Lookups other than by absolute frame number depend on the current + trace selected, so make sure it is correct on the remote end + first. */ + if (type != tfind_number) + set_remote_traceframe (); + p = rs->buf; strcpy (p, "QTFrame:"); p = strchr (p, '\0'); @@ -9994,7 +10064,7 @@ remote_trace_find (enum trace_find_type type, int num, sprintf (p, "outside:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0)); break; default: - error ("Unknown trace find type %d", type); + error (_("Unknown trace find type %d"), type); } putpkt (rs->buf); @@ -10010,6 +10080,8 @@ remote_trace_find (enum trace_find_type type, int num, target_frameno = (int) strtol (p, &reply, 16); if (reply == p) error (_("Unable to parse trace frame number")); + /* Don't update our remote traceframe number cache on failure + to select a remote traceframe. */ if (target_frameno == -1) return -1; break; @@ -10030,6 +10102,8 @@ remote_trace_find (enum trace_find_type type, int num, } if (tpp) *tpp = target_tracept; + + remote_traceframe_number = target_frameno; return target_frameno; } @@ -10040,6 +10114,8 @@ remote_get_trace_state_variable_value (int tsvnum, LONGEST *val) char *reply; ULONGEST uval; + set_remote_traceframe (); + sprintf (rs->buf, "qTV:%x", tsvnum); putpkt (rs->buf); reply = remote_get_noisy_reply (&target_buf, &target_buf_size); @@ -10166,6 +10242,26 @@ remote_set_circular_trace_buffer (int val) error (_("Bogus reply from target: %s"), reply); } +static struct traceframe_info * +remote_traceframe_info (void) +{ + char *text; + + text = target_read_stralloc (¤t_target, + TARGET_OBJECT_TRACEFRAME_INFO, NULL); + if (text != NULL) + { + struct traceframe_info *info; + struct cleanup *back_to = make_cleanup (xfree, text); + + info = parse_traceframe_info (text); + do_cleanups (back_to); + return info; + } + + return NULL; +} + static void init_remote_ops (void) { @@ -10215,7 +10311,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_has_stack = default_child_has_stack; remote_ops.to_has_registers = default_child_has_registers; remote_ops.to_has_execution = default_child_has_execution; - remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ + remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ remote_ops.to_can_execute_reverse = remote_can_execute_reverse; remote_ops.to_magic = OPS_MAGIC; remote_ops.to_memory_map = remote_memory_map; @@ -10233,16 +10329,19 @@ Specify the serial device it is connected to\n\ remote_ops.to_supports_multi_process = remote_supports_multi_process; remote_ops.to_trace_init = remote_trace_init; remote_ops.to_download_tracepoint = remote_download_tracepoint; - remote_ops.to_download_trace_state_variable = remote_download_trace_state_variable; + remote_ops.to_download_trace_state_variable + = remote_download_trace_state_variable; remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions; remote_ops.to_trace_start = remote_trace_start; remote_ops.to_get_trace_status = remote_get_trace_status; remote_ops.to_trace_stop = remote_trace_stop; remote_ops.to_trace_find = remote_trace_find; - remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value; + remote_ops.to_get_trace_state_variable_value + = remote_get_trace_state_variable_value; remote_ops.to_save_trace_data = remote_save_trace_data; remote_ops.to_upload_tracepoints = remote_upload_tracepoints; - remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables; + remote_ops.to_upload_trace_state_variables + = remote_upload_trace_state_variables; remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data; remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing; remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer; @@ -10254,6 +10353,7 @@ Specify the serial device it is connected to\n\ = remote_static_tracepoint_marker_at; remote_ops.to_static_tracepoint_markers_by_strid = remote_static_tracepoint_markers_by_strid; + remote_ops.to_traceframe_info = remote_traceframe_info; } /* Set up the extended remote vector by making a copy of the standard @@ -10536,7 +10636,8 @@ If set, a break, instead of a cntrl-c, is sent to the remote target."), deprecate_cmd (cmd, "show remote interrupt-sequence"); add_setshow_enum_cmd ("interrupt-sequence", class_support, - interrupt_sequence_modes, &interrupt_sequence_mode, _("\ + interrupt_sequence_modes, &interrupt_sequence_mode, + _("\ Set interrupt sequence to remote target."), _("\ Show interrupt sequence to remote target."), _("\ Valid value is \"Ctrl-C\", \"BREAK\" or \"BREAK-g\". The default is \"Ctrl-C\"."), @@ -10590,14 +10691,18 @@ further restriction and ``limit'' to enable that restriction."), Set the maximum number of target hardware watchpoints."), _("\ Show the maximum number of target hardware watchpoints."), _("\ Specify a negative limit for unlimited."), - NULL, NULL, /* FIXME: i18n: The maximum number of target hardware watchpoints is %s. */ + NULL, NULL, /* FIXME: i18n: The maximum + number of target hardware + watchpoints is %s. */ &remote_set_cmdlist, &remote_show_cmdlist); add_setshow_zinteger_cmd ("hardware-breakpoint-limit", no_class, &remote_hw_breakpoint_limit, _("\ Set the maximum number of target hardware breakpoints."), _("\ Show the maximum number of target hardware breakpoints."), _("\ Specify a negative limit for unlimited."), - NULL, NULL, /* FIXME: i18n: The maximum number of target hardware breakpoints is %s. */ + NULL, NULL, /* FIXME: i18n: The maximum + number of target hardware + breakpoints is %s. */ &remote_set_cmdlist, &remote_show_cmdlist); add_setshow_integer_cmd ("remoteaddresssize", class_obscure, @@ -10671,6 +10776,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_write], "qXfer:siginfo:write", "write-siginfo-object", 0); + add_packet_config_cmd + (&remote_protocol_packets[PACKET_qXfer_traceframe_info], + "qXfer:trace-frame-info:read", "traceframe-info", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr], "qGetTLSAddr", "get-thread-local-storage-address", 0); @@ -10722,7 +10831,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, "qAttached", "query-attached", 0); add_packet_config_cmd (&remote_protocol_packets[PACKET_ConditionalTracepoints], - "ConditionalTracepoints", "conditional-tracepoints", 0); + "ConditionalTracepoints", + "conditional-tracepoints", 0); add_packet_config_cmd (&remote_protocol_packets[PACKET_FastTracepoints], "FastTracepoints", "fast-tracepoints", 0); @@ -10749,7 +10859,9 @@ Show use of remote protocol `Z' packets "), _("\ When set, GDB will attempt to use the remote breakpoint and watchpoint\n\ packets."), set_remote_protocol_Z_packet_cmd, - show_remote_protocol_Z_packet_cmd, /* FIXME: i18n: Use of remote protocol `Z' packets is %s. */ + show_remote_protocol_Z_packet_cmd, + /* FIXME: i18n: Use of remote protocol + `Z' packets is %s. */ &remote_set_cmdlist, &remote_show_cmdlist); add_prefix_cmd ("remote", class_files, remote_command, _("\ diff --git a/contrib/gdb-7/gdb/remote.h b/contrib/gdb-7/gdb/remote.h index cdf11fb98c..25f5ccc26c 100644 --- a/contrib/gdb-7/gdb/remote.h +++ b/contrib/gdb-7/gdb/remote.h @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1999, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -34,7 +34,7 @@ extern void getpkt (char **buf, long *sizeof_buf, int forever); of the packet is in BUF. The string in BUF can be at most PBUFSIZ - 5 to account for the $, # and checksum, and for a possible /0 if we are debugging (remote_debug) and want to print the sent packet - as a string */ + as a string. */ extern int putpkt (char *buf); @@ -42,11 +42,6 @@ extern char *unpack_varlen_hex (char *buff, ULONGEST *result); extern void async_remote_interrupt_twice (void *arg); -extern int remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, - int len); - -extern int remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len); - void register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes, const struct target_desc *tdesc); void register_remote_support_xml (const char *); diff --git a/contrib/gdb-7/gdb/reverse.c b/contrib/gdb-7/gdb/reverse.c index 4fd8a75e96..61f2e7c50b 100644 --- a/contrib/gdb-7/gdb/reverse.c +++ b/contrib/gdb-7/gdb/reverse.c @@ -1,6 +1,7 @@ /* Reverse execution and reverse debugging. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -23,6 +24,7 @@ #include "top.h" #include "cli/cli-cmds.h" #include "cli/cli-decode.h" +#include "cli/cli-utils.h" #include "inferior.h" #include "regcache.h" @@ -172,9 +174,14 @@ save_bookmark_command (char *args, int from_tty) /* Implement "delete bookmark" command. */ static int -delete_one_bookmark (struct bookmark *b) +delete_one_bookmark (int num) { - struct bookmark *b1; + struct bookmark *b1, *b; + + /* Find bookmark with corresponding number. */ + ALL_BOOKMARKS (b) + if (b->number == num) + break; /* Special case, first item in list. */ if (b == bookmark_chain) @@ -214,7 +221,8 @@ static void delete_bookmark_command (char *args, int from_tty) { struct bookmark *b; - unsigned long num; + int num; + struct get_number_or_range_state state; if (bookmark_chain == NULL) { @@ -230,15 +238,14 @@ delete_bookmark_command (char *args, int from_tty) return; } - num = strtoul (args, NULL, 0); - /* Find bookmark with corresponding number. */ - ALL_BOOKMARKS (b) - if (b->number == num) - break; - - if (!delete_one_bookmark (b)) - /* Not found. */ - error (_("delete bookmark: no bookmark found for '%s'."), args); + init_number_or_range (&state, args); + while (!state.finished) + { + num = get_number_or_range (&state); + if (!delete_one_bookmark (num)) + /* Not found. */ + warning (_("No bookmark #%d."), num); + } } /* Implement "goto-bookmark" command. */ @@ -271,7 +278,7 @@ goto_bookmark_command (char *args, int from_tty) } /* General case. Bookmark identified by bookmark number. */ - num = strtoul (args, NULL, 0); + num = get_number (&args); ALL_BOOKMARKS (b) if (b->number == num) break; @@ -286,33 +293,53 @@ goto_bookmark_command (char *args, int from_tty) error (_("goto-bookmark: no bookmark found for '%s'."), args); } +static int +bookmark_1 (int bnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); + struct bookmark *b; + int matched = 0; + + ALL_BOOKMARKS (b) + { + if (bnum == -1 || bnum == b->number) + { + printf_filtered (" %d %s '%s'\n", + b->number, + paddress (gdbarch, b->pc), + b->opaque_data); + matched++; + } + } + + if (bnum > 0 && matched == 0) + printf_filtered ("No bookmark #%d\n", bnum); + + return matched; +} + /* Implement "info bookmarks" command. */ static void bookmarks_info (char *args, int from_tty) { - struct bookmark *b; int bnum = -1; - struct gdbarch *gdbarch; - - if (args) - bnum = parse_and_eval_long (args); if (!bookmark_chain) + printf_filtered (_("No bookmarks.\n")); + else if (args == NULL || *args == '\0') + bookmark_1 (-1); + else { - printf_filtered (_("No bookmarks.\n")); - return; + struct get_number_or_range_state state; + + init_number_or_range (&state, args); + while (!state.finished) + { + bnum = get_number_or_range (&state); + bookmark_1 (bnum); + } } - - gdbarch = get_regcache_arch (get_current_regcache ()); - printf_filtered (_("Bookmark Address Opaque\n")); - printf_filtered (_(" ID Data\n")); - - ALL_BOOKMARKS (b) - printf_filtered (" %d %s '%s'\n", - b->number, - paddress (gdbarch, b->pc), - b->opaque_data); } @@ -369,7 +396,8 @@ execution history that can be returned to later in the same debug \n\ session.")); add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\ Delete a bookmark from the bookmark list.\n\ -Argument is a bookmark number, or no argument to delete all bookmarks.\n"), +Argument is a bookmark number or numbers,\n\ + or no argument to delete all bookmarks.\n"), &deletelist); add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\ Go to an earlier-bookmarked point in the program's execution history.\n\ diff --git a/contrib/gdb-7/gdb/sentinel-frame.c b/contrib/gdb-7/gdb/sentinel-frame.c index 8c11d7bd10..6c2f3e079d 100644 --- a/contrib/gdb-7/gdb/sentinel-frame.c +++ b/contrib/gdb-7/gdb/sentinel-frame.c @@ -1,7 +1,7 @@ /* Code dealing with register stack frames, for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010 + 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -51,9 +51,10 @@ sentinel_frame_prev_register (struct frame_info *this_frame, struct gdbarch *gdbarch = get_frame_arch (this_frame); struct frame_unwind_cache *cache = *this_prologue_cache; struct value *value; + struct type *regtype = register_type (gdbarch, regnum); /* Return the actual value. */ - value = allocate_value (register_type (gdbarch, regnum)); + value = allocate_value (regtype); VALUE_LVAL (value) = lval_register; VALUE_REGNUM (value) = regnum; VALUE_FRAME_ID (value) = get_frame_id (this_frame); @@ -61,7 +62,10 @@ sentinel_frame_prev_register (struct frame_info *this_frame, /* Use the regcache_cooked_read() method so that it, on the fly, constructs either a raw or pseudo register from the raw register cache. */ - regcache_cooked_read (cache->regcache, regnum, value_contents_raw (value)); + if (regcache_cooked_read (cache->regcache, + regnum, + value_contents_raw (value)) == REG_UNAVAILABLE) + mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype)); return value; } @@ -86,9 +90,10 @@ sentinel_frame_prev_arch (struct frame_info *this_frame, return get_regcache_arch (cache->regcache); } -const struct frame_unwind sentinel_frame_unwinder = +const struct frame_unwind sentinel_frame_unwind = { SENTINEL_FRAME, + default_frame_unwind_stop_reason, sentinel_frame_this_id, sentinel_frame_prev_register, NULL, @@ -96,5 +101,3 @@ const struct frame_unwind sentinel_frame_unwinder = NULL, sentinel_frame_prev_arch, }; - -const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; diff --git a/contrib/gdb-7/gdb/sentinel-frame.h b/contrib/gdb-7/gdb/sentinel-frame.h index 0c9f576ef6..30c2b85d4f 100644 --- a/contrib/gdb-7/gdb/sentinel-frame.h +++ b/contrib/gdb-7/gdb/sentinel-frame.h @@ -1,6 +1,7 @@ /* Code dealing with register stack frames, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -34,6 +35,6 @@ extern void *sentinel_frame_cache (struct regcache *regcache); /* At present there is only one type of sentinel frame. */ -extern const struct frame_unwind *const sentinel_frame_unwind; +extern const struct frame_unwind sentinel_frame_unwind; #endif /* !defined (SENTINEL_FRAME_H) */ diff --git a/contrib/gdb-7/gdb/ser-base.c b/contrib/gdb-7/gdb/ser-base.c index c17a389030..368afa6331 100644 --- a/contrib/gdb-7/gdb/ser-base.c +++ b/contrib/gdb-7/gdb/ser-base.c @@ -1,7 +1,8 @@ /* Generic serial interface functions. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -41,27 +42,27 @@ static handler_func fd_event; is constantly scheduling timer events. ASYNC only stops pestering its client when it is de-async'ed or it - is told to go away. */ + is told to go away. */ /* Value of scb->async_state: */ enum { /* >= 0 (TIMER_SCHEDULED) */ - /* The ID of the currently scheduled timer event. This state is + /* The ID of the currently scheduled timer event. This state is rarely encountered. Timer events are one-off so as soon as the - event is delivered the state is shanged to NOTHING_SCHEDULED. */ + event is delivered the state is shanged to NOTHING_SCHEDULED. */ FD_SCHEDULED = -1, /* The fd_event() handler is scheduled. It is called when ever the - file descriptor becomes ready. */ + file descriptor becomes ready. */ NOTHING_SCHEDULED = -2 /* Either no task is scheduled (just going into ASYNC mode) or a timer event has just gone off and the current state has been - forced into nothing scheduled. */ + forced into nothing scheduled. */ }; /* Identify and schedule the next ASYNC task based on scb->async_state and scb->buf* (the input FIFO). A state machine is used to avoid the need to make redundant calls into the event-loop - the next - scheduled task is only changed when needed. */ + scheduled task is only changed when needed. */ static void reschedule (struct serial *scb) @@ -127,7 +128,7 @@ reschedule (struct serial *scb) is no pending error). As soon as data arrives, it is read into the input FIFO and the client notified. The client should then drain the FIFO using readchar(). If the FIFO isn't immediatly emptied, - push_event() is used to nag the client until it is. */ + push_event() is used to nag the client until it is. */ static void fd_event (int error, void *context) @@ -141,7 +142,7 @@ fd_event (int error, void *context) { /* Prime the input FIFO. The readchar() function is used to pull characters out of the buffer. See also - generic_readchar(). */ + generic_readchar(). */ int nr; nr = scb->ops->read_prim (scb, BUFSIZ); if (nr == 0) @@ -165,7 +166,7 @@ fd_event (int error, void *context) /* PUSH_EVENT: The input FIFO is non-empty (or there is a pending error). Nag the client until all the data has been read. In the case of errors, the client will need to close or de-async the - device before naging stops. */ + device before naging stops. */ static void push_event (void *context) @@ -179,7 +180,7 @@ push_event (void *context) } /* Wait for input on scb, with timeout seconds. Returns 0 on success, - otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ + otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ static int ser_base_wait_for (struct serial *scb, int timeout) @@ -192,7 +193,7 @@ ser_base_wait_for (struct serial *scb, int timeout) /* NOTE: Some OS's can scramble the READFDS when the select() call fails (ex the kernel with Red Hat 5.2). Initialize all - arguments before each call. */ + arguments before each call. */ tv.tv_sec = timeout; tv.tv_usec = 0; @@ -214,7 +215,8 @@ ser_base_wait_for (struct serial *scb, int timeout) else if (errno == EINTR) continue; else - return SERIAL_ERROR; /* Got an error from select or poll */ + return SERIAL_ERROR; /* Got an error from select or + poll. */ } return 0; @@ -224,7 +226,7 @@ ser_base_wait_for (struct serial *scb, int timeout) /* Read a character with user-specified timeout. TIMEOUT is number of seconds to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns -2 if timeout expired, EOF if line dropped - dead, or -3 for any other error (see errno in that case). */ + dead, or -3 for any other error (see errno in that case). */ static int do_ser_base_readchar (struct serial *scb, int timeout) @@ -260,12 +262,12 @@ do_ser_base_readchar (struct serial *scb, int timeout) timeout -= delta; /* If we got a character or an error back from wait_for, then we can - break from the loop before the timeout is completed. */ + break from the loop before the timeout is completed. */ if (status != SERIAL_TIMEOUT) break; /* If we have exhausted the original timeout, then generate - a SERIAL_TIMEOUT, and pass it out of the loop. */ + a SERIAL_TIMEOUT, and pass it out of the loop. */ else if (timeout == 0) { status = SERIAL_TIMEOUT; @@ -293,7 +295,7 @@ do_ser_base_readchar (struct serial *scb, int timeout) return *scb->bufp++; } -/* Perform operations common to both old and new readchar. */ +/* Perform operations common to both old and new readchar. */ /* Return the next character from the input FIFO. If the FIFO is empty, call the SERIAL specific routine to try and read in more @@ -305,7 +307,7 @@ do_ser_base_readchar (struct serial *scb, int timeout) specific readchar() function. Note: reschedule() is called after every read. This is because there is no guarentee that the lower level fd_event() poll_event() code (which also calls reschedule()) - will be called. */ + will be called. */ int generic_readchar (struct serial *scb, int timeout, @@ -320,7 +322,7 @@ generic_readchar (struct serial *scb, int timeout, } else if (scb->bufcnt < 0) { - /* Some errors/eof are are sticky. */ + /* Some errors/eof are are sticky. */ ch = scb->bufcnt; } else @@ -332,7 +334,7 @@ generic_readchar (struct serial *scb, int timeout, { case SERIAL_EOF: case SERIAL_ERROR: - /* Make the error/eof stick. */ + /* Make the error/eof stick. */ scb->bufcnt = ch; break; case SERIAL_TIMEOUT: @@ -451,13 +453,20 @@ ser_base_drain_output (struct serial *scb) void ser_base_raw (struct serial *scb) { - return; /* Always in raw mode */ + return; /* Always in raw mode. */ } serial_ttystate ser_base_get_tty_state (struct serial *scb) { - /* allocate a dummy */ + /* Allocate a dummy. */ + return (serial_ttystate) XMALLOC (int); +} + +serial_ttystate +ser_base_copy_tty_state (struct serial *scb, serial_ttystate ttystate) +{ + /* Allocate another dummy. */ return (serial_ttystate) XMALLOC (int); } @@ -487,13 +496,13 @@ ser_base_print_tty_state (struct serial *scb, int ser_base_setbaudrate (struct serial *scb, int rate) { - return 0; /* Never fails! */ + return 0; /* Never fails! */ } int ser_base_setstopbits (struct serial *scb, int num) { - return 0; /* Never fails! */ + return 0; /* Never fails! */ } /* Put the SERIAL device into/out-of ASYNC mode. */ @@ -504,7 +513,7 @@ ser_base_async (struct serial *scb, { if (async_p) { - /* Force a re-schedule. */ + /* Force a re-schedule. */ scb->async_state = NOTHING_SCHEDULED; if (serial_debug_p (scb)) fprintf_unfiltered (gdb_stdlog, "[fd%d->asynchronous]\n", @@ -516,7 +525,7 @@ ser_base_async (struct serial *scb, if (serial_debug_p (scb)) fprintf_unfiltered (gdb_stdlog, "[fd%d->synchronous]\n", scb->fd); - /* De-schedule whatever tasks are currently scheduled. */ + /* De-schedule whatever tasks are currently scheduled. */ switch (scb->async_state) { case FD_SCHEDULED: diff --git a/contrib/gdb-7/gdb/ser-base.h b/contrib/gdb-7/gdb/ser-base.h index 005f93c759..8cbc22585d 100644 --- a/contrib/gdb-7/gdb/ser-base.h +++ b/contrib/gdb-7/gdb/ser-base.h @@ -1,6 +1,7 @@ /* Generic serial interface functions. - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -31,6 +32,8 @@ extern int ser_base_flush_input (struct serial *scb); extern int ser_base_send_break (struct serial *scb); extern void ser_base_raw (struct serial *scb); extern serial_ttystate ser_base_get_tty_state (struct serial *scb); +extern serial_ttystate ser_base_copy_tty_state (struct serial *scb, + serial_ttystate ttystate); extern int ser_base_set_tty_state (struct serial *scb, serial_ttystate ttystate); extern void ser_base_print_tty_state (struct serial *scb, diff --git a/contrib/gdb-7/gdb/ser-pipe.c b/contrib/gdb-7/gdb/ser-pipe.c index 07fe65b14e..9bf0d04f30 100644 --- a/contrib/gdb-7/gdb/ser-pipe.c +++ b/contrib/gdb-7/gdb/ser-pipe.c @@ -1,5 +1,5 @@ /* Serial interface for a pipe to a separate program - Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Solutions. @@ -31,6 +31,7 @@ #include #include #include "gdb_string.h" +#include "gdb_wait.h" #include @@ -44,7 +45,7 @@ struct pipe_state int pid; }; -/* Open up a raw pipe */ +/* Open up a raw pipe. */ static int pipe_open (struct serial *scb, const char *name) @@ -79,7 +80,7 @@ pipe_open (struct serial *scb, const char *name) on certain platforms. */ pid = vfork (); - /* Error. */ + /* Error. */ if (pid == -1) { close (pdes[0]); @@ -96,7 +97,7 @@ pipe_open (struct serial *scb, const char *name) err_pdes[0] = err_pdes[1] = -1; } - /* Child. */ + /* Child. */ if (pid == 0) { /* We don't want ^c to kill the connection. */ @@ -108,7 +109,7 @@ pipe_open (struct serial *scb, const char *name) signal (SIGINT, SIG_IGN); #endif - /* re-wire pdes[1] to stdin/stdout */ + /* Re-wire pdes[1] to stdin/stdout. */ close (pdes[0]); if (pdes[1] != STDOUT_FILENO) { @@ -124,18 +125,18 @@ pipe_open (struct serial *scb, const char *name) close (err_pdes[1]); } #if 0 - /* close any stray FD's - FIXME - how? */ + /* close any stray FD's - FIXME - how? */ /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams from previous popen() calls that remain open in the - parent process are closed in the new child process. */ + parent process are closed in the new child process. */ for (old = pidlist; old; old = old->next) - close (fileno (old->fp)); /* don't allow a flush */ + close (fileno (old->fp)); /* Don't allow a flush. */ #endif execl ("/bin/sh", "sh", "-c", name, (char *) 0); _exit (127); } - /* Parent. */ + /* Parent. */ close (pdes[1]); if (err_pdes[1] != -1) close (err_pdes[1]); @@ -157,23 +158,45 @@ pipe_close (struct serial *scb) { struct pipe_state *state = scb->state; + close (scb->fd); + scb->fd = -1; + if (state != NULL) { - int pid = state->pid; - close (scb->fd); - scb->fd = -1; + int status; + kill (state->pid, SIGTERM); +#ifdef HAVE_WAITPID + /* Assume the program will exit after SIGTERM. Might be + useful to print any remaining stderr output from + scb->error_fd while waiting. */ + waitpid (state->pid, &status, 0); +#endif if (scb->error_fd != -1) close (scb->error_fd); scb->error_fd = -1; xfree (state); scb->state = NULL; - kill (pid, SIGTERM); - /* Might be useful to check that the child does die, - and while we're waiting for it to die print any remaining - stderr output. */ } } +int +gdb_pipe (int pdes[2]) +{ +#if !HAVE_SOCKETPAIR + errno = ENOSYS; + return -1; +#else + + if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0) + return -1; + + /* If we don't do this, GDB simply exits when the remote side + dies. */ + signal (SIGPIPE, SIG_IGN); + return 0; +#endif +} + void _initialize_ser_pipe (void) { @@ -191,6 +214,7 @@ _initialize_ser_pipe (void) ops->send_break = ser_base_send_break; ops->go_raw = ser_base_raw; ops->get_tty_state = ser_base_get_tty_state; + ops->copy_tty_state = ser_base_copy_tty_state; ops->set_tty_state = ser_base_set_tty_state; ops->print_tty_state = ser_base_print_tty_state; ops->noflush_set_tty_state = ser_base_noflush_set_tty_state; diff --git a/contrib/gdb-7/gdb/ser-tcp.c b/contrib/gdb-7/gdb/ser-tcp.c index cb862e7e55..e3d5640504 100644 --- a/contrib/gdb-7/gdb/ser-tcp.c +++ b/contrib/gdb-7/gdb/ser-tcp.c @@ -1,7 +1,7 @@ /* Serial interface for raw TCP connections on Un*x like systems. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2005, 2006, - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -29,10 +29,10 @@ #include #ifdef HAVE_SYS_FILIO_H -#include /* For FIONBIO. */ +#include /* For FIONBIO. */ #endif #ifdef HAVE_SYS_IOCTL_H -#include /* For FIONBIO. */ +#include /* For FIONBIO. */ #endif #include @@ -73,7 +73,7 @@ static int tcp_auto_retry = 1; static int tcp_retry_limit = 15; -/* how many times per second to poll deprecated_ui_loop_hook */ +/* How many times per second to poll deprecated_ui_loop_hook. */ #define POLL_INTERVAL 5 @@ -149,7 +149,7 @@ wait_for_connect (struct serial *scb, int *polls) return n; } -/* Open a tcp socket */ +/* Open a tcp socket. */ int net_open (struct serial *scb, const char *name) @@ -178,14 +178,15 @@ net_open (struct serial *scb, const char *name) port_str = strchr (name, ':'); if (!port_str) - error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */ + error (_("net_open: No colon in host name!")); /* Shouldn't ever + happen. */ tmp = min (port_str - name, (int) sizeof hostname - 1); - strncpy (hostname, name, tmp); /* Don't want colon */ - hostname[tmp] = '\000'; /* Tie off host name */ + strncpy (hostname, name, tmp); /* Don't want colon. */ + hostname[tmp] = '\000'; /* Tie off host name. */ port = atoi (port_str + 1); - /* default hostname is localhost */ + /* Default hostname is localhost. */ if (!hostname[0]) strcpy (hostname, "localhost"); @@ -212,11 +213,12 @@ net_open (struct serial *scb, const char *name) if (scb->fd == -1) return -1; - /* set socket nonblocking */ + /* Set socket nonblocking. */ ioarg = 1; ioctl (scb->fd, FIONBIO, &ioarg); - /* Use Non-blocking connect. connect() will return 0 if connected already. */ + /* Use Non-blocking connect. connect() will return 0 if connected + already. */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); if (n < 0) @@ -256,7 +258,7 @@ net_open (struct serial *scb, const char *name) return -1; } - /* looks like we need to wait for the connect */ + /* Looks like we need to wait for the connect. */ do { n = wait_for_connect (scb, &polls); @@ -269,7 +271,7 @@ net_open (struct serial *scb, const char *name) } } - /* Got something. Is it an error? */ + /* Got something. Is it an error? */ { int res, err; socklen_t len; @@ -301,13 +303,13 @@ net_open (struct serial *scb, const char *name) } } - /* turn off nonblocking */ + /* Turn off nonblocking. */ ioarg = 0; ioctl (scb->fd, FIONBIO, &ioarg); if (use_udp == 0) { - /* Disable Nagle algorithm. Needed in some cases. */ + /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof (tmp)); @@ -347,7 +349,7 @@ net_write_prim (struct serial *scb, const void *buf, size_t count) int ser_tcp_send_break (struct serial *scb) { - /* Send telnet IAC and BREAK characters. */ + /* Send telnet IAC and BREAK characters. */ return (serial_write (scb, "\377\363", 2)); } @@ -388,6 +390,7 @@ _initialize_ser_tcp (void) ops->send_break = ser_tcp_send_break; ops->go_raw = ser_base_raw; ops->get_tty_state = ser_base_get_tty_state; + ops->copy_tty_state = ser_base_copy_tty_state; ops->set_tty_state = ser_base_set_tty_state; ops->print_tty_state = ser_base_print_tty_state; ops->noflush_set_tty_state = ser_base_noflush_set_tty_state; diff --git a/contrib/gdb-7/gdb/ser-tcp.h b/contrib/gdb-7/gdb/ser-tcp.h index bf28d35302..c8ce0bf5a6 100644 --- a/contrib/gdb-7/gdb/ser-tcp.h +++ b/contrib/gdb-7/gdb/ser-tcp.h @@ -1,6 +1,7 @@ /* Serial interface for raw TCP connections on Un*x like systems. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-unix.c b/contrib/gdb-7/gdb/ser-unix.c index 266453c2c1..c541452a8c 100644 --- a/contrib/gdb-7/gdb/ser-unix.c +++ b/contrib/gdb-7/gdb/ser-unix.c @@ -1,7 +1,7 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -103,7 +103,7 @@ static int hardwire_setstopbits (struct serial *, int); void _initialize_ser_hardwire (void); -/* Open up a real live device for serial I/O */ +/* Open up a real live device for serial I/O. */ static int hardwire_open (struct serial *scb, const char *name) @@ -183,7 +183,21 @@ hardwire_get_tty_state (struct serial *scb) state = (struct hardwire_ttystate *) xmalloc (sizeof *state); if (get_tty_state (scb, state)) - return NULL; + { + xfree (state); + return NULL; + } + + return (serial_ttystate) state; +} + +static serial_ttystate +hardwire_copy_tty_state (struct serial *scb, serial_ttystate ttystate) +{ + struct hardwire_ttystate *state; + + state = (struct hardwire_ttystate *) xmalloc (sizeof *state); + *state = *(struct hardwire_ttystate *) ttystate; return (serial_ttystate) state; } @@ -287,7 +301,8 @@ hardwire_print_tty_state (struct serial *scb, #endif } -/* Wait for the output to drain away, as opposed to flushing (discarding) it */ +/* Wait for the output to drain away, as opposed to flushing + (discarding) it. */ static int hardwire_drain_output (struct serial *scb) @@ -303,7 +318,7 @@ hardwire_drain_output (struct serial *scb) #ifdef HAVE_SGTTY /* Get the current state and then restore it using TIOCSETP, which should cause the output to drain and pending input - to be discarded. */ + to be discarded. */ { struct hardwire_ttystate state; @@ -388,7 +403,8 @@ hardwire_raw (struct serial *scb) struct hardwire_ttystate state; if (get_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", + safe_strerror (errno)); #ifdef HAVE_TERMIOS state.termios.c_iflag = 0; @@ -431,24 +447,24 @@ hardwire_raw (struct serial *scb) scb->current_timeout = 0; if (set_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", + safe_strerror (errno)); } /* Wait for input on scb, with timeout seconds. Returns 0 on success, otherwise SERIAL_TIMEOUT or SERIAL_ERROR. For termio{s}, we actually just setup VTIME if necessary, and let the - timeout occur in the read() in hardwire_read(). - */ + timeout occur in the read() in hardwire_read(). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ser_base*() until the old TERMIOS/SGTTY/... timer code has been - flushed. . */ + flushed. . */ /* NOTE: cagney/1999-09-30: Much of the code below is dead. The only possible values of the TIMEOUT parameter are ONE and ZERO. Consequently all the code that tries to handle the possability of - an overflowed timer is unnecessary. */ + an overflowed timer is unnecessary. */ static int wait_for (struct serial *scb, int timeout) @@ -462,7 +478,7 @@ wait_for (struct serial *scb, int timeout) /* NOTE: Some OS's can scramble the READFDS when the select() call fails (ex the kernel with Red Hat 5.2). Initialize all - arguments before each call. */ + arguments before each call. */ tv.tv_sec = timeout; tv.tv_usec = 0; @@ -481,7 +497,7 @@ wait_for (struct serial *scb, int timeout) else if (errno == EINTR) continue; else - return SERIAL_ERROR; /* Got an error from select or poll */ + return SERIAL_ERROR; /* Got an error from select or poll. */ return 0; } @@ -497,7 +513,8 @@ wait_for (struct serial *scb, int timeout) struct hardwire_ttystate state; if (get_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", + safe_strerror (errno)); #ifdef HAVE_TERMIOS if (timeout < 0) @@ -549,27 +566,29 @@ wait_for (struct serial *scb, int timeout) #endif if (set_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", + safe_strerror (errno)); return 0; } #endif /* HAVE_TERMIO || HAVE_TERMIOS */ } -/* Read a character with user-specified timeout. TIMEOUT is number of seconds - to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns - char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line - dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */ +/* Read a character with user-specified timeout. TIMEOUT is number of + seconds to wait, or -1 to wait forever. Use timeout of 0 to effect + a poll. Returns char if successful. Returns SERIAL_TIMEOUT if + timeout expired, EOF if line dropped dead, or SERIAL_ERROR for any + other error (see errno in that case). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ser_base*() until the old TERMIOS/SGTTY/... timer code has been - flushed. */ + flushed. */ /* NOTE: cagney/1999-09-16: This function is not identical to ser_base_readchar() as part of replacing it with ser_base*() merging will be required - this code handles the case where read() times out due to no data while ser_base_readchar() doesn't expect - that. */ + that. */ static int do_hardwire_readchar (struct serial *scb, int timeout) @@ -631,7 +650,7 @@ do_hardwire_readchar (struct serial *scb, int timeout) else if (errno == EINTR) continue; else - return SERIAL_ERROR; /* Got an error from read */ + return SERIAL_ERROR; /* Got an error from read. */ } scb->bufcnt = status; @@ -763,30 +782,31 @@ rate_to_code (int rate) for (i = 0; baudtab[i].rate != -1; i++) { - /* test for perfect macth. */ + /* test for perfect macth. */ if (rate == baudtab[i].rate) return baudtab[i].code; else { - /* check if it is in between valid values. */ + /* check if it is in between valid values. */ if (rate < baudtab[i].rate) { if (i) { - warning (_("Invalid baud rate %d. Closest values are %d and %d."), - rate, baudtab[i - 1].rate, baudtab[i].rate); + warning (_("Invalid baud rate %d. " + "Closest values are %d and %d."), + rate, baudtab[i - 1].rate, baudtab[i].rate); } else { warning (_("Invalid baud rate %d. Minimum value is %d."), - rate, baudtab[0].rate); + rate, baudtab[0].rate); } return -1; } } } - /* The requested speed was too large. */ + /* The requested speed was too large. */ warning (_("Invalid baud rate %d. Maximum value is %d."), rate, baudtab[i - 1].rate); return -1; @@ -801,7 +821,7 @@ hardwire_setbaudrate (struct serial *scb, int rate) if (baud_code < 0) { /* The baud rate was not valid. - A warning has already been issued. */ + A warning has already been issued. */ errno = EINVAL; return -1; } @@ -896,8 +916,8 @@ _initialize_ser_hardwire (void) ops->open = hardwire_open; ops->close = hardwire_close; /* FIXME: Don't replace this with the equivalent ser_base*() until - the old TERMIOS/SGTTY/... timer code has been flushed. cagney - 1999-09-16. */ + the old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ ops->readchar = hardwire_readchar; ops->write = ser_base_write; ops->flush_output = hardwire_flush_output; @@ -905,6 +925,7 @@ _initialize_ser_hardwire (void) ops->send_break = hardwire_send_break; ops->go_raw = hardwire_raw; ops->get_tty_state = hardwire_get_tty_state; + ops->copy_tty_state = hardwire_copy_tty_state; ops->set_tty_state = hardwire_set_tty_state; ops->print_tty_state = hardwire_print_tty_state; ops->noflush_set_tty_state = hardwire_noflush_set_tty_state; diff --git a/contrib/gdb-7/gdb/ser-unix.h b/contrib/gdb-7/gdb/ser-unix.h index 985aef7662..398b5d3565 100644 --- a/contrib/gdb-7/gdb/ser-unix.h +++ b/contrib/gdb-7/gdb/ser-unix.h @@ -1,6 +1,6 @@ /* Serial interface for UN*X file-descriptor based connection. - Copyright (C) 1999, 2000, 2002, 2007, 2008, 2009, 2010 + Copyright (C) 1999, 2000, 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/serial.c b/contrib/gdb-7/gdb/serial.c index 75a08781d2..7c8fbc2c76 100644 --- a/contrib/gdb-7/gdb/serial.c +++ b/contrib/gdb-7/gdb/serial.c @@ -1,7 +1,7 @@ /* Generic serial interface routines Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -27,30 +27,31 @@ extern void _initialize_serial (void); -/* Is serial being debugged? */ +/* Is serial being debugged? */ static int global_serial_debug_p; -/* Linked list of serial I/O handlers */ +/* Linked list of serial I/O handlers. */ static struct serial_ops *serial_ops_list = NULL; -/* This is the last serial stream opened. Used by connect command. */ +/* This is the last serial stream opened. Used by connect command. */ static struct serial *last_serial_opened = NULL; -/* Pointer to list of scb's. */ +/* Pointer to list of scb's. */ static struct serial *scb_base; /* Non-NULL gives filename which contains a recording of the remote session, - suitable for playback by gdbserver. */ + suitable for playback by gdbserver. */ static char *serial_logfile = NULL; static struct ui_file *serial_logfp = NULL; -static struct serial_ops *serial_interface_lookup (char *); -static void serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout); +static struct serial_ops *serial_interface_lookup (const char *); +static void serial_logchar (struct ui_file *stream, + int ch_type, int ch, int timeout); static const char logbase_hex[] = "hex"; static const char logbase_octal[] = "octal"; static const char logbase_ascii[] = "ascii"; @@ -61,7 +62,7 @@ static const char *serial_logbase = logbase_ascii; static int serial_current_type = 0; -/* Log char CH of type CHTYPE, with TIMEOUT */ +/* Log char CH of type CHTYPE, with TIMEOUT. */ /* Define bogus char to represent a BREAK. Should be careful to choose a value that can't be confused with a normal char, or an error code. */ @@ -123,7 +124,8 @@ serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout) fputs_unfiltered ("\\v", stream); break; default: - fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); + fprintf_unfiltered (stream, + isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break; } } @@ -141,13 +143,13 @@ serial_log_command (const char *cmd) fputs_unfiltered (cmd, serial_logfp); /* Make sure that the log file is as up-to-date as possible, - in case we are getting ready to dump core or something. */ + in case we are getting ready to dump core or something. */ gdb_flush (serial_logfp); } static struct serial_ops * -serial_interface_lookup (char *name) +serial_interface_lookup (const char *name) { struct serial_ops *ops; @@ -165,7 +167,7 @@ serial_add_interface (struct serial_ops *optable) serial_ops_list = optable; } -/* Open up a device or a network socket, depending upon the syntax of NAME. */ +/* Open up a device or a network socket, depending upon the syntax of NAME. */ struct serial * serial_open (const char *name) @@ -212,7 +214,7 @@ serial_open (const char *name) scb->bufp = scb->buf; scb->error_fd = -1; - /* `...->open (...)' would get expanded by an the open(2) syscall macro. */ + /* `...->open (...)' would get expanded by the open(2) syscall macro. */ if ((*scb->ops->open) (scb, open_name)) { xfree (scb); @@ -255,22 +257,27 @@ serial_for_fd (int fd) return NULL; } -struct serial * -serial_fdopen (const int fd) +/* Open a new serial stream using a file handle, using serial + interface ops OPS. */ + +static struct serial * +serial_fdopen_ops (const int fd, struct serial_ops *ops) { struct serial *scb; - struct serial_ops *ops; - for (scb = scb_base; scb; scb = scb->next) - if (scb->fd == fd) - { - scb->refcnt++; - return scb; - } + scb = serial_for_fd (fd); + if (scb) + { + scb->refcnt++; + return scb; + } - ops = serial_interface_lookup ("terminal"); if (!ops) - ops = serial_interface_lookup ("hardwire"); + { + ops = serial_interface_lookup ("terminal"); + if (!ops) + ops = serial_interface_lookup ("hardwire"); + } if (!ops) return NULL; @@ -281,8 +288,7 @@ serial_fdopen (const int fd) scb->bufcnt = 0; scb->bufp = scb->buf; - - scb->fd = fd; + scb->error_fd = -1; scb->name = NULL; scb->next = scb_base; @@ -293,11 +299,22 @@ serial_fdopen (const int fd) scb->async_context = NULL; scb_base = scb; + if ((ops->fdopen) != NULL) + (*ops->fdopen) (scb, fd); + else + scb->fd = fd; + last_serial_opened = scb; return scb; } +struct serial * +serial_fdopen (const int fd) +{ + return serial_fdopen_ops (fd, NULL); +} + static void do_serial_close (struct serial *scb, int really_close) { @@ -310,7 +327,7 @@ do_serial_close (struct serial *scb, int really_close) fputs_unfiltered ("\nEnd of log\n", serial_logfp); serial_current_type = 0; - /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ + /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ ui_file_delete (serial_logfp); serial_logfp = NULL; } @@ -325,7 +342,7 @@ do_serial_close (struct serial *scb, int really_close) if (scb->refcnt > 0) return; - /* ensure that the FD has been taken out of async mode */ + /* ensure that the FD has been taken out of async mode. */ if (scb->async_handler != NULL) serial_async (scb, NULL, NULL); @@ -368,7 +385,7 @@ serial_readchar (struct serial *scb, int timeout) int ch; /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC - code is finished. */ + code is finished. */ if (0 && serial_is_async_p (scb) && timeout < 0) internal_error (__FILE__, __LINE__, _("serial_readchar: blocking read in async mode")); @@ -379,7 +396,7 @@ serial_readchar (struct serial *scb, int timeout) serial_logchar (serial_logfp, 'r', ch, timeout); /* Make sure that the log file is as up-to-date as possible, - in case we are getting ready to dump core or something. */ + in case we are getting ready to dump core or something. */ gdb_flush (serial_logfp); } if (serial_debug_p (scb)) @@ -404,7 +421,7 @@ serial_write (struct serial *scb, const char *str, int len) serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0); /* Make sure that the log file is as up-to-date as possible, - in case we are getting ready to dump core or something. */ + in case we are getting ready to dump core or something. */ gdb_flush (serial_logfp); } if (serial_debug_p (scb)) @@ -476,6 +493,12 @@ serial_get_tty_state (struct serial *scb) return scb->ops->get_tty_state (scb); } +serial_ttystate +serial_copy_tty_state (struct serial *scb, serial_ttystate ttystate) +{ + return scb->ops->copy_tty_state (scb, ttystate); +} + int serial_set_tty_state (struct serial *scb, serial_ttystate ttystate) { @@ -540,7 +563,7 @@ int deprecated_serial_fd (struct serial *scb) { /* FIXME: should this output a warning that deprecated code is being - called? */ + called? */ if (scb->fd < 0) { internal_error (__FILE__, __LINE__, @@ -582,6 +605,27 @@ serial_done_wait_handle (struct serial *scb) } #endif +int +serial_pipe (struct serial *scbs[2]) +{ + struct serial_ops *ops; + int fildes[2]; + + ops = serial_interface_lookup ("pipe"); + if (!ops) + { + errno = ENOSYS; + return -1; + } + + if (gdb_pipe (fildes) == -1) + return -1; + + scbs[0] = serial_fdopen_ops (fildes[0], ops); + scbs[1] = serial_fdopen_ops (fildes[1], ops); + return 0; +} + #if 0 /* The connect command is #if 0 because I hadn't thought of an elegant way to wait for I/O on two `struct serial *'s simultaneously. Two @@ -622,7 +666,9 @@ connect_command (char *args, int fromtty) dont_repeat (); if (args) - fprintf_unfiltered (gdb_stderr, "This command takes no args. They have been ignored.\n"); + fprintf_unfiltered (gdb_stderr, + "This command takes no args. " + "They have been ignored.\n"); printf_unfiltered ("[Entering connect mode. Use ~. or ~^D to escape]\n"); @@ -711,7 +757,8 @@ static struct cmd_list_element *serial_show_cmdlist; static void serial_set_cmd (char *args, int from_tty) { - printf_unfiltered ("\"set serial\" must be followed by the name of a command.\n"); + printf_unfiltered ("\"set serial\" must be followed " + "by the name of a command.\n"); help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout); } diff --git a/contrib/gdb-7/gdb/serial.h b/contrib/gdb-7/gdb/serial.h index 7690501b89..a1eba8d3a6 100644 --- a/contrib/gdb-7/gdb/serial.h +++ b/contrib/gdb-7/gdb/serial.h @@ -1,6 +1,6 @@ /* Remote serial support interface definitions for GDB, the GNU Debugger. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2004, - 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -37,9 +37,9 @@ typedef void *serial_ttystate; struct serial; /* Try to open NAME. Returns a new `struct serial *' on success, NULL - on failure. Note that some open calls can block and, if possible, + on failure. Note that some open calls can block and, if possible, should be written to be non-blocking, with calls to ui_look_hook - so they can be cancelled. An async interface for open could be + so they can be cancelled. An async interface for open could be added to GDB if necessary. */ extern struct serial *serial_open (const char *name); @@ -56,13 +56,26 @@ extern struct serial *serial_fdopen (const int fd); extern void serial_close (struct serial *scb); +/* Create a pipe, and put the read end in files[0], and the write end + in filde[1]. Returns 0 for success, negative value for error (in + which case errno contains the error). */ + +extern int gdb_pipe (int fildes[2]); + +/* Create a pipe with each end wrapped in a `struct serial' interface. + Put the read end in scbs[0], and the write end in scbs[1]. Returns + 0 for success, negative value for error (in which case errno + contains the error). */ + +extern int serial_pipe (struct serial *scbs[2]); + /* Push out all buffers and destroy SCB without closing the device. */ extern void serial_un_fdopen (struct serial *scb); /* Read one char from the serial device with TIMEOUT seconds to wait or -1 to wait forever. Use timeout of 0 to effect a poll. - Infinite waits are not permitted. Returns unsigned char if ok, else + Infinite waits are not permitted. Returns unsigned char if ok, else one of the following codes. Note that all error return-codes are guaranteed to be < 0. */ @@ -116,6 +129,12 @@ extern void serial_raw (struct serial *scb); extern serial_ttystate serial_get_tty_state (struct serial *scb); +/* Return a pointer to a newly malloc'd ttystate containing a copy + of the state in TTYSTATE. */ + +extern serial_ttystate serial_copy_tty_state (struct serial *scb, + serial_ttystate ttystate); + /* Set the state of the tty to TTYSTATE. The change is immediate. When changing to or from raw mode, input might be discarded. Returns 0 for success, negative value for error (in which case @@ -124,10 +143,12 @@ extern serial_ttystate serial_get_tty_state (struct serial *scb); extern int serial_set_tty_state (struct serial *scb, serial_ttystate ttystate); /* printf_filtered a user-comprehensible description of ttystate on - the specified STREAM. FIXME: At present this sends output to the + the specified STREAM. FIXME: At present this sends output to the default stream - GDB_STDOUT. */ -extern void serial_print_tty_state (struct serial *scb, serial_ttystate ttystate, struct ui_file *); +extern void serial_print_tty_state (struct serial *scb, + serial_ttystate ttystate, + struct ui_file *); /* Set the tty state to NEW_TTYSTATE, where OLD_TTYSTATE is the current state (generally obtained from a recent call to @@ -135,7 +156,9 @@ extern void serial_print_tty_state (struct serial *scb, serial_ttystate ttystate This means that we never switch in or out of raw mode, even if NEW_TTYSTATE specifies a switch. */ -extern int serial_noflush_set_tty_state (struct serial *scb, serial_ttystate new_ttystate, serial_ttystate old_ttystate); +extern int serial_noflush_set_tty_state (struct serial *scb, + serial_ttystate new_ttystate, + serial_ttystate old_ttystate); /* Set the baudrate to the decimal value supplied. Returns 0 for success, -1 for failure. */ @@ -153,11 +176,11 @@ extern int serial_setstopbits (struct serial *scb, int num); /* Asynchronous serial interface: */ -/* Can the serial device support asynchronous mode? */ +/* Can the serial device support asynchronous mode? */ extern int serial_can_async_p (struct serial *scb); -/* Has the serial device been put in asynchronous mode? */ +/* Has the serial device been put in asynchronous mode? */ extern int serial_is_async_p (struct serial *scb); @@ -166,11 +189,12 @@ extern int serial_is_async_p (struct serial *scb); callback. */ typedef void (serial_event_ftype) (struct serial *scb, void *context); -extern void serial_async (struct serial *scb, serial_event_ftype *handler, void *context); +extern void serial_async (struct serial *scb, + serial_event_ftype *handler, void *context); /* Provide direct access to the underlying FD (if any) used to implement the serial device. This interface is clearly - deprecated. Will call internal_error() if the operation isn't + deprecated. Will call internal_error() if the operation isn't applicable to the current serial device. */ extern int deprecated_serial_fd (struct serial *scb); @@ -185,7 +209,7 @@ extern void serial_debug (struct serial *scb, int debug_p); extern int serial_debug_p (struct serial *scb); -/* Details of an instance of a serial object */ +/* Details of an instance of a serial object. */ struct serial { @@ -222,6 +246,7 @@ struct serial_ops struct serial_ops *next; int (*open) (struct serial *, const char *name); void (*close) (struct serial *); + int (*fdopen) (struct serial *, int fd); int (*readchar) (struct serial *, int timeout); int (*write) (struct serial *, const char *str, int len); /* Discard pending output */ @@ -231,6 +256,7 @@ struct serial_ops int (*send_break) (struct serial *); void (*go_raw) (struct serial *); serial_ttystate (*get_tty_state) (struct serial *); + serial_ttystate (*copy_tty_state) (struct serial *, serial_ttystate); int (*set_tty_state) (struct serial *, serial_ttystate); void (*print_tty_state) (struct serial *, serial_ttystate, struct ui_file *); @@ -238,7 +264,7 @@ struct serial_ops serial_ttystate); int (*setbaudrate) (struct serial *, int rate); int (*setstopbits) (struct serial *, int num); - /* Wait for output to drain */ + /* Wait for output to drain. */ int (*drain_output) (struct serial *); /* Change the serial device into/out of asynchronous mode, call the specified function when ever there is something @@ -265,11 +291,11 @@ struct serial_ops #endif /* USE_WIN32API */ }; -/* Add a new serial interface to the interface list */ +/* Add a new serial interface to the interface list. */ extern void serial_add_interface (struct serial_ops * optable); -/* File in which to record the remote debugging session */ +/* File in which to record the remote debugging session. */ extern void serial_log_command (const char *); diff --git a/contrib/gdb-7/gdb/sim-regno.h b/contrib/gdb-7/gdb/sim-regno.h index 46e16bcd04..78c3f329d7 100644 --- a/contrib/gdb-7/gdb/sim-regno.h +++ b/contrib/gdb-7/gdb/sim-regno.h @@ -1,6 +1,7 @@ /* Generic remote debugging interface for simulators. - Copyright (C) 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Red Hat, Inc. diff --git a/contrib/gdb-7/gdb/solib-svr4.c b/contrib/gdb-7/gdb/solib-svr4.c index 1f135d450e..30abaa7c81 100644 --- a/contrib/gdb-7/gdb/solib-svr4.c +++ b/contrib/gdb-7/gdb/solib-svr4.c @@ -1,7 +1,7 @@ /* Handle SVR4 shared libraries for GDB, the GNU Debugger. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -52,7 +52,7 @@ static struct link_map_offsets *svr4_fetch_link_map_offsets (void); static int svr4_have_link_map_offsets (void); static void svr4_relocate_main_executable (void); -/* Link map info to include in an allocated so_list entry */ +/* Link map info to include in an allocated so_list entry. */ struct lm_info { @@ -80,7 +80,7 @@ struct lm_info SVR4 systems will fall back to using a symbol as the "startup mapping complete" breakpoint address. */ -static char *solib_break_names[] = +static const char * const solib_break_names[] = { "r_debug_state", "_r_debug_state", @@ -92,7 +92,7 @@ static char *solib_break_names[] = NULL }; -static char *bkpt_names[] = +static const char * const bkpt_names[] = { "_start", "__start", @@ -100,7 +100,7 @@ static char *bkpt_names[] = NULL }; -static char *main_name_list[] = +static const char * const main_name_list[] = { "main_$main", NULL @@ -140,7 +140,7 @@ svr4_same (struct so_list *gdb, struct so_list *inferior) return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name)); } -/* link map access functions */ +/* link map access functions. */ static CORE_ADDR LM_ADDR_FROM_LINK_MAP (struct so_list *so) @@ -306,7 +306,7 @@ IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so) struct svr4_info { - CORE_ADDR debug_base; /* Base of dynamic linker structures */ + CORE_ADDR debug_base; /* Base of dynamic linker structures. */ /* Validity flag for debug_loader_offset. */ int debug_loader_offset_p; @@ -357,9 +357,7 @@ get_svr4_info (void) /* Local function prototypes */ -static int match_main (char *); - -static CORE_ADDR bfd_lookup_symbol (bfd *, char *); +static int match_main (const char *); /* @@ -387,7 +385,7 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *); */ static CORE_ADDR -bfd_lookup_symbol (bfd *abfd, char *symname) +bfd_lookup_symbol (bfd *abfd, const char *symname) { long storage_needed; asymbol *sym; @@ -596,7 +594,7 @@ find_program_interpreter (void) } -/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is +/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is returned and the corresponding PTR is set. */ static int @@ -994,7 +992,7 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) If FROM_TTYP dereferences to a non-zero integer, allow messages to be printed. This parameter is a pointer rather than an int because open_symbol_file_object() is called via catch_errors() and - catch_errors() requires a pointer argument. */ + catch_errors() requires a pointer argument. */ static int open_symbol_file_object (void *from_ttyp) @@ -1017,12 +1015,12 @@ open_symbol_file_object (void *from_ttyp) /* Always locate the debug struct, in case it has moved. */ info->debug_base = 0; if (locate_base (info) == 0) - return 0; /* failed somehow... */ + return 0; /* failed somehow... */ /* First link map member should be the executable. */ lm = solib_svr4_r_map (info); if (lm == 0) - return 0; /* failed somehow... */ + return 0; /* failed somehow... */ /* Read address of name from target memory to GDB. */ read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size); @@ -1162,7 +1160,7 @@ svr4_current_sos (void) inferior executable, so we must ignore it. For some versions of SVR4, it has no name. For others (Solaris 2.3 for example), it does have a name, so we can no longer use a missing name to - decide when to ignore it. */ + decide when to ignore it. */ else if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0) { info->main_lm_addr = new->lm_info->lm_addr; @@ -1253,9 +1251,9 @@ svr4_fetch_objfile_link_map (struct objfile *objfile) non-zero iff SONAME matches one of the known main executable names. */ static int -match_main (char *soname) +match_main (const char *soname) { - char **mainp; + const char * const *mainp; for (mainp = main_name_list; *mainp != NULL; mainp++) { @@ -1278,7 +1276,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR pc) && pc < info->interp_text_sect_high) || (pc >= info->interp_plt_sect_low && pc < info->interp_plt_sect_high) - || in_plt_section (pc, NULL)); + || in_plt_section (pc, NULL) + || in_gnu_ifunc_stub (pc)); } /* Given an executable's ABFD and target, compute the entry-point @@ -1347,7 +1346,7 @@ static int enable_break (struct svr4_info *info, int from_tty) { struct minimal_symbol *msymbol; - char **bkpt_namep; + const char * const *bkpt_namep; asection *interp_sect; gdb_byte *interp_name; CORE_ADDR sym_addr; @@ -1371,8 +1370,8 @@ enable_break (struct svr4_info *info, int from_tty) sym_addr = gdbarch_addr_bits_remove (target_gdbarch, gdbarch_convert_from_func_ptr_addr (target_gdbarch, - sym_addr, - ¤t_target)); + sym_addr, + ¤t_target)); /* On at least some versions of Solaris there's a dynamic relocation on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if @@ -1609,17 +1608,20 @@ enable_break (struct svr4_info *info, int from_tty) } } - for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++) + if (!current_inferior ()->attach_flag) { - msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); - if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) + for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++) { - sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); - sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, - sym_addr, - ¤t_target); - create_solib_event_breakpoint (target_gdbarch, sym_addr); - return 1; + msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); + if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) + { + sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); + sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + sym_addr, + ¤t_target); + create_solib_event_breakpoint (target_gdbarch, sym_addr); + return 1; + } } } return 0; @@ -1685,7 +1687,7 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size) exec_bfd. Otherwise return 0. We relocate all of the sections by the same amount. This - behavior is mandated by recent editions of the System V ABI. + behavior is mandated by recent editions of the System V ABI. According to the System V Application Binary Interface, Edition 4.1, page 5-5: @@ -1787,8 +1789,8 @@ svr4_exec_displacement (CORE_ADDR *displacementp) may be different from EXEC_BFD as the file may have been prelinked to a different address after the executable has been loaded. Moreover the address of placement in target memory can be - different from what the program headers in target memory say - this - is the goal of PIE. + different from what the program headers in target memory say - + this is the goal of PIE. Detected DISPLACEMENT covers both the offsets of PIE placement and possible new prelink performed after start of the program. Here @@ -1798,7 +1800,8 @@ svr4_exec_displacement (CORE_ADDR *displacementp) if (phdrs_size != phdrs2_size || bfd_get_arch_size (exec_bfd) != arch_size) ok = 0; - else if (arch_size == 32 && phdrs_size >= sizeof (Elf32_External_Phdr) + else if (arch_size == 32 + && phdrs_size >= sizeof (Elf32_External_Phdr) && phdrs_size % sizeof (Elf32_External_Phdr) == 0) { Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header; @@ -1846,6 +1849,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp) Elf32_External_Phdr *phdr2p; gdb_byte *buf_vaddr_p, *buf_paddr_p; CORE_ADDR vaddr, paddr; + asection *plt2_asect; phdrp = &((Elf32_External_Phdr *) buf)[i]; buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr; @@ -1860,22 +1864,53 @@ svr4_exec_displacement (CORE_ADDR *displacementp) /* Check also other adjustment combinations - PR 11786. */ - vaddr = extract_unsigned_integer (buf_vaddr_p, 4, byte_order); + vaddr = extract_unsigned_integer (buf_vaddr_p, 4, + byte_order); vaddr -= displacement; store_unsigned_integer (buf_vaddr_p, 4, byte_order, vaddr); - paddr = extract_unsigned_integer (buf_paddr_p, 4, byte_order); + paddr = extract_unsigned_integer (buf_paddr_p, 4, + byte_order); paddr -= displacement; store_unsigned_integer (buf_paddr_p, 4, byte_order, paddr); if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) continue; + /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS. */ + plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt"); + if (plt2_asect) + { + int content2; + gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz; + CORE_ADDR filesz; + + content2 = (bfd_get_section_flags (exec_bfd, plt2_asect) + & SEC_HAS_CONTENTS) != 0; + + filesz = extract_unsigned_integer (buf_filesz_p, 4, + byte_order); + + /* PLT2_ASECT is from on-disk file (exec_bfd) while + FILESZ is from the in-memory image. */ + if (content2) + filesz += bfd_get_section_size (plt2_asect); + else + filesz -= bfd_get_section_size (plt2_asect); + + store_unsigned_integer (buf_filesz_p, 4, byte_order, + filesz); + + if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) + continue; + } + ok = 0; break; } } - else if (arch_size == 64 && phdrs_size >= sizeof (Elf64_External_Phdr) + else if (arch_size == 64 + && phdrs_size >= sizeof (Elf64_External_Phdr) && phdrs_size % sizeof (Elf64_External_Phdr) == 0) { Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header; @@ -1923,6 +1958,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp) Elf64_External_Phdr *phdr2p; gdb_byte *buf_vaddr_p, *buf_paddr_p; CORE_ADDR vaddr, paddr; + asection *plt2_asect; phdrp = &((Elf64_External_Phdr *) buf)[i]; buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr; @@ -1937,17 +1973,47 @@ svr4_exec_displacement (CORE_ADDR *displacementp) /* Check also other adjustment combinations - PR 11786. */ - vaddr = extract_unsigned_integer (buf_vaddr_p, 8, byte_order); + vaddr = extract_unsigned_integer (buf_vaddr_p, 8, + byte_order); vaddr -= displacement; store_unsigned_integer (buf_vaddr_p, 8, byte_order, vaddr); - paddr = extract_unsigned_integer (buf_paddr_p, 8, byte_order); + paddr = extract_unsigned_integer (buf_paddr_p, 8, + byte_order); paddr -= displacement; store_unsigned_integer (buf_paddr_p, 8, byte_order, paddr); if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) continue; + /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS. */ + plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt"); + if (plt2_asect) + { + int content2; + gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz; + CORE_ADDR filesz; + + content2 = (bfd_get_section_flags (exec_bfd, plt2_asect) + & SEC_HAS_CONTENTS) != 0; + + filesz = extract_unsigned_integer (buf_filesz_p, 8, + byte_order); + + /* PLT2_ASECT is from on-disk file (exec_bfd) while + FILESZ is from the in-memory image. */ + if (content2) + filesz += bfd_get_section_size (plt2_asect); + else + filesz -= bfd_get_section_size (plt2_asect); + + store_unsigned_integer (buf_filesz_p, 8, byte_order, + filesz); + + if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) + continue; + } + ok = 0; break; } @@ -1980,7 +2046,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp) } /* Relocate the main executable. This function should be called upon - stopping the inferior process at the entry point to the program. + stopping the inferior process at the entry point to the program. The entry point from BFD is compared to the AT_ENTRY of AUXV and if they are different, the main executable is relocated by the proper amount. */ @@ -2013,8 +2079,7 @@ svr4_relocate_main_executable (void) the `qOffsets' packet. - The section offsets were not reset earlier, and the best we can - hope is that the old offsets are still applicable to the new run. - */ + hope is that the old offsets are still applicable to the new run. */ if (! svr4_exec_displacement (&displacement)) return; @@ -2112,6 +2177,11 @@ svr4_solib_create_inferior_hook (int from_tty) /* Relocate the main executable if necessary. */ svr4_relocate_main_executable (); + /* No point setting a breakpoint in the dynamic linker if we can't + hit it (e.g., a core file, or a trace file). */ + if (!target_has_execution) + return; + if (!svr4_have_link_map_offsets ()) return; @@ -2126,21 +2196,21 @@ svr4_solib_create_inferior_hook (int from_tty) Now run the target. It will eventually hit the breakpoint, at which point all of the libraries will have been mapped in and we can go groveling around in the dynamic linker structures to find - out what we need to know about them. */ + out what we need to know about them. */ inf = current_inferior (); tp = inferior_thread (); clear_proceed_status (); - inf->stop_soon = STOP_QUIETLY; - tp->stop_signal = TARGET_SIGNAL_0; + inf->control.stop_soon = STOP_QUIETLY; + tp->suspend.stop_signal = TARGET_SIGNAL_0; do { - target_resume (pid_to_ptid (-1), 0, tp->stop_signal); + target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal); wait_for_inferior (0); } - while (tp->stop_signal != TARGET_SIGNAL_TRAP); - inf->stop_soon = NO_STOP_QUIETLY; + while (tp->suspend.stop_signal != TARGET_SIGNAL_TRAP); + inf->control.stop_soon = NO_STOP_QUIETLY; #endif /* defined(_SCO_DS) */ } @@ -2330,7 +2400,7 @@ svr4_lp64_fetch_link_map_offsets (void) struct target_so_ops svr4_so_ops; -/* Lookup global symbol for ELF DSOs linked with -Bsymbolic. Those DSOs have a +/* Lookup global symbol for ELF DSOs linked with -Bsymbolic. Those DSOs have a different rule for symbol lookup. The lookup begins here in the DSO, not in the main executable. */ diff --git a/contrib/gdb-7/gdb/solib-svr4.h b/contrib/gdb-7/gdb/solib-svr4.h index f27bde8e92..b35f0db602 100644 --- a/contrib/gdb-7/gdb/solib-svr4.h +++ b/contrib/gdb-7/gdb/solib-svr4.h @@ -1,6 +1,6 @@ /* Handle shared libraries for GDB, the GNU Debugger. - Copyright (C) 2000, 2004, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2000, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/solib.c b/contrib/gdb-7/gdb/solib.c index 837814b590..819eb7dab7 100644 --- a/contrib/gdb-7/gdb/solib.c +++ b/contrib/gdb-7/gdb/solib.c @@ -1,7 +1,7 @@ /* Handle shared libraries for GDB, the GNU Debugger. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -102,8 +102,8 @@ static void show_solib_search_path (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The search path for loading non-absolute shared library symbol files is %s.\n"), + fprintf_filtered (file, _("The search path for loading non-absolute " + "shared library symbol files is %s.\n"), value); } @@ -345,12 +345,12 @@ solib_find (char *in_pathname, int *fd) target_lbasename (fskind, in_pathname), O_RDONLY | O_BINARY, &temp_pathname); - /* If not found, try to use target supplied solib search method */ + /* If not found, try to use target supplied solib search method. */ if (found_file < 0 && ops->find_and_open_solib) found_file = ops->find_and_open_solib (in_pathname, O_RDONLY | O_BINARY, &temp_pathname); - /* If not found, next search the inferior's $PATH environment variable. */ + /* If not found, next search the inferior's $PATH environment variable. */ if (found_file < 0 && gdb_sysroot_is_empty) found_file = openp (get_in_environ (current_inferior ()->environment, "PATH"), @@ -358,7 +358,7 @@ solib_find (char *in_pathname, int *fd) &temp_pathname); /* If not found, next search the inferior's $LD_LIBRARY_PATH - environment variable. */ + environment variable. */ if (found_file < 0 && gdb_sysroot_is_empty) found_file = openp (get_in_environ (current_inferior ()->environment, "LD_LIBRARY_PATH"), @@ -500,7 +500,7 @@ solib_map_sections (struct so_list *so) so->abfd = gdb_bfd_ref (abfd); /* copy full path name into so_name, so that later symbol_file_add - can find it */ + can find it. */ if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE) error (_("Shared library file name is too long.")); strcpy (so->so_name, bfd_get_filename (abfd)); @@ -515,7 +515,7 @@ solib_map_sections (struct so_list *so) { /* Relocate the section binding addresses as recorded in the shared object's file by the base address to which the object was actually - mapped. */ + mapped. */ ops->relocate_section_addresses (so, p); /* If the target didn't provide information about the address @@ -580,7 +580,7 @@ free_so_symbols (struct so_list *so) DESCRIPTION Free the storage associated with the `struct so_list' object SO. - If we have opened a BFD for SO, close it. + If we have opened a BFD for SO, close it. The caller is responsible for removing SO from whatever list it is a member of. If we have placed SO's sections in some target's @@ -638,7 +638,8 @@ solib_read_symbols (struct so_list *so, int flags) /* Have we already loaded this shared object? */ ALL_OBJFILES (so->objfile) { - if (strcmp (so->objfile->name, so->so_name) == 0) + if (filename_cmp (so->objfile->name, so->so_name) == 0 + && so->objfile->addr_low == so->addr_low) break; } if (so->objfile != NULL) @@ -648,16 +649,14 @@ solib_read_symbols (struct so_list *so, int flags) so->sections_end); so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED); + so->objfile->addr_low = so->addr_low; free_section_addr_info (sap); } if (e.reason < 0) - { - if (from_tty) - exception_fprintf - (gdb_stderr, e, - _("Error while reading shared library symbols:\n")); - } + exception_fprintf (gdb_stderr, e, _("Error while reading shared" + " library symbols for %s:\n"), + so->so_name); else { if (from_tty || info_verbose) @@ -763,7 +762,7 @@ update_solib_list (int from_tty, struct target_ops *target) } else { - if (! strcmp (gdb->so_original_name, i->so_original_name)) + if (! filename_cmp (gdb->so_original_name, i->so_original_name)) break; } @@ -836,8 +835,9 @@ update_solib_list (int from_tty, struct target_ops *target) } if (e.reason < 0) - exception_fprintf (gdb_stderr, e, _("\ -Error while mapping shared library sections:\n")); + exception_fprintf (gdb_stderr, e, + _("Error while mapping shared " + "library sections:\n")); /* Notify any observer that the shared object has been loaded now that we've added it to GDB's tables. */ @@ -852,9 +852,9 @@ Error while mapping shared library sections:\n")); stand out well. */ if (not_found == 1) - warning (_("\ -Could not load shared library symbols for %s.\n\ -Do you need \"set solib-search-path\" or \"set sysroot\"?"), + warning (_("Could not load shared library symbols for %s.\n" + "Do you need \"set solib-search-path\" " + "or \"set sysroot\"?"), not_found_filename); else if (not_found > 1) warning (_("\ @@ -907,7 +907,8 @@ libpthread_solib_p (struct so_list *so) FROM_TTY and TARGET are as described for update_solib_list, above. */ void -solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms) +solib_add (char *pattern, int from_tty, + struct target_ops *target, int readsyms) { struct so_list *gdb; @@ -1099,7 +1100,8 @@ info_sharedlibrary_command (char *pattern, int from_tty) { if (so_missing_debug_info) ui_out_message (uiout, 0, - _("(*): Shared library is missing debugging information.\n")); + _("(*): Shared library is missing " + "debugging information.\n")); } } @@ -1324,6 +1326,7 @@ reload_shared_libraries_1 (int from_tty) SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0); filename = tilde_expand (so->so_original_name); + make_cleanup (xfree, filename); abfd = solib_bfd_open (filename); if (abfd != NULL) { @@ -1336,7 +1339,7 @@ reload_shared_libraries_1 (int from_tty) symbol file, close that. */ if ((found_pathname == NULL && was_loaded) || (found_pathname != NULL - && strcmp (found_pathname, so->so_name) != 0)) + && filename_cmp (found_pathname, so->so_name) != 0)) { if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)) free_objfile (so->objfile); @@ -1348,7 +1351,7 @@ reload_shared_libraries_1 (int from_tty) file, open it. */ if (found_pathname != NULL && (!was_loaded - || strcmp (found_pathname, so->so_name) != 0)) + || filename_cmp (found_pathname, so->so_name) != 0)) { volatile struct gdb_exception e; @@ -1356,8 +1359,9 @@ reload_shared_libraries_1 (int from_tty) solib_map_sections (so); if (e.reason < 0) - exception_fprintf (gdb_stderr, e, _("\ -Error while mapping shared library sections:\n")); + exception_fprintf (gdb_stderr, e, + _("Error while mapping " + "shared library sections:\n")); else if (auto_solib_add || was_loaded || libpthread_solib_p (so)) solib_read_symbols (so, flags); } @@ -1376,7 +1380,7 @@ reload_shared_libraries (char *ignored, int from_tty, ops = solib_ops (target_gdbarch); - /* Creating inferior hooks here has two purposes. First, if we reload + /* Creating inferior hooks here has two purposes. First, if we reload shared libraries then the address of solib breakpoint we've computed previously might be no longer valid. For example, if we forgot to set solib-absolute-prefix and are setting it right now, then the previous @@ -1470,7 +1474,8 @@ Show autoloading of shared library symbols."), _("\ If \"on\", symbols from all shared object libraries will be loaded\n\ automatically when the inferior begins execution, when the dynamic linker\n\ informs gdb that a new library has been loaded, or when attaching to the\n\ -inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'."), +inferior. Otherwise, symbols must be loaded manually, using \ +`sharedlibrary'."), NULL, show_auto_solib_add, &setlist, &showlist); @@ -1493,9 +1498,12 @@ For other (relative) files, you can add directories using\n\ add_setshow_optional_filename_cmd ("solib-search-path", class_support, &solib_search_path, _("\ -Set the search path for loading non-absolute shared library symbol files."), _("\ -Show the search path for loading non-absolute shared library symbol files."), _("\ -This takes precedence over the environment variables PATH and LD_LIBRARY_PATH."), +Set the search path for loading non-absolute shared library symbol files."), + _("\ +Show the search path for loading non-absolute shared library symbol files."), + _("\ +This takes precedence over the environment variables \ +PATH and LD_LIBRARY_PATH."), reload_shared_libraries, show_solib_search_path, &setlist, &showlist); diff --git a/contrib/gdb-7/gdb/solib.h b/contrib/gdb-7/gdb/solib.h index 03a4b08b26..c473d85578 100644 --- a/contrib/gdb-7/gdb/solib.h +++ b/contrib/gdb-7/gdb/solib.h @@ -1,7 +1,7 @@ /* Shared library declarations for GDB, the GNU Debugger. Copyright (C) 1992, 1993, 1995, 1998, 1999, 2000, 2001, 2003, 2005, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -28,11 +28,11 @@ struct target_so_ops; struct program_space; /* Called when we free all symtabs, to free the shared library information - as well. */ + as well. */ extern void clear_solib (void); -/* Called to add symbols from a shared library to gdb's symbol table. */ +/* Called to add symbols from a shared library to gdb's symbol table. */ extern void solib_add (char *, int, struct target_ops *, int); extern int solib_read_symbols (struct so_list *, int); @@ -65,7 +65,7 @@ extern int solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size); extern int in_solib_dynsym_resolve_code (CORE_ADDR); -/* Discard symbols that were auto-loaded from shared libraries. */ +/* Discard symbols that were auto-loaded from shared libraries. */ extern void no_shared_libraries (char *ignored, int from_tty); diff --git a/contrib/gdb-7/gdb/solist.h b/contrib/gdb-7/gdb/solist.h index bcba0ad65b..dad11be46f 100644 --- a/contrib/gdb-7/gdb/solist.h +++ b/contrib/gdb-7/gdb/solist.h @@ -1,6 +1,6 @@ /* Shared library declarations for GDB, the GNU Debugger. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -39,7 +39,7 @@ struct so_list /* A pointer to target specific link map information. Often this will be a copy of struct link_map from the user process, but it need not be; it can be any collection of data needed to - traverse the dynamic linker's data structures. */ + traverse the dynamic linker's data structures. */ struct lm_info *lm_info; /* Shared object file name, exactly as it appears in the @@ -49,7 +49,7 @@ struct so_list map we've already loaded. */ char so_original_name[SO_NAME_MAX_PATH_SIZE]; - /* shared object file name, expanded to something GDB can open */ + /* Shared object file name, expanded to something GDB can open. */ char so_name[SO_NAME_MAX_PATH_SIZE]; /* Program space this shared library belongs to. */ @@ -62,7 +62,7 @@ struct so_list current_sos must initialize these fields to 0. */ bfd *abfd; - char symbols_loaded; /* flag: symbols read in yet? */ + char symbols_loaded; /* flag: symbols read in yet? */ /* objfile with symbols for a loaded library. Target memory is read from ABFD. OBJFILE may be NULL either before symbols have been loaded, if @@ -85,8 +85,8 @@ struct target_so_ops void (*relocate_section_addresses) (struct so_list *so, struct target_section *); - /* Free the the link map info and any other private data - structures associated with a so_list entry. */ + /* Free the link map info and any other private data structures + associated with a so_list entry. */ void (*free_so) (struct so_list *so); /* Reset or free private data structures not associated with @@ -107,13 +107,13 @@ struct target_so_ops int (*open_symbol_file_object) (void *from_ttyp); /* Determine if PC lies in the dynamic symbol resolution code of - the run time loader */ + the run time loader. */ int (*in_dynsym_resolve_code) (CORE_ADDR pc); /* Find and open shared library binary file. */ bfd *(*bfd_open) (char *pathname); - /* Extra hook for finding and opening a solib. + /* Extra hook for finding and opening a solib. Convenience function for remote debuggers finding host libs. */ int (*find_and_open_solib) (char *soname, unsigned o_flags, char **temp_pathname); @@ -154,7 +154,7 @@ extern bfd *solib_bfd_fopen (char *pathname, int fd); /* Find solib binary file and open it. */ extern bfd *solib_bfd_open (char *in_pathname); -/* FIXME: gdbarch needs to control this variable */ +/* FIXME: gdbarch needs to control this variable. */ extern struct target_so_ops *current_target_so_ops; /* Handler for library-specific global symbol lookup in solib.c. */ diff --git a/contrib/gdb-7/gdb/source.c b/contrib/gdb-7/gdb/source.c index 3e896726a0..5710f14d3d 100644 --- a/contrib/gdb-7/gdb/source.c +++ b/contrib/gdb-7/gdb/source.c @@ -1,7 +1,7 @@ /* List lines of source files for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -52,11 +52,11 @@ #define OPEN_MODE (O_RDONLY | O_BINARY) #define FDOPEN_MODE FOPEN_RB -/* Prototypes for exported functions. */ +/* Prototypes for exported functions. */ void _initialize_source (void); -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static int get_filename_and_charpos (struct symtab *, char **); @@ -68,8 +68,6 @@ static void line_info (char *, int); static void source_info (char *, int); -static void show_directories (char *, int); - /* Path of directories to search for source files. Same format as the PATH environment variable's value. */ @@ -107,8 +105,9 @@ static void show_lines_to_list (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Number of source lines gdb will list by default is %s.\n"), + fprintf_filtered (file, + _("Number of source lines gdb " + "will list by default is %s.\n"), value); } @@ -122,14 +121,14 @@ static int last_line_listed; static int first_line_listed; /* Saves the name of the last source file visited and a possible error code. - Used to prevent repeating annoying "No such file or directories" msgs */ + Used to prevent repeating annoying "No such file or directories" msgs. */ static struct symtab *last_source_visited = NULL; static int last_source_error = 0; /* Return the first line listed by print_source_lines. Used by command interpreters to request listing from - a previous point. */ + a previous point. */ int get_first_line_listed (void) @@ -140,7 +139,7 @@ get_first_line_listed (void) /* Return the default number of lines to print with commands like the cli "list". The caller of print_source_lines must use this to calculate the end line and use it in the call to print_source_lines - as it does not automatically use this value. */ + as it does not automatically use this value. */ int get_lines_to_list (void) @@ -149,7 +148,7 @@ get_lines_to_list (void) } /* Return the current source file for listing and next line to list. - NOTE: The returned sal pc and end fields are not valid. */ + NOTE: The returned sal pc and end fields are not valid. */ struct symtab_and_line get_current_source_symtab_and_line (void) @@ -171,7 +170,7 @@ get_current_source_symtab_and_line (void) We must be cautious about where it is called, as it can recurse as the process of determining a new default may call the caller! Use get_current_source_symtab_and_line only to get whatever - we have without erroring out or trying to get a default. */ + we have without erroring out or trying to get a default. */ void set_default_source_symtab_and_line (void) @@ -179,7 +178,7 @@ set_default_source_symtab_and_line (void) if (!have_full_symbols () && !have_partial_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); - /* Pull in a current source symtab if necessary */ + /* Pull in a current source symtab if necessary. */ if (current_source_symtab == 0) select_source_symtab (0); } @@ -187,7 +186,7 @@ set_default_source_symtab_and_line (void) /* Return the current default file for listing and next line to list (the returned sal pc and end fields are not valid.) and set the current default to whatever is in SAL. - NOTE: The returned sal pc and end fields are not valid. */ + NOTE: The returned sal pc and end fields are not valid. */ struct symtab_and_line set_current_source_symtab_and_line (const struct symtab_and_line *sal) @@ -207,7 +206,7 @@ set_current_source_symtab_and_line (const struct symtab_and_line *sal) return cursal; } -/* Reset any information stored about a default file and line to print. */ +/* Reset any information stored about a default file and line to print. */ void clear_current_source_symtab_and_line (void) @@ -293,14 +292,49 @@ select_source_symtab (struct symtab *s) error (_("Can't find a default source file")); } +/* Handler for "set directories path-list" command. + "set dir mumble" doesn't prepend paths, it resets the entire + path list. The theory is that set(show(dir)) should be a no-op. */ + +static void +set_directories_command (char *args, int from_tty, struct cmd_list_element *c) +{ + /* This is the value that was set. + It needs to be processed to maintain $cdir:$cwd and remove dups. */ + char *set_path = source_path; + + /* We preserve the invariant that $cdir:$cwd begins life at the end of + the list by calling init_source_path. If they appear earlier in + SET_PATH then mod_path will move them appropriately. + mod_path will also remove duplicates. */ + init_source_path (); + if (*set_path != '\0') + mod_path (set_path, &source_path); + + xfree (set_path); +} + +/* Print the list of source directories. + This is used by the "ld" command, so it has the signature of a command + function. */ + static void -show_directories (char *ignore, int from_tty) +show_directories_1 (char *ignore, int from_tty) { puts_filtered ("Source directories searched: "); puts_filtered (source_path); puts_filtered ("\n"); } +/* Handler for "show directories" command. */ + +static void +show_directories_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + show_directories_1 (NULL, from_tty); +} + /* Forget what we learned about line positions in source files, and which directories contain them; must check again now since files may be found in a different directory now. */ @@ -352,7 +386,7 @@ void directory_command (char *dirname, int from_tty) { dont_repeat (); - /* FIXME, this goes to "delete dir"... */ + /* FIXME, this goes to "delete dir"... */ if (dirname == 0) { if (!from_tty || query (_("Reinitialize source path to empty? "))) @@ -367,7 +401,7 @@ directory_command (char *dirname, int from_tty) forget_cached_source_info (); } if (from_tty) - show_directories ((char *) 0, from_tty); + show_directories_1 ((char *) 0, from_tty); } /* Add a path given with the -d command line switch. @@ -391,7 +425,7 @@ mod_path (char *dirname, char **which_path) if dirname should be parsed for separators that indicate multiple directories. This allows for interfaces that pre-parse the dirname and allow specification of traditional separator characters such - as space or tab. */ + as space or tab. */ void add_path (char *dirname, char **which_path, int parse_separators) @@ -408,7 +442,7 @@ add_path (char *dirname, char **which_path, int parse_separators) if (parse_separators) { /* This will properly parse the space and tab separators - and any quotes that may exist. DIRNAME_SEPARATOR will + and any quotes that may exist. DIRNAME_SEPARATOR will be dealt with later. */ argv = gdb_buildargv (dirname); make_cleanup_freeargv (argv); @@ -461,7 +495,7 @@ add_path (char *dirname, char **which_path, int parse_separators) && !(p == name + 3 && name[1] == ':') /* "d:/" */ #endif && IS_DIR_SEPARATOR (p[-1])) - /* Sigh. "foo/" => "foo" */ + /* Sigh. "foo/" => "foo" */ --p; *p = '\0'; @@ -535,22 +569,17 @@ add_path (char *dirname, char **which_path, int parse_separators) p = *which_path; while (1) { - /* FIXME: strncmp loses in interesting ways on MS-DOS and - MS-Windows because of case-insensitivity and two different - but functionally identical slash characters. We need a - special filesystem-dependent file-name comparison function. - - Actually, even on Unix I would use realpath() or its work- - alike before comparing. Then all the code above which + /* FIXME: we should use realpath() or its work-alike + before comparing. Then all the code above which removes excess slashes and dots could simply go away. */ - if (!strncmp (p, name, len) + if (!filename_ncmp (p, name, len) && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR)) { - /* Found it in the search path, remove old copy */ + /* Found it in the search path, remove old copy. */ if (p > *which_path) - p--; /* Back over leading separator */ + p--; /* Back over leading separator. */ if (prefix > p - *which_path) - goto skip_dup; /* Same dir twice in one cmd */ + goto skip_dup; /* Same dir twice in one cmd. */ strcpy (p, &p[len + 1]); /* Copy from next \0 or : */ } p = strchr (p, DIRNAME_SEPARATOR); @@ -566,8 +595,9 @@ add_path (char *dirname, char **which_path, int parse_separators) tinybuf[0] = DIRNAME_SEPARATOR; tinybuf[1] = '\0'; - /* If we have already tacked on a name(s) in this command, be sure they stay - on the front as we tack on some more. */ + /* If we have already tacked on a name(s) in this command, + be sure they stay on the front as we tack on some + more. */ if (prefix) { char *temp, c; @@ -576,7 +606,7 @@ add_path (char *dirname, char **which_path, int parse_separators) old[prefix] = '\0'; temp = concat (old, tinybuf, name, (char *)NULL); old[prefix] = c; - *which_path = concat (temp, "", &old[prefix], (char *)NULL); + *which_path = concat (temp, "", &old[prefix], (char *) NULL); prefix = strlen (temp); xfree (temp); } @@ -590,7 +620,8 @@ add_path (char *dirname, char **which_path, int parse_separators) old = *which_path; } } - skip_dup:; + skip_dup: + ; } while (arg != NULL); } @@ -622,7 +653,7 @@ source_info (char *ignore, int from_tty) } -/* Return True if the file NAME exists and is a regular file */ +/* Return True if the file NAME exists and is a regular file. */ static int is_regular_file (const char *name) { @@ -632,8 +663,8 @@ is_regular_file (const char *name) /* Stat should never fail except when the file does not exist. If stat fails, analyze the source of error and return True unless the file does not exist, to avoid returning false results - on obscure systems where stat does not work as expected. - */ + on obscure systems where stat does not work as expected. */ + if (status != 0) return (errno != ENOENT); @@ -666,7 +697,7 @@ is_regular_file (const char *name) Otherwise, return -1, with errno set for the last name we tried to open. */ /* >>>> This should only allow files of certain types, - >>>> eg executable, non-directory */ + >>>> eg executable, non-directory. */ int openp (const char *path, int opts, const char *string, int mode, char **filename_opened) @@ -728,7 +759,7 @@ openp (const char *path, int opts, const char *string, if (HAS_DRIVE_SPEC (string)) string = STRIP_DRIVE_SPEC (string); - /* /foo => foo, to avoid multiple slashes that Emacs doesn't like. */ + /* /foo => foo, to avoid multiple slashes that Emacs doesn't like. */ while (IS_DIR_SEPARATOR(string[0])) string++; @@ -753,7 +784,7 @@ openp (const char *path, int opts, const char *string, /* Name is $cwd -- insert current directory name instead. */ int newlen; - /* First, realloc the filename buffer if too short. */ + /* First, realloc the filename buffer if too short. */ len = strlen (current_directory); newlen = len + strlen (string) + 2; if (newlen > alloclen) @@ -780,7 +811,7 @@ openp (const char *path, int opts, const char *string, continue; } - /* Remove trailing slashes */ + /* Remove trailing slashes. */ while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1])) filename[--len] = 0; @@ -798,9 +829,9 @@ openp (const char *path, int opts, const char *string, done: if (filename_opened) { - /* If a file was opened, canonicalize its filename. Use xfullpath + /* If a file was opened, canonicalize its filename. Use xfullpath rather than gdb_realpath to avoid resolving the basename part - of filenames when the associated file is a symbolic link. This + of filenames when the associated file is a symbolic link. This fixes a potential inconsistency between the filenames known to GDB and the filenames it prints in the annotations. */ if (fd < 0) @@ -809,7 +840,7 @@ done: *filename_opened = xfullpath (filename); else { - /* Beware the // my son, the Emacs barfs, the botch that catch... */ + /* Beware the // my son, the Emacs barfs, the botch that catch... */ char *f = concat (current_directory, IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]) @@ -905,7 +936,7 @@ get_substitute_path_rule (const char *path) /* If the user specified a source path substitution rule that applies to PATH, then apply it and return the new path. This new path must - be deallocated afterwards. + be deallocated afterwards. Return NULL if no substitution rule was specified by the user, or if no rule applied to the given PATH. */ @@ -933,8 +964,8 @@ rewrite_source_path (const char *path) } /* This function is capable of finding the absolute path to a - source file, and opening it, provided you give it a FILENAME. Both the - DIRNAME and FULLNAME are only added suggestions on where to find the file. + source file, and opening it, provided you give it a FILENAME. Both the + DIRNAME and FULLNAME are only added suggestions on where to find the file. FILENAME should be the filename to open. DIRNAME is the compilation directory of a particular source file. @@ -944,12 +975,12 @@ rewrite_source_path (const char *path) is applied we free the old value and set a new one. On Success - A valid file descriptor is returned. ( the return value is positive ) + A valid file descriptor is returned (the return value is positive). FULLNAME is set to the absolute path to the file just opened. The caller is responsible for freeing FULLNAME. On Failure - An invalid file descriptor is returned. ( the return value is negative ) + An invalid file descriptor is returned (the return value is negative). FULLNAME is set to NULL. */ int @@ -961,7 +992,7 @@ find_and_open_source (const char *filename, const char *p; int result; - /* Quick way out if we already know its full name */ + /* Quick way out if we already know its full name. */ if (*fullname) { @@ -979,7 +1010,7 @@ find_and_open_source (const char *filename, result = open (*fullname, OPEN_MODE); if (result >= 0) return result; - /* Didn't work -- free old one, try again. */ + /* Didn't work -- free old one, try again. */ xfree (*fullname); *fullname = NULL; } @@ -997,10 +1028,11 @@ find_and_open_source (const char *filename, dirname = rewritten_dirname; } - /* Replace a path entry of $cdir with the compilation directory name */ + /* Replace a path entry of $cdir with the compilation directory + name. */ #define cdir_len 5 /* We cast strstr's result in case an ANSIhole has made it const, - which produces a "required warning" when assigned to a nonconst. */ + which produces a "required warning" when assigned to a nonconst. */ p = (char *) strstr (source_path, "$cdir"); if (p && (p == path || p[-1] == DIRNAME_SEPARATOR) && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0')) @@ -1011,8 +1043,9 @@ find_and_open_source (const char *filename, alloca (strlen (source_path) + 1 + strlen (dirname) + 1); len = p - source_path; strncpy (path, source_path, len); /* Before $cdir */ - strcpy (path + len, dirname); /* new stuff */ - strcat (path + len, source_path + len + cdir_len); /* After $cdir */ + strcpy (path + len, dirname); /* new stuff */ + strcat (path + len, source_path + len + cdir_len); /* After + $cdir */ } } @@ -1032,7 +1065,7 @@ find_and_open_source (const char *filename, result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, fullname); if (result < 0) { - /* Didn't work. Try using just the basename. */ + /* Didn't work. Try using just the basename. */ p = lbasename (filename); if (p != filename) result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, fullname); @@ -1044,7 +1077,7 @@ find_and_open_source (const char *filename, /* Open a source file given a symtab S. Returns a file descriptor or negative number for error. - This function is a convience function to find_and_open_source. */ + This function is a convience function to find_and_open_source. */ int open_source_file (struct symtab *s) @@ -1071,7 +1104,7 @@ symtab_to_fullname (struct symtab *s) return NULL; /* Don't check s->fullname here, the file could have been - deleted/moved/..., look for it again */ + deleted/moved/..., look for it again. */ r = find_and_open_source (s->filename, s->dirname, &s->fullname); if (r >= 0) @@ -1116,7 +1149,7 @@ find_source_lines (struct symtab *s, int desc) { char c; - /* Have to read it byte by byte to find out where the chars live */ + /* Have to read it byte by byte to find out where the chars live. */ line_charpos[0] = lseek (desc, 0, SEEK_CUR); nlines = 1; @@ -1209,7 +1242,7 @@ source_charpos_line (struct symtab *s, int chr) if (s == 0 || s->line_charpos == 0) return 0; lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok */ + /* Files are usually short, so sequential search is Ok. */ while (line < s->nlines && *lnp <= chr) { line++; @@ -1284,7 +1317,7 @@ identify_source_line (struct symtab *s, int line, int mid_statement, /* Print source lines from the file of symtab S, - starting with line number LINE and stopping before line number STOPLINE. */ + starting with line number LINE and stopping before line number STOPLINE. */ static void print_source_lines_base (struct symtab *s, int line, int stopline, int noerror); @@ -1298,15 +1331,16 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) int nlines = stopline - line; struct cleanup *cleanup; - /* Regardless of whether we can open the file, set current_source_symtab. */ + /* Regardless of whether we can open the file, set current_source_symtab. */ current_source_symtab = s; current_source_line = line; first_line_listed = line; - /* If printing of source lines is disabled, just print file and line number */ + /* If printing of source lines is disabled, just print file and line + number. */ if (ui_out_test_flags (uiout, ui_source_list)) { - /* Only prints "No such file or directory" once */ + /* Only prints "No such file or directory" once. */ if ((s != last_source_visited) || (!last_source_error)) { last_source_visited = s; @@ -1410,7 +1444,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) /* Show source lines from the file of symtab S, starting with line number LINE and stopping before line number STOPLINE. If this is not the command line version, then the source is shown in the source - window otherwise it is simply printed */ + window otherwise it is simply printed. */ void print_source_lines (struct symtab *s, int line, int stopline, int noerror) @@ -1447,7 +1481,7 @@ line_info (char *arg, int from_tty) } /* C++ More than one line may have been specified, as when the user - specifies an overloaded function name. Print info on them all. */ + specifies an overloaded function name. Print info on them all. */ for (i = 0; i < sals.nelts; i++) { sal = sals.sals[i]; @@ -1592,11 +1626,11 @@ forward_search_command (char *regex, int from_tty) p[-1] = '\n'; } - /* we now have a source line in buf, null terminate and match */ + /* We now have a source line in buf, null terminate and match. */ *p = 0; if (re_exec (buf) > 0) { - /* Match! */ + /* Match! */ do_cleanups (cleanups); print_source_lines (current_source_symtab, line, line + 1, 0); set_internalvar_integer (lookup_internalvar ("_"), line); @@ -1649,8 +1683,8 @@ reverse_search_command (char *regex, int from_tty) cleanups = make_cleanup_fclose (stream); while (line > 1) { -/* FIXME!!! We walk right off the end of buf if we get a long line!!! */ - char buf[4096]; /* Should be reasonable??? */ +/* FIXME!!! We walk right off the end of buf if we get a long line!!! */ + char buf[4096]; /* Should be reasonable??? */ char *p = buf; c = getc (stream); @@ -1674,7 +1708,7 @@ reverse_search_command (char *regex, int from_tty) *p = 0; if (re_exec (buf) > 0) { - /* Match! */ + /* Match! */ do_cleanups (cleanups); print_source_lines (current_source_symtab, line, line + 1, 0); set_internalvar_integer (lookup_internalvar ("_"), line); @@ -1938,16 +1972,27 @@ With no argument, reset the search path to $cdir:$cwd, the default."), set_cmd_completer (c, filename_completer); - add_cmd ("directories", no_class, show_directories, _("\ -Current search path for finding source files.\n\ + add_setshow_optional_filename_cmd ("directories", + class_files, + &source_path, + _("\ +Set the search path for finding source files."), + _("\ +Show the search path for finding source files."), + _("\ $cwd in the path means the current working directory.\n\ -$cdir in the path means the compilation directory of the source file."), - &showlist); +$cdir in the path means the compilation directory of the source file.\n\ +GDB ensures the search path always ends with $cdir:$cwd by\n\ +appending these directories if necessary.\n\ +Setting the value to an empty string sets it to $cdir:$cwd, the default."), + set_directories_command, + show_directories_command, + &setlist, &showlist); if (xdb_commands) { add_com_alias ("D", "directory", class_files, 0); - add_cmd ("ld", no_class, show_directories, _("\ + add_cmd ("ld", no_class, show_directories_1, _("\ Current search path for finding source files.\n\ $cwd in the path means the current working directory.\n\ $cdir in the path means the compilation directory of the source file."), diff --git a/contrib/gdb-7/gdb/source.h b/contrib/gdb-7/gdb/source.h index 7b755c6b52..501d0b36b9 100644 --- a/contrib/gdb-7/gdb/source.h +++ b/contrib/gdb-7/gdb/source.h @@ -1,5 +1,6 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1999, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1999, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -35,17 +36,17 @@ extern void find_source_lines (struct symtab *s, int desc); /* Return the first line listed by print_source_lines. Used by command interpreters to request listing from - a previous point. */ + a previous point. */ extern int get_first_line_listed (void); /* Return the default number of lines to print with commands like the cli "list". The caller of print_source_lines must use this to calculate the end line and use it in the call to print_source_lines - as it does not automatically use this value. */ + as it does not automatically use this value. */ extern int get_lines_to_list (void); /* Return the current source file for listing and next line to list. - NOTE: The returned sal pc and end fields are not valid. */ + NOTE: The returned sal pc and end fields are not valid. */ extern struct symtab_and_line get_current_source_symtab_and_line (void); /* If the current source file for listing is not set, try and get a default. @@ -54,16 +55,16 @@ extern struct symtab_and_line get_current_source_symtab_and_line (void); We must be cautious about where it is called, as it can recurse as the process of determining a new default may call the caller! Use get_current_source_symtab_and_line only to get whatever - we have without erroring out or trying to get a default. */ + we have without erroring out or trying to get a default. */ extern void set_default_source_symtab_and_line (void); /* Return the current default file for listing and next line to list (the returned sal pc and end fields are not valid.) and set the current default to whatever is in SAL. - NOTE: The returned sal pc and end fields are not valid. */ + NOTE: The returned sal pc and end fields are not valid. */ extern struct symtab_and_line set_current_source_symtab_and_line (const struct symtab_and_line *); -/* Reset any information stored about a default file and line to print. */ +/* Reset any information stored about a default file and line to print. */ extern void clear_current_source_symtab_and_line (void); /* Add a source path substitution rule. */ diff --git a/contrib/gdb-7/gdb/stabsread.c b/contrib/gdb-7/gdb/stabsread.c index b62156cbed..c7d8a6c474 100644 --- a/contrib/gdb-7/gdb/stabsread.c +++ b/contrib/gdb-7/gdb/stabsread.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ the "stabs" format. This format is used with many systems that use the a.out object file format, as well as some systems that use COFF or ELF where the stabs data is placed in a special section. - Avoid placing any object file format specific code in this file. */ + Avoid placing any object file format specific code in this file. */ #include "defs.h" #include "gdb_string.h" @@ -34,7 +34,7 @@ #include "expression.h" #include "symfile.h" #include "objfiles.h" -#include "aout/stab_gnu.h" /* We always use GNU stabs, not native */ +#include "aout/stab_gnu.h" /* We always use GNU stabs, not native. */ #include "libaout.h" #include "aout/aout64.h" #include "gdb-stabs.h" @@ -61,7 +61,7 @@ extern void _initialize_stabsread (void); C++ class pass lists of data member fields and lists of member function fields in an instance of a field_info structure, as defined below. This is part of some reorganization of low level C++ support and is - expected to eventually go away... (FIXME) */ + expected to eventually go away... (FIXME) */ struct field_info { @@ -190,7 +190,7 @@ static struct symbol *current_symbol = NULL; /* Make a list of nameless types that are undefined. This happens when another type is referenced by its number - before this type is actually defined. For instance "t(0,1)=k(0,2)" + before this type is actually defined. For instance "t(0,1)=k(0,2)" and type (0,2) is defined only later. */ struct nat @@ -233,7 +233,8 @@ dbx_lookup_type (int typenums[2], struct objfile *objfile) if (filenum < 0 || filenum >= n_this_object_header_files) { complaint (&symfile_complaints, - _("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d."), + _("Invalid symbol data: type number " + "(%d,%d) out of range at symtab pos %d."), filenum, index, symnum); goto error_return; } @@ -313,7 +314,7 @@ dbx_lookup_type (int typenums[2], struct objfile *objfile) and return the type object. This can create an empty (zeroed) type object. TYPENUMS may be (-1, -1) to return a new type object that is not - put into the type vector, and so may not be referred to by number. */ + put into the type vector, and so may not be referred to by number. */ static struct type * dbx_alloc_type (int typenums[2], struct objfile *objfile) @@ -339,7 +340,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) } /* for all the stabs in a given stab vector, build appropriate types - and fix their symbols in given symbol vector. */ + and fix their symbols in given symbol vector. */ static void patch_block_stabs (struct pending *symbols, struct pending_stabs *stabs, @@ -353,7 +354,7 @@ patch_block_stabs (struct pending *symbols, struct pending_stabs *stabs, if (stabs) { /* for all the stab entries, find their corresponding symbols and - patch their types! */ + patch their types! */ for (ii = 0; ii < stabs->count; ++ii) { @@ -462,7 +463,7 @@ read_type_number (char **pp, int *typenums) #define VISIBILITY_IGNORE '9' /* Optimized out or zero length */ /* Structure for storing pointers to reference definitions for fast lookup - during "process_later". */ + during "process_later". */ struct ref_map { @@ -477,15 +478,15 @@ struct ref_map static struct ref_map *ref_map; -/* Ptr to free cell in chunk's linked list. */ +/* Ptr to free cell in chunk's linked list. */ static int ref_count = 0; -/* Number of chunks malloced. */ +/* Number of chunks malloced. */ static int ref_chunk = 0; /* This file maintains a cache of stabs aliases found in the symbol - table. If the symbol table changes, this cache must be cleared - or we are left holding onto data in invalid obstacks. */ + table. If the symbol table changes, this cache must be cleared + or we are left holding onto data in invalid obstacks. */ void stabsread_clear_cache (void) { @@ -495,8 +496,8 @@ stabsread_clear_cache (void) /* Create array of pointers mapping refids to symbols and stab strings. Add pointers to reference definition symbols and/or their values as we - find them, using their reference numbers as our index. - These will be used later when we resolve references. */ + find them, using their reference numbers as our index. + These will be used later when we resolve references. */ void ref_add (int refnum, struct symbol *sym, char *stabs, CORE_ADDR value) { @@ -544,7 +545,7 @@ process_reference (char **string) /* Advance beyond the initial '#'. */ p = *string + 1; - /* Read number as reference id. */ + /* Read number as reference id. */ while (*p && isdigit (*p)) { refnum = refnum * 10 + *p - '0'; @@ -565,16 +566,16 @@ symbol_reference_defined (char **string) refnum = process_reference (&p); - /* Defining symbols end in '=' */ + /* Defining symbols end in '='. */ if (*p == '=') { - /* Symbol is being defined here. */ + /* Symbol is being defined here. */ *string = p + 1; return refnum; } else { - /* Must be a reference. Either the symbol has already been defined, + /* Must be a reference. Either the symbol has already been defined, or this is a forward reference to it. */ *string = p; return -1; @@ -594,7 +595,7 @@ stab_reg_to_regnum (struct symbol *sym, struct gdbarch *gdbarch) + gdbarch_num_pseudo_regs (gdbarch), SYMBOL_PRINT_NAME (sym)); - regno = gdbarch_sp_regnum (gdbarch); /* Known safe, though useless */ + regno = gdbarch_sp_regnum (gdbarch); /* Known safe, though useless. */ } return regno; @@ -618,8 +619,8 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, /* We would like to eliminate nameless symbols, but keep their types. E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer - to type 2, but, should not create a symbol to address that type. Since - the symbol will be nameless, there is no way any user can refer to it. */ + to type 2, but, should not create a symbol to address that type. Since + the symbol will be nameless, there is no way any user can refer to it. */ int nameless; @@ -627,7 +628,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, if (string[0] == 0) return 0; - /* Ignore old-style symbols from cc -go */ + /* Ignore old-style symbols from cc -go. */ if (p == 0) return 0; @@ -635,6 +636,12 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, { p += 2; p = strchr (p, ':'); + if (p == NULL) + { + complaint (&symfile_complaints, + _("Bad stabs string '%s'"), string); + return NULL; + } } /* If a nameless stab entry, all we need is the type, not the symbol. @@ -693,18 +700,18 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, /* SunPRO (3.0 at least) static variable encoding. */ if (gdbarch_static_transform_name_p (gdbarch)) goto normal; - /* ... fall through ... */ + /* ... fall through ... */ default: complaint (&symfile_complaints, _("Unknown C++ symbol name `%s'"), string); - goto normal; /* Do *something* with it */ + goto normal; /* Do *something* with it. */ } } else { normal: - SYMBOL_LANGUAGE (sym) = current_subfile->language; + SYMBOL_SET_LANGUAGE (sym, current_subfile->language); if (SYMBOL_LANGUAGE (sym) == language_cplus) { char *name = alloca (p - string + 1); @@ -712,7 +719,6 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, memcpy (name, string, p - string); name[p - string] = '\0'; new_name = cp_canonicalize_string (name); - cp_scan_for_anonymous_namespaces (sym); } if (new_name != NULL) { @@ -721,6 +727,10 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, } else SYMBOL_SET_NAMES (sym, string, p - string, 1, objfile); + + if (SYMBOL_LANGUAGE (sym) == language_cplus) + cp_scan_for_anonymous_namespaces (sym); + } p++; @@ -849,9 +859,10 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, /* NULL terminate the string. */ string_local[ind] = 0; - range_type = create_range_type (NULL, - objfile_type (objfile)->builtin_int, - 0, ind); + range_type + = create_range_type (NULL, + objfile_type (objfile)->builtin_int, + 0, ind); SYMBOL_TYPE (sym) = create_array_type (NULL, objfile_type (objfile)->builtin_char, range_type); @@ -931,7 +942,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, primarily for promotion when calling the function from GDB. */ TYPE_PROTOTYPED (SYMBOL_TYPE (sym)) = 1; - /* fall into process_prototype_types */ + /* fall into process_prototype_types. */ process_prototype_types: /* Sun acc puts declared types of arguments here. */ @@ -950,7 +961,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, nsemi++; } - /* Allocate parameter information fields and fill them in. */ + /* Allocate parameter information fields and fill them in. */ TYPE_FIELDS (ftype) = (struct field *) TYPE_ALLOC (ftype, nsemi * sizeof (struct field)); while (*p++ == ';') @@ -965,7 +976,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, /* The Sun compilers mark integer arguments, which should be promoted to the width of the calling conventions, with - a type which references itself. This type is turned into + a type which references itself. This type is turned into a TYPE_CODE_VOID type by read_type, and we have to turn it back into builtin_int here. FIXME: Do we need a new builtin_promoted_int_arg ? */ @@ -1148,7 +1159,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, break; case 'S': - /* Static symbol at top level of file */ + /* Static symbol at top level of file. */ SYMBOL_TYPE (sym) = read_type (&p, objfile); SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE_ADDRESS (sym) = valu; @@ -1159,7 +1170,8 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, { struct minimal_symbol *msym; - msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), NULL, objfile); + msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), + NULL, objfile); if (msym != NULL) { char *new_name = gdbarch_static_transform_name @@ -1176,7 +1188,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, case 't': /* In Ada, there is no distinction between typedef and non-typedef; any type declaration implicitly has the equivalent of a typedef, - and thus 't' is in fact equivalent to 'Tt'. + and thus 't' is in fact equivalent to 'Tt'. Therefore, for Ada units, we check the character immediately before the 't', and if we do not find a 'T', then make sure to @@ -1194,7 +1206,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_TYPE (sym) = read_type (&p, objfile); /* For a nameless type, we don't want a create a symbol, thus we - did not use `sym'. Return without further processing. */ + did not use `sym'. Return without further processing. */ if (nameless) return NULL; @@ -1222,7 +1234,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, { /* gcc-2.6 or later (when using -fvtable-thunks) emits a unique named type for a vtable entry. - Some gdb code depends on that specific name. */ + Some gdb code depends on that specific name. */ extern const char vtbl_ptr_name[]; if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR @@ -1247,15 +1259,16 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, Fortunately, this check seems not to be necessary for anything except pointers or functions. */ - /* ezannoni: 2000-10-26. This seems to apply for - versions of gcc older than 2.8. This was the original + /* ezannoni: 2000-10-26. This seems to apply for + versions of gcc older than 2.8. This was the original problem: with the following code gdb would tell that - the type for name1 is caddr_t, and func is char() + the type for name1 is caddr_t, and func is char(). + typedef char *caddr_t; char *name2; struct x { - char *name1; + char *name1; } xx; char *func() { @@ -1263,7 +1276,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, main () {} */ - /* Pascal accepts names for pointer types. */ + /* Pascal accepts names for pointer types. */ if (current_subfile->language == language_pascal) { TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_LINKAGE_NAME (sym); @@ -1286,9 +1299,10 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_VALUE (struct_sym) = valu; SYMBOL_DOMAIN (struct_sym) = STRUCT_DOMAIN; if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = obconcat (&objfile->objfile_obstack, - SYMBOL_LINKAGE_NAME (sym), - (char *) NULL); + TYPE_NAME (SYMBOL_TYPE (sym)) + = obconcat (&objfile->objfile_obstack, + SYMBOL_LINKAGE_NAME (sym), + (char *) NULL); add_symbol_to_list (struct_sym, &file_symbols); } @@ -1305,7 +1319,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_TYPE (sym) = read_type (&p, objfile); /* For a nameless type, we don't want a create a symbol, thus we - did not use `sym'. Return without further processing. */ + did not use `sym'. Return without further processing. */ if (nameless) return NULL; @@ -1313,14 +1327,15 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_VALUE (sym) = valu; SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_TAG_NAME (SYMBOL_TYPE (sym)) = obconcat (&objfile->objfile_obstack, - SYMBOL_LINKAGE_NAME (sym), - (char *) NULL); + TYPE_TAG_NAME (SYMBOL_TYPE (sym)) + = obconcat (&objfile->objfile_obstack, + SYMBOL_LINKAGE_NAME (sym), + (char *) NULL); add_symbol_to_list (sym, &file_symbols); if (synonym) { - /* Clone the sym and then modify it. */ + /* Clone the sym and then modify it. */ struct symbol *typedef_sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol)); @@ -1329,15 +1344,16 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_VALUE (typedef_sym) = valu; SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN; if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = obconcat (&objfile->objfile_obstack, - SYMBOL_LINKAGE_NAME (sym), - (char *) NULL); + TYPE_NAME (SYMBOL_TYPE (sym)) + = obconcat (&objfile->objfile_obstack, + SYMBOL_LINKAGE_NAME (sym), + (char *) NULL); add_symbol_to_list (typedef_sym, &file_symbols); } break; case 'V': - /* Static symbol of local scope */ + /* Static symbol of local scope. */ SYMBOL_TYPE (sym) = read_type (&p, objfile); SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE_ADDRESS (sym) = valu; @@ -1457,7 +1473,8 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, static struct type * error_type (char **pp, struct objfile *objfile) { - complaint (&symfile_complaints, _("couldn't parse type; debugger out of date?")); + complaint (&symfile_complaints, + _("couldn't parse type; debugger out of date?")); while (1) { /* Skip to end of symbol. */ @@ -1498,10 +1515,10 @@ read_type (char **pp, struct objfile *objfile) there is no size attribute. */ int type_size = -1; - /* Used to distinguish string and bitstring from char-array and set. */ + /* Used to distinguish string and bitstring from char-array and set. */ int is_string = 0; - /* Used to distinguish vector from array. */ + /* Used to distinguish vector from array. */ int is_vector = 0; /* Read type number if present. The type number may be omitted. @@ -1578,7 +1595,8 @@ again: /* Complain and keep going, so compilers can invent new cross-reference types. */ complaint (&symfile_complaints, - _("Unrecognized cross-reference type `%c'"), (*pp)[0]); + _("Unrecognized cross-reference type `%c'"), + (*pp)[0]); code = TYPE_CODE_STRUCT; break; } @@ -1622,8 +1640,8 @@ again: } if (type_name == NULL) { - to = type_name = - (char *) obstack_alloc (&objfile->objfile_obstack, p - *pp + 1); + to = type_name = (char *) + obstack_alloc (&objfile->objfile_obstack, p - *pp + 1); /* Copy the name. */ from = *pp + 1; @@ -1689,10 +1707,10 @@ again: (*pp)--; /* We deal with something like t(1,2)=(3,4)=... which - the Lucid compiler and recent gcc versions (post 2.7.3) use. */ + the Lucid compiler and recent gcc versions (post 2.7.3) use. */ /* Allocate and enter the typedef type first. - This handles recursive types. */ + This handles recursive types. */ type = dbx_alloc_type (typenums, objfile); TYPE_CODE (type) = TYPE_CODE_TYPEDEF; { @@ -1805,7 +1823,8 @@ again: else { complaint (&symfile_complaints, - _("Prototyped function type didn't end arguments with `#':\n%s"), + _("Prototyped function type didn't " + "end arguments with `#':\n%s"), type_start); } @@ -1888,12 +1907,12 @@ again: break; case 'S': /* String attribute */ - /* FIXME: check to see if following type is array? */ + /* FIXME: check to see if following type is array? */ is_string = 1; break; case 'V': /* Vector attribute */ - /* FIXME: check to see if following type is array? */ + /* FIXME: check to see if following type is array? */ is_vector = 1; break; @@ -1917,7 +1936,8 @@ again: return_type = read_type (pp, objfile); if (*(*pp)++ != ';') complaint (&symfile_complaints, - _("invalid (minimal) member type data format at symtab pos %d."), + _("invalid (minimal) member type " + "data format at symtab pos %d."), symnum); type = allocate_stub_method (return_type); if (typenums[0] != -1) @@ -2015,8 +2035,8 @@ again: break; default: - --*pp; /* Go back to the symbol in error */ - /* Particularly important if it was \0! */ + --*pp; /* Go back to the symbol in error. */ + /* Particularly important if it was \0! */ return error_type (pp, objfile); } @@ -2034,14 +2054,15 @@ again: } /* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1. - Return the proper type node for a given builtin type number. */ + Return the proper type node for a given builtin type number. */ static const struct objfile_data *rs6000_builtin_type_data; static struct type * rs6000_builtin_type (int typenum, struct objfile *objfile) { - struct type **negative_types = objfile_data (objfile, rs6000_builtin_type_data); + struct type **negative_types = objfile_data (objfile, + rs6000_builtin_type_data); /* We recognize types numbered from -NUMBER_RECOGNIZED to -1. */ #define NUMBER_RECOGNIZED 34 @@ -2109,6 +2130,7 @@ rs6000_builtin_type (int typenum, struct objfile *objfile) case 9: rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "unsigned", objfile); + break; case 10: rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "unsigned long", objfile); @@ -2275,13 +2297,13 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, char *p; /* Process each list until we find something that is not a member function - or find the end of the functions. */ + or find the end of the functions. */ while (**pp != ';') { /* We should be positioned at the start of the function name. Scan forward to find the first ':' and if it is not the - first of a "::" delimiter, then this is not a member function. */ + first of a "::" delimiter, then this is not a member function. */ p = *pp; while (*p != ':') { @@ -2346,7 +2368,7 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, /* Check for and handle cretinous dbx symbol name continuation! */ if (look_ahead_type == NULL) { - /* Normal case. */ + /* Normal case. */ STABS_CONTINUE (pp, objfile); new_sublist->fn_field.type = read_type (pp, objfile); @@ -2370,7 +2392,7 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, p++; } - /* If this is just a stub, then we don't have the real name here. */ + /* If this is just a stub, then we don't have the real name here. */ if (TYPE_STUB (new_sublist->fn_field.type)) { @@ -2395,33 +2417,35 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, STABS_CONTINUE (pp, objfile); switch (**pp) { - case 'A': /* Normal functions. */ + case 'A': /* Normal functions. */ new_sublist->fn_field.is_const = 0; new_sublist->fn_field.is_volatile = 0; (*pp)++; break; - case 'B': /* `const' member functions. */ + case 'B': /* `const' member functions. */ new_sublist->fn_field.is_const = 1; new_sublist->fn_field.is_volatile = 0; (*pp)++; break; - case 'C': /* `volatile' member function. */ + case 'C': /* `volatile' member function. */ new_sublist->fn_field.is_const = 0; new_sublist->fn_field.is_volatile = 1; (*pp)++; break; - case 'D': /* `const volatile' member function. */ + case 'D': /* `const volatile' member function. */ new_sublist->fn_field.is_const = 1; new_sublist->fn_field.is_volatile = 1; (*pp)++; break; - case '*': /* File compiled with g++ version 1 -- no info */ + case '*': /* File compiled with g++ version 1 -- + no info. */ case '?': case '.': break; default: complaint (&symfile_complaints, - _("const/volatile indicator missing, got '%c'"), **pp); + _("const/volatile indicator missing, got '%c'"), + **pp); break; } @@ -2456,7 +2480,7 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, look_ahead_type = read_type (pp, objfile); if (**pp == ':') { - /* g++ version 1 overloaded methods. */ + /* g++ version 1 overloaded methods. */ } else { @@ -2504,7 +2528,8 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, default: /* error */ complaint (&symfile_complaints, - _("member function type missing, got '%c'"), (*pp)[-1]); + _("member function type missing, got '%c'"), + (*pp)[-1]); /* Fall through into normal member function. */ case '.': @@ -2588,8 +2613,8 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type, method name physname physname method name __opi [none] __opi__3Foo operator int opname - [now or later] - Foo _._3Foo _._3Foo ~Foo separate and + [now or later] + Foo _._3Foo _._3Foo ~Foo separate and rename operator i _ZN3FoocviEv _ZN3FoocviEv operator int demangle __comp_ctor _ZN3FooC1ERKS_ _ZN3FooC1ERKS_ Foo demangle @@ -2751,7 +2776,7 @@ read_cpp_abbrev (struct field_info *fip, char **pp, struct type *type, /* At this point, *pp points to something like "22:23=*22...", where the type number before the ':' is the "context" and everything after is a regular type definition. Lookup the - type, find it's name, and construct the field name. */ + type, find it's name, and construct the field name. */ context = read_type (pp, objfile); @@ -2772,7 +2797,8 @@ read_cpp_abbrev (struct field_info *fip, char **pp, struct type *type, if (name == NULL) { complaint (&symfile_complaints, - _("C++ abbreviated type name unknown at symtab pos %d"), + _("C++ abbreviated type name " + "unknown at symtab pos %d"), symnum); name = "FOO"; } @@ -2789,7 +2815,7 @@ read_cpp_abbrev (struct field_info *fip, char **pp, struct type *type, } /* At this point, *pp points to the ':'. Skip it and read the - field type. */ + field type. */ p = ++(*pp); if (p[-1] != ':') @@ -2836,7 +2862,7 @@ read_one_struct_field (struct field_info *fip, char **pp, char *p, obsavestring (*pp, p - *pp, &objfile->objfile_obstack); *pp = p + 1; - /* This means we have a visibility for a field coming. */ + /* This means we have a visibility for a field coming. */ if (**pp == '/') { (*pp)++; @@ -2853,7 +2879,7 @@ read_one_struct_field (struct field_info *fip, char **pp, char *p, { p = ++(*pp); #if 0 - /* Possible future hook for nested types. */ + /* Possible future hook for nested types. */ if (**pp == '!') { fip->list->field.bitpos = (long) -2; /* nested type */ @@ -2981,9 +3007,9 @@ read_struct_fields (struct field_info *fip, char **pp, struct type *type, /* Read each data member type until we find the terminating ';' at the end of the data member list, or break for some other reason such as finding the - start of the member function list. */ + start of the member function list. */ /* Stab string for structure/union does not end with two ';' in - SUN C compiler 5.3 i.e. F6U2, hence check for end of string. */ + SUN C compiler 5.3 i.e. F6U2, hence check for end of string. */ while (**pp != ';' && **pp != '\0') { @@ -3013,7 +3039,7 @@ read_struct_fields (struct field_info *fip, char **pp, struct type *type, /* Look for the ':' that separates the field name from the field values. Data members are delimited by a single ':', while member functions are delimited by a pair of ':'s. When we hit the member - functions (if any), terminate scan loop and return. */ + functions (if any), terminate scan loop and return. */ while (*p != ':' && *p != '\0') { @@ -3033,7 +3059,7 @@ read_struct_fields (struct field_info *fip, char **pp, struct type *type, { /* (the deleted) chill the list of fields: the last entry (at the head) is a partially constructed entry which we now - scrub. */ + scrub. */ fip->list = fip->list->next; } return 1; @@ -3079,7 +3105,7 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type, } else { - /* Skip the '!' baseclass information marker. */ + /* Skip the '!' baseclass information marker. */ (*pp)++; } @@ -3116,13 +3142,14 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type, memset (new, 0, sizeof (struct nextfield)); new->next = fip->list; fip->list = new; - FIELD_BITSIZE (new->field) = 0; /* this should be an unpacked field! */ + FIELD_BITSIZE (new->field) = 0; /* This should be an unpacked + field! */ STABS_CONTINUE (pp, objfile); switch (**pp) { case '0': - /* Nothing to do. */ + /* Nothing to do. */ break; case '1': SET_TYPE_FIELD_VIRTUAL (type, i); @@ -3131,7 +3158,8 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type, /* Unknown character. Complain and treat it as non-virtual. */ { complaint (&symfile_complaints, - _("Unknown virtual character `%c' for baseclass"), **pp); + _("Unknown virtual character `%c' for baseclass"), + **pp); } } ++(*pp); @@ -3168,12 +3196,12 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type, /* The last piece of baseclass information is the type of the base class. Read it, and remember it's type name as this - field's name. */ + field's name. */ new->field.type = read_type (pp, objfile); new->field.name = type_name_no_tag (new->field.type); - /* skip trailing ';' and bump count of number of fields seen */ + /* Skip trailing ';' and bump count of number of fields seen. */ if (**pp == ';') (*pp)++; else @@ -3198,7 +3226,7 @@ read_tilde_fields (struct field_info *fip, char **pp, struct type *type, STABS_CONTINUE (pp, objfile); - /* If we are positioned at a ';', then skip it. */ + /* If we are positioned at a ';', then skip it. */ if (**pp == ';') { (*pp)++; @@ -3211,7 +3239,7 @@ read_tilde_fields (struct field_info *fip, char **pp, struct type *type, if (**pp == '=' || **pp == '+' || **pp == '-') { /* Obsolete flags that used to indicate the presence - of constructors and/or destructors. */ + of constructors and/or destructors. */ (*pp)++; } @@ -3240,7 +3268,7 @@ read_tilde_fields (struct field_info *fip, char **pp, struct type *type, } TYPE_VPTR_BASETYPE (type) = t; - if (type == t) /* Our own class provides vtbl ptr */ + if (type == t) /* Our own class provides vtbl ptr. */ { for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); @@ -3257,7 +3285,8 @@ read_tilde_fields (struct field_info *fip, char **pp, struct type *type, } /* Virtual function table field not found. */ complaint (&symfile_complaints, - _("virtual function table pointer not found when defining class `%s'"), + _("virtual function table pointer " + "not found when defining class `%s'"), TYPE_NAME (type)); return 0; } @@ -3282,7 +3311,7 @@ attach_fn_fields_to_type (struct field_info *fip, struct type *type) fip->fnlist != NULL; fip->fnlist = fip->fnlist->next) { - --n; /* Circumvent Sun3 compiler bug */ + --n; /* Circumvent Sun3 compiler bug. */ TYPE_FN_FIELDLISTS (type)[n] = fip->fnlist->fn_fieldlist; } return 1; @@ -3303,7 +3332,7 @@ attach_fields_to_type (struct field_info *fip, struct type *type, /* Count up the number of fields that we have, as well as taking note of whether or not there are any non-public fields, which requires us to allocate and build the private_field_bits and protected_field_bits - bitfields. */ + bitfields. */ for (scan = fip->list; scan != NULL; scan = scan->next) { @@ -3316,7 +3345,7 @@ attach_fields_to_type (struct field_info *fip, struct type *type, /* Now we know how many fields there are, and whether or not there are any non-public fields. Record the field count, allocate space for the - array of fields, and create blank visibility bitfields if necessary. */ + array of fields, and create blank visibility bitfields if necessary. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) @@ -3340,9 +3369,10 @@ attach_fields_to_type (struct field_info *fip, struct type *type, B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); } - /* Copy the saved-up fields into the field vector. Start from the head - of the list, adding to the tail of the field array, so that they end - up in the same order in the array in which they were added to the list. */ + /* Copy the saved-up fields into the field vector. Start from the + head of the list, adding to the tail of the field array, so that + they end up in the same order in the array in which they were + added to the list. */ while (nfields-- > 0) { @@ -3367,7 +3397,8 @@ attach_fields_to_type (struct field_info *fip, struct type *type, default: /* Unknown visibility. Complain and treat it as public. */ { - complaint (&symfile_complaints, _("Unknown visibility `%c' for field"), + complaint (&symfile_complaints, + _("Unknown visibility `%c' for field"), fip->list->visibility); } break; @@ -3453,7 +3484,7 @@ set_length_in_type_chain (struct type *type) describing the type. PP points to a character pointer that points to the next unconsumed token - in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;", + in the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;", *PP will point to "4a:1,0,32;;". TYPE points to an incomplete type that needs to be filled in. @@ -3513,7 +3544,7 @@ read_struct_type (char **pp, struct type *type, enum type_code type_code, /* Now read the baseclasses, if any, read the regular C struct or C++ class member fields, attach the fields to the type, read the C++ member functions, attach them to the type, and then read any tilde - field (baseclass specifier for the class holding the main vtable). */ + field (baseclass specifier for the class holding the main vtable). */ if (!read_baseclasses (&fi, pp, type, objfile) || !read_struct_fields (&fi, pp, type, objfile) @@ -3656,7 +3687,7 @@ read_enum_type (char **pp, struct type *type, obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol)); memset (sym, 0, sizeof (struct symbol)); SYMBOL_SET_LINKAGE_NAME (sym, name); - SYMBOL_LANGUAGE (sym) = current_subfile->language; + SYMBOL_SET_LANGUAGE (sym, current_subfile->language); SYMBOL_CLASS (sym) = LOC_CONST; SYMBOL_DOMAIN (sym) = VAR_DOMAIN; SYMBOL_VALUE (sym) = n; @@ -3767,12 +3798,12 @@ read_sun_builtin_type (char **pp, int typenums[2], struct objfile *objfile) if (nbits != 0) return error_type (pp, objfile); - /* The second number is always 0, so ignore it too. */ + /* The second number is always 0, so ignore it too. */ read_huge_number (pp, ';', &nbits, 0); if (nbits != 0) return error_type (pp, objfile); - /* The third number is the number of bits for this type. */ + /* The third number is the number of bits for this type. */ type_bits = read_huge_number (pp, 0, &nbits, 0); if (nbits != 0) return error_type (pp, objfile); @@ -3810,7 +3841,7 @@ read_sun_floating_type (char **pp, int typenums[2], struct objfile *objfile) if (nbits != 0) return error_type (pp, objfile); - /* The second number is the number of bytes occupied by this type */ + /* The second number is the number of bytes occupied by this type. */ nbytes = read_huge_number (pp, ';', &nbits, 0); if (nbits != 0) return error_type (pp, objfile); @@ -3889,7 +3920,8 @@ read_huge_number (char **pp, int end, int *bits, int twos_complement_bits) len = p1 - p; if (len > twos_complement_bits / 3 - || (twos_complement_bits % 3 == 0 && len == twos_complement_bits / 3)) + || (twos_complement_bits % 3 == 0 + && len == twos_complement_bits / 3)) { /* Ok, we have enough characters for a signed value, check for signness by testing if the sign bit is set. */ @@ -3930,14 +3962,14 @@ read_huge_number (char **pp, int end, int *bits, int twos_complement_bits) { /* unsigned representation */ n *= radix; - n += c - '0'; /* FIXME this overflows anyway */ + n += c - '0'; /* FIXME this overflows anyway. */ } } else overflow = 1; /* This depends on large values being output in octal, which is - what GCC does. */ + what GCC does. */ if (radix == 8) { if (nbits == 0) @@ -4057,7 +4089,7 @@ read_range_type (char **pp, int typenums[2], int type_size, int nbits = 0; /* If a type size attribute has been specified, the bounds of - the range should fit in this size. If the lower bounds needs + the range should fit in this size. If the lower bounds needs more bits than the upper bound, then the type is signed. */ if (n2bits <= type_size && n3bits <= type_size) { @@ -4109,7 +4141,7 @@ read_range_type (char **pp, int typenums[2], int type_size, Also note that for complexes, g77 sets n2 to the size of one of the member floats, not the whole complex beast. My guess is that - this was to work well with pre-COMPLEX versions of gdb. */ + this was to work well with pre-COMPLEX versions of gdb. */ if (n3 == 0 && n2 > 0) { @@ -4229,7 +4261,7 @@ read_args (char **pp, int end, struct objfile *objfile, int *nargsp, int *varargsp) { /* FIXME! Remove this arbitrary limit! */ - struct type *types[1024]; /* allow for fns of 1023 parameters */ + struct type *types[1024]; /* Allow for fns of 1023 parameters. */ int n = 0, i; struct field *rval; @@ -4242,7 +4274,7 @@ read_args (char **pp, int end, struct objfile *objfile, int *nargsp, STABS_CONTINUE (pp, objfile); types[n++] = read_type (pp, objfile); } - (*pp)++; /* get past `end' (the ':' character) */ + (*pp)++; /* get past `end' (the ':' character). */ if (n == 0) { @@ -4328,7 +4360,7 @@ common_block_end (struct objfile *objfile) sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol)); memset (sym, 0, sizeof (struct symbol)); - /* Note: common_block_name already saved on objfile_obstack */ + /* Note: common_block_name already saved on objfile_obstack. */ SYMBOL_SET_LINKAGE_NAME (sym, common_block_name); SYMBOL_CLASS (sym) = LOC_BLOCK; @@ -4520,7 +4552,7 @@ cleanup_undefined_types_1 (void) { struct pending *ppt; int i; - /* Name of the type, without "struct" or "union" */ + /* Name of the type, without "struct" or "union". */ char *typename = TYPE_TAG_NAME (*type); if (typename == NULL) @@ -4625,7 +4657,7 @@ scan_file_globals (struct objfile *objfile) prev = NULL; /* Get the hash index and check all the symbols - under that hash index. */ + under that hash index. */ hash = hashname (SYMBOL_LINKAGE_NAME (msymbol)); @@ -4635,7 +4667,7 @@ scan_file_globals (struct objfile *objfile) SYMBOL_LINKAGE_NAME (sym)) == 0) { /* Splice this symbol out of the hash chain and - assign the value we have to it. */ + assign the value we have to it. */ if (prev) { SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym); @@ -4703,7 +4735,8 @@ scan_file_globals (struct objfile *objfile) SYMBOL_CLASS (prev) = LOC_UNRESOLVED; else complaint (&symfile_complaints, - _("%s: common block `%s' from global_sym_chain unresolved"), + _("%s: common block `%s' from " + "global_sym_chain unresolved"), objfile->name, SYMBOL_PRINT_NAME (prev)); } } @@ -4731,7 +4764,7 @@ stabsread_new_init (void) } /* Initialize anything that needs initializing at the same time as - start_symtab() is called. */ + start_symtab() is called. */ void start_stabs (void) @@ -4746,7 +4779,7 @@ start_stabs (void) common_block_name = NULL; } -/* Call after end_symtab() */ +/* Call after end_symtab(). */ void end_stabs (void) @@ -4798,7 +4831,7 @@ find_name_end (char *name) } } -/* Initializer for this module */ +/* Initializer for this module. */ void _initialize_stabsread (void) diff --git a/contrib/gdb-7/gdb/stabsread.h b/contrib/gdb-7/gdb/stabsread.h index d2006a8dc0..92523a9a9a 100644 --- a/contrib/gdb-7/gdb/stabsread.h +++ b/contrib/gdb-7/gdb/stabsread.h @@ -1,6 +1,6 @@ /* Include file for stabs debugging format support functions. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010 + 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -57,11 +57,11 @@ struct pending_stabs EXTERN struct pending_stabs *global_stabs; /* The type code that process_one_symbol saw on its previous invocation. - Used to detect pairs of N_SO symbols. */ + Used to detect pairs of N_SO symbols. */ EXTERN int previous_stab_code; -/* Support for Sun changes to dbx symbol format */ +/* Support for Sun changes to dbx symbol format. */ /* For each identified header file, we have a table of types defined in that header file. @@ -88,8 +88,9 @@ struct header_file char *name; - /* Numeric code distinguishing instances of one header file that produced - different results when included. It comes from the N_BINCL or N_EXCL. */ + /* Numeric code distinguishing instances of one header file that + produced different results when included. It comes from the + N_BINCL or N_EXCL. */ int instance; @@ -103,13 +104,13 @@ struct header_file }; -/* The table of header_files of this OBJFILE. */ +/* The table of header_files of this OBJFILE. */ #define HEADER_FILES(OBJFILE) (DBX_SYMFILE_INFO (OBJFILE)->header_files) -/* The actual length of HEADER_FILES. */ +/* The actual length of HEADER_FILES. */ #define N_HEADER_FILES(OBJFILE) (DBX_SYMFILE_INFO (OBJFILE)->n_header_files) -/* The allocated lengh of HEADER_FILES. */ +/* The allocated lengh of HEADER_FILES. */ #define N_ALLOCATED_HEADER_FILES(OBJFILE) \ (DBX_SYMFILE_INFO (OBJFILE)->n_allocated_header_files) diff --git a/contrib/gdb-7/gdb/stack.c b/contrib/gdb-7/gdb/stack.c index 830fd41c7c..0888b69d3f 100644 --- a/contrib/gdb-7/gdb/stack.c +++ b/contrib/gdb-7/gdb/stack.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -64,7 +64,7 @@ static const char *print_frame_arguments_choices[] = {"all", "scalars", "none", NULL}; static const char *print_frame_arguments = "scalars"; -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static void print_frame_local_vars (struct frame_info *, int, struct ui_file *); @@ -466,8 +466,9 @@ show_disassemble_next_line (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Debugger's willingness to use disassemble-next-line is %s.\n"), + fprintf_filtered (file, + _("Debugger's willingness to use " + "disassemble-next-line is %s.\n"), value); } @@ -628,12 +629,12 @@ print_frame_info (struct frame_info *frame, int print_level, get_user_print_options (&opts); /* We used to do this earlier, but that is clearly - wrong. This function is used by many different + wrong. This function is used by many different parts of gdb, including normal_stop in infrun.c, which uses this to print out the current PC when we stepi/nexti into the middle of a source - line. Only the command line really wants this - behavior. Other UIs probably would like the + line. Only the command line really wants this + behavior. Other UIs probably would like the ability to decide for themselves if it is desired. */ if (opts.addressprint && mid_statement) { @@ -653,24 +654,33 @@ print_frame_info (struct frame_info *frame, int print_level, } if (print_what != LOCATION) - set_default_breakpoint (1, sal.pspace, - get_frame_pc (frame), sal.symtab, sal.line); + { + CORE_ADDR pc; + + if (get_frame_pc_if_available (frame, &pc)) + set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + else + set_default_breakpoint (0, 0, 0, 0, 0); + } annotate_frame_end (); gdb_flush (gdb_stdout); } -/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding - to FRAME. */ +/* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function + corresponding to FRAME. */ + void find_frame_funname (struct frame_info *frame, char **funname, - enum language *funlang) + enum language *funlang, struct symbol **funcp) { struct symbol *func; *funname = NULL; *funlang = language_unknown; + if (funcp) + *funcp = NULL; func = get_frame_function (frame); if (func) @@ -715,6 +725,8 @@ find_frame_funname (struct frame_info *frame, char **funname, { *funname = SYMBOL_PRINT_NAME (func); *funlang = SYMBOL_LANGUAGE (func); + if (funcp) + *funcp = func; if (*funlang == language_cplus) { /* It seems appropriate to use SYMBOL_PRINT_NAME() here, @@ -734,9 +746,13 @@ find_frame_funname (struct frame_info *frame, char **funname, } else { - struct minimal_symbol *msymbol = - lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame)); + struct minimal_symbol *msymbol; + CORE_ADDR pc; + + if (!get_frame_address_in_block_if_available (frame, &pc)) + return; + msymbol = lookup_minimal_symbol_by_pc (pc); if (msymbol != NULL) { *funname = SYMBOL_PRINT_NAME (msymbol); @@ -756,14 +772,19 @@ print_frame (struct frame_info *frame, int print_level, struct ui_stream *stb; struct cleanup *old_chain, *list_chain; struct value_print_options opts; + struct symbol *func; + CORE_ADDR pc = 0; + int pc_p; + + pc_p = get_frame_pc_if_available (frame, &pc); stb = ui_out_stream_new (uiout); old_chain = make_cleanup_ui_out_stream_delete (stb); - find_frame_funname (frame, &funname, &funlang); + find_frame_funname (frame, &funname, &funlang, &func); annotate_frame_begin (print_level ? frame_relative_level (frame) : 0, - gdbarch, get_frame_pc (frame)); + gdbarch, pc); list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); @@ -775,11 +796,15 @@ print_frame (struct frame_info *frame, int print_level, } get_user_print_options (&opts); if (opts.addressprint) - if (frame_show_address (frame, sal) || !sal.symtab + if (!sal.symtab + || frame_show_address (frame, sal) || print_what == LOC_AND_ADDRESS) { annotate_frame_address (); - ui_out_field_core_addr (uiout, "addr", gdbarch, get_frame_pc (frame)); + if (pc_p) + ui_out_field_core_addr (uiout, "addr", gdbarch, pc); + else + ui_out_field_string (uiout, "addr", ""); annotate_frame_address_end (); ui_out_text (uiout, " in "); } @@ -797,11 +822,11 @@ print_frame (struct frame_info *frame, int print_level, struct cleanup *args_list_chain; args.frame = frame; - args.func = find_pc_function (get_frame_address_in_block (frame)); + args.func = func; args.stream = gdb_stdout; args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args"); catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR); - /* FIXME: ARGS must be a list. If one argument is a string it + /* FIXME: ARGS must be a list. If one argument is a string it will have " that will not be properly escaped. */ /* Invoke ui_out_tuple_end. */ do_cleanups (args_list_chain); @@ -829,7 +854,7 @@ print_frame (struct frame_info *frame, int print_level, annotate_frame_source_end (); } - if (!funname || (!sal.symtab || !sal.symtab->filename)) + if (pc_p && (!funname || (!sal.symtab || !sal.symtab->filename))) { #ifdef PC_SOLIB char *lib = PC_SOLIB (get_frame_pc (frame)); @@ -927,7 +952,7 @@ parse_frame_specification_1 (const char *frame_exp, const char *message, fid = find_relative_frame (get_current_frame (), &level); if (level == 0) - /* find_relative_frame was successful */ + /* find_relative_frame was successful. */ return fid; } @@ -1006,6 +1031,9 @@ frame_info (char *addr_exp, int from_tty) int selected_frame_p; struct gdbarch *gdbarch; struct cleanup *back_to = make_cleanup (null_cleanup, NULL); + CORE_ADDR frame_pc; + int frame_pc_p; + CORE_ADDR caller_pc; fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p); gdbarch = get_frame_arch (fi); @@ -1024,11 +1052,10 @@ frame_info (char *addr_exp, int from_tty) get_frame_pc(). */ pc_regname = "pc"; + frame_pc_p = get_frame_pc_if_available (fi, &frame_pc); find_frame_sal (fi, &sal); func = get_frame_function (fi); - /* FIXME: cagney/2002-11-28: Why bother? Won't sal.symtab contain - the same value? */ - s = find_pc_symtab (get_frame_pc (fi)); + s = sal.symtab; if (func) { funname = SYMBOL_PRINT_NAME (func); @@ -1049,11 +1076,11 @@ frame_info (char *addr_exp, int from_tty) } } } - else + else if (frame_pc_p) { struct minimal_symbol *msymbol; - msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); + msymbol = lookup_minimal_symbol_by_pc (frame_pc); if (msymbol != NULL) { funname = SYMBOL_PRINT_NAME (msymbol); @@ -1074,7 +1101,10 @@ frame_info (char *addr_exp, int from_tty) fputs_filtered (paddress (gdbarch, get_frame_base (fi)), gdb_stdout); printf_filtered (":\n"); printf_filtered (" %s = ", pc_regname); - fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout); + if (frame_pc_p) + fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout); + else + fputs_filtered ("", gdb_stdout); wrap_here (" "); if (funname) @@ -1089,7 +1119,10 @@ frame_info (char *addr_exp, int from_tty) puts_filtered ("; "); wrap_here (" "); printf_filtered ("saved %s ", pc_regname); - fputs_filtered (paddress (gdbarch, frame_unwind_caller_pc (fi)), gdb_stdout); + if (frame_unwind_caller_pc_if_available (fi, &caller_pc)) + fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout); + else + fputs_filtered ("", gdb_stdout); printf_filtered ("\n"); if (calling_frame_info == NULL) @@ -1179,6 +1212,7 @@ frame_info (char *addr_exp, int from_tty) { enum lval_type lval; int optimized; + int unavailable; CORE_ADDR addr; int realnum; int count; @@ -1195,9 +1229,9 @@ frame_info (char *addr_exp, int from_tty) /* Find out the location of the saved stack pointer with out actually evaluating it. */ frame_register_unwind (fi, gdbarch_sp_regnum (gdbarch), - &optimized, &lval, &addr, + &optimized, &unavailable, &lval, &addr, &realnum, NULL); - if (!optimized && lval == not_lval) + if (!optimized && !unavailable && lval == not_lval) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int sp_size = register_size (gdbarch, gdbarch_sp_regnum (gdbarch)); @@ -1205,7 +1239,7 @@ frame_info (char *addr_exp, int from_tty) CORE_ADDR sp; frame_register_unwind (fi, gdbarch_sp_regnum (gdbarch), - &optimized, &lval, &addr, + &optimized, &unavailable, &lval, &addr, &realnum, value); /* NOTE: cagney/2003-05-22: This is assuming that the stack pointer was packed as an unsigned integer. That @@ -1216,14 +1250,14 @@ frame_info (char *addr_exp, int from_tty) printf_filtered ("\n"); need_nl = 0; } - else if (!optimized && lval == lval_memory) + else if (!optimized && !unavailable && lval == lval_memory) { printf_filtered (" Previous frame's sp at "); fputs_filtered (paddress (gdbarch, addr), gdb_stdout); printf_filtered ("\n"); need_nl = 0; } - else if (!optimized && lval == lval_register) + else if (!optimized && !unavailable && lval == lval_register) { printf_filtered (" Previous frame's sp in %s\n", gdbarch_register_name (gdbarch, realnum)); @@ -1241,11 +1275,11 @@ frame_info (char *addr_exp, int from_tty) { /* Find out the location of the saved register without fetching the corresponding value. */ - frame_register_unwind (fi, i, &optimized, &lval, &addr, &realnum, - NULL); + frame_register_unwind (fi, i, &optimized, &unavailable, + &lval, &addr, &realnum, NULL); /* For moment, only display registers that were saved on the stack. */ - if (!optimized && lval == lval_memory) + if (!optimized && !unavailable && lval == lval_memory) { if (count == 0) puts_filtered (" Saved registers:\n "); @@ -1575,7 +1609,7 @@ struct print_variable_and_value_data int values_printed; }; -/* The callback for the locals and args iterators */ +/* The callback for the locals and args iterators. */ static void do_print_variable_and_value (const char *print_name, @@ -1595,6 +1629,14 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs, { struct print_variable_and_value_data cb_data; struct block *block; + CORE_ADDR pc; + + if (!get_frame_pc_if_available (frame, &pc)) + { + fprintf_filtered (stream, + _("PC unavailable, cannot determine locals.\n")); + return; + } block = get_frame_block (frame, 0); if (block == 0) @@ -1747,6 +1789,13 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) { struct print_variable_and_value_data cb_data; struct symbol *func; + CORE_ADDR pc; + + if (!get_frame_pc_if_available (frame, &pc)) + { + fprintf_filtered (stream, _("PC unavailable, cannot determine args.\n")); + return; + } func = get_frame_function (frame); if (func == NULL) @@ -2012,9 +2061,10 @@ return_command (char *retval_exp, int from_tty) && using_struct_return (gdbarch, SYMBOL_TYPE (thisfun), return_type)) { - query_prefix = "\ -The location at which to store the function's return value is unknown.\n\ -If you continue, the return value that you specified will be ignored.\n"; + query_prefix = "The location at which to store the " + "function's return value is unknown.\n" + "If you continue, the return value " + "that you specified will be ignored.\n"; return_value = NULL; } } @@ -2067,7 +2117,7 @@ If you continue, the return value that you specified will be ignored.\n"; } /* Sets the scope to input function name, provided that the function - is within the current stack frame */ + is within the current stack frame. */ struct function_bounds { @@ -2133,6 +2183,10 @@ get_frame_language (void) if (frame) { + volatile struct gdb_exception ex; + CORE_ADDR pc = 0; + struct symtab *s; + /* We determine the current frame language by looking up its associated symtab. To retrieve this symtab, we use the frame PC. However we cannot use the frame PC as is, because it @@ -2141,11 +2195,22 @@ get_frame_language (void) we rely on get_frame_address_in_block(), it provides us with a PC that is guaranteed to be inside the frame's code block. */ - CORE_ADDR pc = get_frame_address_in_block (frame); - struct symtab *s = find_pc_symtab (pc); - if (s) - return s->language; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + pc = get_frame_address_in_block (frame); + } + if (ex.reason < 0) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + } + else + { + s = find_pc_symtab (pc); + if (s != NULL) + return s->language; + } } return language_unknown; @@ -2181,8 +2246,8 @@ Same as the `down' command, but does not print anything.\n\ This is useful in command scripts.")); add_com ("frame", class_stack, frame_command, _("\ -Select and print a stack frame.\n\ -With no argument, print the selected stack frame. (See also \"info frame\").\n\ +Select and print a stack frame.\nWith no argument, \ +print the selected stack frame. (See also \"info frame\").\n\ An argument specifies the frame to select.\n\ It can be a stack frame number or the address of the frame.\n\ With argument, nothing is printed if input is coming from\n\ @@ -2203,8 +2268,8 @@ It can be a stack frame number or the address of the frame.\n")); add_com ("backtrace", class_stack, backtrace_command, _("\ Print backtrace of all stack frames, or innermost COUNT frames.\n\ -With a negative argument, print outermost -COUNT frames.\n\ -Use of the 'full' qualifier also prints the values of the local variables.\n")); +With a negative argument, print outermost -COUNT frames.\nUse of the \ +'full' qualifier also prints the values of the local variables.\n")); add_com_alias ("bt", "backtrace", class_stack, 0); if (xdb_commands) { @@ -2247,8 +2312,10 @@ Usage: func \n")); add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack, &disassemble_next_line, _("\ -Set whether to disassemble next source line or insn when execution stops."), _("\ -Show whether to disassemble next source line or insn when execution stops."), _("\ +Set whether to disassemble next source line or insn when execution stops."), + _("\ +Show whether to disassemble next source line or insn when execution stops."), + _("\ If ON, GDB will display disassembly of the next source line, in addition\n\ to displaying the source line itself. If the next source line cannot\n\ be displayed (e.g., source is unavailable or there's no line info), GDB\n\ diff --git a/contrib/gdb-7/gdb/stack.h b/contrib/gdb-7/gdb/stack.h index 5e874b4fd4..3cce623f1f 100644 --- a/contrib/gdb-7/gdb/stack.h +++ b/contrib/gdb-7/gdb/stack.h @@ -1,6 +1,7 @@ /* Stack manipulation commands, for GDB the GNU Debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -22,12 +23,10 @@ void select_frame_command (char *level_exp, int from_tty); -/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding - to FRAME. */ void find_frame_funname (struct frame_info *frame, char **funname, - enum language *funlang); + enum language *funlang, struct symbol **funcp); -typedef void (*iterate_over_block_arg_local_vars_cb) (const char *symbol_print_name, +typedef void (*iterate_over_block_arg_local_vars_cb) (const char *print_name, struct symbol *sym, void *cb_data); diff --git a/contrib/gdb-7/gdb/std-operator.def b/contrib/gdb-7/gdb/std-operator.def new file mode 100644 index 0000000000..267215c8e8 --- /dev/null +++ b/contrib/gdb-7/gdb/std-operator.def @@ -0,0 +1,327 @@ +/* Standard language operator definitions for GDB, the GNU debugger. + + Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007, 2008, 2009, + 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Used when it's necessary to pass an opcode which will be ignored, + or to catch uninitialized values. */ +OP (OP_NULL) + +/* BINOP_... operate on two values computed by following subexpressions, +replacing them by one result value. They take no immediate arguments. */ + +OP (BINOP_ADD) /* + */ +OP (BINOP_SUB) /* - */ +OP (BINOP_MUL) /* * */ +OP (BINOP_DIV) /* / */ +OP (BINOP_REM) /* % */ +OP (BINOP_MOD) /* mod (Knuth 1.2.4) */ +OP (BINOP_LSH) /* << */ +OP (BINOP_RSH) /* >> */ +OP (BINOP_LOGICAL_AND) /* && */ +OP (BINOP_LOGICAL_OR) /* || */ +OP (BINOP_BITWISE_AND) /* & */ +OP (BINOP_BITWISE_IOR) /* | */ +OP (BINOP_BITWISE_XOR) /* ^ */ +OP (BINOP_EQUAL) /* == */ +OP (BINOP_NOTEQUAL) /* != */ +OP (BINOP_LESS) /* < */ +OP (BINOP_GTR) /* > */ +OP (BINOP_LEQ) /* <= */ +OP (BINOP_GEQ) /* >= */ +OP (BINOP_REPEAT) /* @ */ +OP (BINOP_ASSIGN) /* = */ +OP (BINOP_COMMA) /* , */ +OP (BINOP_SUBSCRIPT) /* x[y] */ +OP (BINOP_EXP) /* Exponentiation */ + +/* C++. */ + +OP (BINOP_MIN) /* ? */ + +/* STRUCTOP_MEMBER is used for pointer-to-member constructs. + X . * Y translates into X STRUCTOP_MEMBER Y. */ +OP (STRUCTOP_MEMBER) + +/* STRUCTOP_MPTR is used for pointer-to-member constructs + when X is a pointer instead of an aggregate. */ +OP (STRUCTOP_MPTR) + +/* TYPE_INSTANCE is used when the user specifies a specific + type instantiation for overloaded methods/functions. + + The format is: + TYPE_INSTANCE num_types type0 ... typeN num_types TYPE_INSTANCE. */ +OP (TYPE_INSTANCE) + +/* end of C++. */ + +/* For Modula-2 integer division DIV. */ +OP (BINOP_INTDIV) + +/* +=, -=, *=, and so on. The following exp_element is another opcode, + a BINOP_, saying how to modify. Then comes another BINOP_ASSIGN_MODIFY, + making three exp_elements in total. */ +OP (BINOP_ASSIGN_MODIFY) + +/* Modula-2 standard (binary) procedures. */ +OP (BINOP_VAL) + +/* Concatenate two operands, such as character strings or bitstrings. + If the first operand is a integer expression, then it means concatenate + the second operand with itself that many times. */ +OP (BINOP_CONCAT) + +/* For (the deleted) Chill and Pascal. */ +OP (BINOP_IN) /* Returns 1 iff ARG1 IN ARG2. */ + +/* This is the "colon operator" used various places in (the + deleted) Chill. */ +OP (BINOP_RANGE) + +/* This must be the highest BINOP_ value, for expprint.c. */ +OP (BINOP_END) + +/* Operates on three values computed by following subexpressions. */ +OP (TERNOP_COND) /* ?: */ + +/* A sub-string/sub-array. (the deleted) Chill syntax: + OP1(OP2:OP3). Return elements OP2 through OP3 of OP1. */ +OP (TERNOP_SLICE) + +/* A sub-string/sub-array. (The deleted) Chill syntax: OP1(OP2 UP + OP3). Return OP3 elements of OP1, starting with element + OP2. */ +OP (TERNOP_SLICE_COUNT) + +/* Multidimensional subscript operator, such as Modula-2 x[a,b,...]. + The dimensionality is encoded in the operator, like the number of + function arguments in OP_FUNCALL, I.E. . + The value of the first following subexpression is subscripted + by each of the next following subexpressions, one per dimension. */ +OP (MULTI_SUBSCRIPT) + +/* The OP_... series take immediate following arguments. + After the arguments come another OP_... (the same one) + so that the grouping can be recognized from the end. */ + +/* OP_LONG is followed by a type pointer in the next exp_element + and the long constant value in the following exp_element. + Then comes another OP_LONG. + Thus, the operation occupies four exp_elements. */ +OP (OP_LONG) + +/* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a + long. */ +OP (OP_DOUBLE) + +/* OP_VAR_VALUE takes one struct block * in the following element, + and one struct symbol * in the following exp_element, followed + by another OP_VAR_VALUE, making four exp_elements. If the + block is non-NULL, evaluate the symbol relative to the + innermost frame executing in that block; if the block is NULL + use the selected frame. */ +OP (OP_VAR_VALUE) + +/* OP_LAST is followed by an integer in the next exp_element. + The integer is zero for the last value printed, + or it is the absolute number of a history element. + With another OP_LAST at the end, this makes three exp_elements. */ +OP (OP_LAST) + +/* OP_REGISTER is followed by a string in the next exp_element. + This is the name of a register to fetch. */ +OP (OP_REGISTER) + +/* OP_INTERNALVAR is followed by an internalvar ptr in the next + exp_element. With another OP_INTERNALVAR at the end, this + makes three exp_elements. */ +OP (OP_INTERNALVAR) + +/* OP_FUNCALL is followed by an integer in the next exp_element. + The integer is the number of args to the function call. + That many plus one values from following subexpressions + are used, the first one being the function. + The integer is followed by a repeat of OP_FUNCALL, + making three exp_elements. */ +OP (OP_FUNCALL) + +/* OP_OBJC_MSGCALL is followed by a string in the next exp_element + and then an integer. The string is the selector string. The + integer is the number of arguments to the message call. That + many plus one values are used, the first one being the object + pointer. This is an Objective C message. */ +OP (OP_OBJC_MSGCALL) + +/* This is EXACTLY like OP_FUNCALL but is semantically different. + In F77, array subscript expressions, substring expressions and + function calls are all exactly the same syntactically. They + may only be disambiguated at runtime. Thus this operator, + which indicates that we have found something of the form + ( ). */ +OP (OP_F77_UNDETERMINED_ARGLIST) + +/* OP_COMPLEX takes a type in the following element, followed by another + OP_COMPLEX, making three exp_elements. It is followed by two double + args, and converts them into a complex number of the given type. */ +OP (OP_COMPLEX) + +/* OP_STRING represents a string constant. + Its format is the same as that of a STRUCTOP, but the string + data is just made into a string constant when the operation + is executed. */ +OP (OP_STRING) + +/* OP_BITSTRING represents a packed bitstring constant. + Its format is the same as that of a STRUCTOP, but the bitstring + data is just made into a bitstring constant when the operation + is executed. */ +OP (OP_BITSTRING) + +/* OP_ARRAY creates an array constant out of the following subexpressions. + It is followed by two exp_elements, the first containing an integer + that is the lower bound of the array and the second containing another + integer that is the upper bound of the array. The second integer is + followed by a repeat of OP_ARRAY, making four exp_elements total. + The bounds are used to compute the number of following subexpressions + to consume, as well as setting the bounds in the created array constant. + The type of the elements is taken from the type of the first subexp, + and they must all match. */ +OP (OP_ARRAY) + +/* UNOP_CAST is followed by a type pointer in the next exp_element. + With another UNOP_CAST at the end, this makes three exp_elements. + It casts the value of the following subexpression. */ +OP (UNOP_CAST) + +/* The C++ dynamic_cast operator. */ +OP (UNOP_DYNAMIC_CAST) + +/* The C++ reinterpret_cast operator. */ +OP (UNOP_REINTERPRET_CAST) + +/* UNOP_MEMVAL is followed by a type pointer in the next exp_element + With another UNOP_MEMVAL at the end, this makes three exp_elements. + It casts the contents of the word addressed by the value of the + following subexpression. */ +OP (UNOP_MEMVAL) + +/* UNOP_MEMVAL_TLS is followed by a `struct objfile' pointer in the next + exp_element and a type pointer in the following exp_element. + With another UNOP_MEMVAL_TLS at the end, this makes four exp_elements. + It casts the contents of the word offsetted by the value of the + following subexpression from the TLS specified by `struct objfile'. */ +OP (UNOP_MEMVAL_TLS) + +/* UNOP_... operate on one value from a following subexpression + and replace it with a result. They take no immediate arguments. */ + +OP (UNOP_NEG) /* Unary - */ +OP (UNOP_LOGICAL_NOT) /* Unary ! */ +OP (UNOP_COMPLEMENT) /* Unary ~ */ +OP (UNOP_IND) /* Unary * */ +OP (UNOP_ADDR) /* Unary & */ +OP (UNOP_PREINCREMENT) /* ++ before an expression */ +OP (UNOP_POSTINCREMENT) /* ++ after an expression */ +OP (UNOP_PREDECREMENT) /* -- before an expression */ +OP (UNOP_POSTDECREMENT) /* -- after an expression */ +OP (UNOP_SIZEOF) /* Unary sizeof (followed by expression) */ + +OP (UNOP_PLUS) /* Unary plus */ + +OP (UNOP_CAP) /* Modula-2 standard (unary) procedures */ +OP (UNOP_CHR) +OP (UNOP_ORD) +OP (UNOP_ABS) +OP (UNOP_FLOAT) +OP (UNOP_HIGH) +OP (UNOP_MAX) +OP (UNOP_MIN) +OP (UNOP_ODD) +OP (UNOP_TRUNC) + +OP (OP_BOOL) /* Modula-2 builtin BOOLEAN type */ +OP (OP_M2_STRING) /* Modula-2 string constants */ + +/* STRUCTOP_... operate on a value from a following subexpression + by extracting a structure component specified by a string + that appears in the following exp_elements (as many as needed). + STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->". + They differ only in the error message given in case the value is + not suitable or the structure component specified is not found. + + The length of the string follows the opcode, followed by + BYTES_TO_EXP_ELEM(length) elements containing the data of the + string, followed by the length again and the opcode again. */ + +OP (STRUCTOP_STRUCT) +OP (STRUCTOP_PTR) + +/* C++: OP_THIS is just a placeholder for the class instance variable. + It just comes in a tight (OP_THIS, OP_THIS) pair. */ +OP (OP_THIS) + +/* Objective-C: OP_OBJC_SELF is just a placeholder for the class + instance variable. It just comes in a tight (OP_OBJC_SELF, + OP_OBJC_SELF) pair. */ +OP (OP_OBJC_SELF) + +/* Objective C: "@selector" pseudo-operator. */ +OP (OP_OBJC_SELECTOR) + +/* OP_SCOPE surrounds a type name and a field name. The type + name is encoded as one element, but the field name stays as + a string, which, of course, is variable length. */ +OP (OP_SCOPE) + +/* Used to represent named structure field values in brace + initializers (or tuples as they are called in (the deleted) + Chill). + + The gcc C syntax is NAME:VALUE or .NAME=VALUE, the (the + deleted) Chill syntax is .NAME:VALUE. Multiple labels (as in + the (the deleted) Chill syntax .NAME1,.NAME2:VALUE) is + represented as if it were .NAME1:(.NAME2:VALUE) (though that is + not valid (the deleted) Chill syntax). + + The NAME is represented as for STRUCTOP_STRUCT; VALUE follows. */ +OP (OP_LABELED) + +/* OP_TYPE is for parsing types, and used with the "ptype" command + so we can look up types that are qualified by scope, either with + the GDB "::" operator, or the Modula-2 '.' operator. */ +OP (OP_TYPE) + +/* An un-looked-up identifier. */ +OP (OP_NAME) + +/* An Objective C Foundation Class NSString constant. */ +OP (OP_OBJC_NSSTRING) + +/* A F90 array range operator (for "exp:exp", "exp:", ":exp" and ":"). */ +OP (OP_F90_RANGE) + +/* OP_DECFLOAT is followed by a type pointer in the next exp_element + and a dec long constant value in the following exp_element. + Then comes another OP_DECFLOAT. */ +OP (OP_DECFLOAT) + +/* OP_ADL_FUNC specifies that the function is to be looked up in an + Argument Dependent manner (Koenig lookup). */ +OP (OP_ADL_FUNC) diff --git a/contrib/gdb-7/gdb/std-regs.c b/contrib/gdb-7/gdb/std-regs.c index 8f0d444e1c..1054b89b8f 100644 --- a/contrib/gdb-7/gdb/std-regs.c +++ b/contrib/gdb-7/gdb/std-regs.c @@ -1,6 +1,6 @@ /* Builtin frame register, for GDB, the GNU debugger. - Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010 + Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Red Hat. @@ -48,11 +48,8 @@ value_of_builtin_frame_fp_reg (struct frame_info *frame, const void *baton) struct value *val = allocate_value (data_ptr_type); gdb_byte *buf = value_contents_raw (val); - if (frame == NULL) - memset (buf, 0, TYPE_LENGTH (value_type (val))); - else - gdbarch_address_to_pointer (gdbarch, data_ptr_type, - buf, get_frame_base_address (frame)); + gdbarch_address_to_pointer (gdbarch, data_ptr_type, + buf, get_frame_base_address (frame)); return val; } } @@ -70,11 +67,8 @@ value_of_builtin_frame_pc_reg (struct frame_info *frame, const void *baton) struct value *val = allocate_value (func_ptr_type); gdb_byte *buf = value_contents_raw (val); - if (frame == NULL) - memset (buf, 0, TYPE_LENGTH (value_type (val))); - else - gdbarch_address_to_pointer (gdbarch, func_ptr_type, - buf, get_frame_pc (frame)); + gdbarch_address_to_pointer (gdbarch, func_ptr_type, + buf, get_frame_pc (frame)); return val; } } diff --git a/contrib/gdb-7/gdb/symfile.c b/contrib/gdb-7/gdb/symfile.c index 42f7ae3e07..1478c83c03 100644 --- a/contrib/gdb-7/gdb/symfile.c +++ b/contrib/gdb-7/gdb/symfile.c @@ -1,7 +1,7 @@ /* Generic symbol file reading for the GNU debugger, GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -67,7 +67,8 @@ #include "psymtab.h" -int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num); +int (*deprecated_ui_load_progress_hook) (const char *section, + unsigned long num); void (*deprecated_show_load_progress) (const char *section, unsigned long section_sent, unsigned long section_size, @@ -78,19 +79,14 @@ void (*deprecated_post_add_symbol_hook) (void); static void clear_symtab_users_cleanup (void *ignore); -/* Global variables owned by this file */ -int readnow_symbol_files; /* Read full symbols immediately */ +/* Global variables owned by this file. */ +int readnow_symbol_files; /* Read full symbols immediately. */ -/* External variables and functions referenced. */ +/* External variables and functions referenced. */ extern void report_transfer_performance (unsigned long, time_t, time_t); -/* Functions this file defines */ - -#if 0 -static int simple_read_overlay_region_table (void); -static void simple_free_overlay_region_table (void); -#endif +/* Functions this file defines. */ static void load_command (char *, int); @@ -102,7 +98,7 @@ bfd *symfile_bfd_open (char *); int get_section_index (struct objfile *, char *); -static struct sym_fns *find_sym_fns (bfd *); +static const struct sym_fns *find_sym_fns (bfd *); static void decrement_reading_symtab (void *); @@ -145,9 +141,12 @@ void _initialize_symfile (void); /* List of all available sym_fns. On gdb startup, each object file reader calls add_symtab_fns() to register information on each format it is - prepared to read. */ + prepared to read. */ -static struct sym_fns *symtab_fns = NULL; +typedef const struct sym_fns *sym_fns_ptr; +DEF_VEC_P (sym_fns_ptr); + +static VEC (sym_fns_ptr) *symtab_fns = NULL; /* Flag for whether user will be reloading symbols multiple times. Defaults to ON for VxWorks, otherwise OFF. */ @@ -161,8 +160,8 @@ static void show_symbol_reloading (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Dynamic symbol table reloading multiple times in one run is %s.\n"), + fprintf_filtered (file, _("Dynamic symbol table reloading " + "multiple times in one run is %s.\n"), value); } @@ -174,25 +173,15 @@ Dynamic symbol table reloading multiple times in one run is %s.\n"), this flag and then add the shared library symbols as needed. Note that there is a potential for confusion, since if the shared library symbols are not loaded, commands like "info fun" will *not* - report all the functions that are actually present. */ + report all the functions that are actually present. */ int auto_solib_add = 1; - -/* For systems that support it, a threshold size in megabytes. If - automatically adding a new library's symbol table to those already - known to the debugger would cause the total shared library symbol - size to exceed this threshhold, then the shlib's symbols are not - added. The threshold is ignored if the user explicitly asks for a - shlib to be added, such as when using the "sharedlibrary" - command. */ - -int auto_solib_limit; /* Make a null terminated copy of the string at PTR with SIZE characters in the obstack pointed to by OBSTACKP . Returns the address of the copy. - Note that the string at PTR does not have to be null terminated, I.E. it - may be part of a larger string and we are only saving a substring. */ + Note that the string at PTR does not have to be null terminated, I.e. it + may be part of a larger string and we are only saving a substring. */ char * obsavestring (const char *ptr, int size, struct obstack *obstackp) @@ -200,7 +189,7 @@ obsavestring (const char *ptr, int size, struct obstack *obstackp) char *p = (char *) obstack_alloc (obstackp, size + 1); /* Open-coded memcpy--saves function call time. These strings are usually short. FIXME: Is this really still true with a compiler that can - inline memcpy? */ + inline memcpy? */ { const char *p1 = ptr; char *p2 = p; @@ -213,9 +202,10 @@ obsavestring (const char *ptr, int size, struct obstack *obstackp) return p; } -/* Concatenate NULL terminated variable argument list of `const char *' strings; - return the new string. Space is found in the OBSTACKP. Argument list must - be terminated by a sentinel expression `(char *) NULL'. */ +/* Concatenate NULL terminated variable argument list of `const char *' + strings; return the new string. Space is found in the OBSTACKP. + Argument list must be terminated by a sentinel expression `(char *) + NULL'. */ char * obconcat (struct obstack *obstackp, ...) @@ -238,7 +228,7 @@ obconcat (struct obstack *obstackp, ...) return obstack_finish (obstackp); } -/* True if we are reading a symbol table. */ +/* True if we are reading a symbol table. */ int currently_reading_symtab = 0; @@ -301,7 +291,7 @@ alloc_section_addr_info (size_t num_sections) } /* Build (allocate and populate) a section_addr_info struct from - an existing section table. */ + an existing section table. */ extern struct section_addr_info * build_section_addr_info_from_section_table (const struct target_section *start, @@ -372,7 +362,7 @@ build_section_addr_info_from_objfile (const struct objfile *objfile) return sap; } -/* Free all memory allocated by build_section_addr_info_from_section_table. */ +/* Free all memory allocated by build_section_addr_info_from_section_table. */ extern void free_section_addr_info (struct section_addr_info *sap) @@ -531,7 +521,7 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections)); - /* Now calculate offsets for section that were specified by the caller. */ + /* Now calculate offsets for section that were specified by the caller. */ for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) { struct other_sections *osp; @@ -540,13 +530,30 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, if (osp->addr == 0) continue; - /* Record all sections in offsets */ + /* Record all sections in offsets. */ /* The section_offsets in the objfile are here filled in using - the BFD index. */ + the BFD index. */ section_offsets->offsets[osp->sectindex] = osp->addr; } } +/* Transform section name S for a name comparison. prelink can split section + `.bss' into two sections `.dynbss' and `.bss' (in this order). Similarly + prelink can split `.sbss' into `.sdynbss' and `.sbss'. Use virtual address + of the new `.dynbss' (`.sdynbss') section as the adjacent new `.bss' + (`.sbss') section has invalid (increased) virtual address. */ + +static const char * +addr_section_name (const char *s) +{ + if (strcmp (s, ".dynbss") == 0) + return ".bss"; + if (strcmp (s, ".sdynbss") == 0) + return ".sbss"; + + return s; +} + /* qsort comparator for addrs_section_sort. Sort entries in ascending order by their (name, sectindex) pair. sectindex makes the sort by name stable. */ @@ -557,7 +564,7 @@ addrs_section_compar (const void *ap, const void *bp) const struct other_sections *b = *((struct other_sections **) bp); int retval, a_idx, b_idx; - retval = strcmp (a->name, b->name); + retval = strcmp (addr_section_name (a->name), addr_section_name (b->name)); if (retval) return retval; @@ -633,7 +640,8 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) abfd_addrs_sorted = addrs_section_sort (abfd_addrs); make_cleanup (xfree, abfd_addrs_sorted); - /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and ABFD_ADDRS_SORTED. */ + /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and + ABFD_ADDRS_SORTED. */ addrs_to_abfd_addrs = xzalloc (sizeof (*addrs_to_abfd_addrs) * addrs->num_sections); @@ -641,14 +649,16 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) while (*addrs_sorted) { - const char *sect_name = (*addrs_sorted)->name; + const char *sect_name = addr_section_name ((*addrs_sorted)->name); while (*abfd_addrs_sorted - && strcmp ((*abfd_addrs_sorted)->name, sect_name) < 0) + && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), + sect_name) < 0) abfd_addrs_sorted++; if (*abfd_addrs_sorted - && strcmp ((*abfd_addrs_sorted)->name, sect_name) == 0) + && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), + sect_name) == 0) { int index_in_addrs; @@ -676,12 +686,11 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) { - const char *sect_name = addrs->other[i].name; struct other_sections *sect = addrs_to_abfd_addrs[i]; if (sect) { - /* This is the index used by BFD. */ + /* This is the index used by BFD. */ addrs->other[i].sectindex = sect->sectindex; if (addrs->other[i].addr != 0) @@ -694,6 +703,9 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) } else { + /* addr_section_name transformation is not used for SECT_NAME. */ + const char *sect_name = addrs->other[i].name; + /* This section does not exist in ABFD, which is normally unexpected and we want to issue a warning. @@ -704,12 +716,20 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) a warning. Shared libraries contain just the section ".gnu.liblist" but it is not marked as loadable there. There is no other way to identify them than by their name as the sections - created by prelink have no special flags. */ + created by prelink have no special flags. + + For the sections `.bss' and `.sbss' see addr_section_name. */ if (!(strcmp (sect_name, ".gnu.liblist") == 0 || strcmp (sect_name, ".gnu.conflict") == 0 - || strcmp (sect_name, ".dynbss") == 0 - || strcmp (sect_name, ".sdynbss") == 0)) + || (strcmp (sect_name, ".bss") == 0 + && i > 0 + && strcmp (addrs->other[i - 1].name, ".dynbss") == 0 + && addrs_to_abfd_addrs[i - 1] != NULL) + || (strcmp (sect_name, ".sbss") == 0 + && i > 0 + && strcmp (addrs->other[i - 1].name, ".sdynbss") == 0 + && addrs_to_abfd_addrs[i - 1] != NULL))) warning (_("section %s not found in %s"), sect_name, bfd_get_filename (abfd)); @@ -799,7 +819,8 @@ default_symfile_offsets (struct objfile *objfile, continue; bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]); - exec_set_section_address (bfd_get_filename (abfd), cur_sec->index, + exec_set_section_address (bfd_get_filename (abfd), + cur_sec->index, offsets[cur_sec->index]); offsets[cur_sec->index] = 0; } @@ -807,7 +828,7 @@ default_symfile_offsets (struct objfile *objfile, } /* Remember the bfd indexes for the .text, .data, .bss and - .rodata sections. */ + .rodata sections. */ init_objfile_sect_indices (objfile); } @@ -923,7 +944,7 @@ syms_from_objfile (struct objfile *objfile, objfile->sf = find_sym_fns (objfile->obfd); if (objfile->sf == NULL) - return; /* No symbols. */ + return; /* No symbols. */ /* Make sure that partially constructed symbol tables will be cleaned up if an error occurs during symbol reading. */ @@ -931,7 +952,7 @@ syms_from_objfile (struct objfile *objfile, /* If ADDRS and OFFSETS are both NULL, put together a dummy address list. We now establish the convention that an addr of zero means - no load address was specified. */ + no load address was specified. */ if (! addrs && ! offsets) { local_addr @@ -975,7 +996,7 @@ syms_from_objfile (struct objfile *objfile, /* Initialize symbol reading routines for this objfile, allow complaints to appear for this new file, and record how verbose to be, then do the - initial symbol reading for this file. */ + initial symbol reading for this file. */ (*objfile->sf->sym_init) (objfile); clear_complaints (&symfile_complaints, 1, add_flags & SYMFILE_VERBOSE); @@ -998,6 +1019,9 @@ syms_from_objfile (struct objfile *objfile, (*objfile->sf->sym_read) (objfile, add_flags); + if ((add_flags & SYMFILE_NO_READ) == 0) + require_partial_symbols (objfile, 0); + /* Discard cleanups as symbol reading was successful. */ discard_cleanups (old_chain); @@ -1006,20 +1030,20 @@ syms_from_objfile (struct objfile *objfile, /* Perform required actions after either reading in the initial symbols for a new objfile, or mapping in the symbols from a reusable - objfile. */ + objfile. ADD_FLAGS is a bitmask of enum symfile_add_flags. */ void new_symfile_objfile (struct objfile *objfile, int add_flags) { /* If this is the main symbol file we have to clean up all users of the - old main symbol file. Otherwise it is sufficient to fixup all the + old main symbol file. Otherwise it is sufficient to fixup all the breakpoints that may have been redefined by this symbol file. */ if (add_flags & SYMFILE_MAINLINE) { /* OK, make it the "real" symbol file. */ symfile_objfile = objfile; - clear_symtab_users (); + clear_symtab_users (add_flags); } else if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) { @@ -1044,7 +1068,7 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) ADDRS is ignored when SYMFILE_MAINLINE bit is set in ADD_FLAGS. Upon success, returns a pointer to the objfile that was added. - Upon failure, jumps back to command level (never returns). */ + Upon failure, jumps back to command level (never returns). */ static struct objfile * symbol_file_add_with_addrs_or_offsets (bfd *abfd, @@ -1058,6 +1082,15 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, struct cleanup *my_cleanups; const char *name = bfd_get_filename (abfd); const int from_tty = add_flags & SYMFILE_VERBOSE; + const int should_print = ((from_tty || info_verbose) + && (readnow_symbol_files + || (add_flags & SYMFILE_NO_READ) == 0)); + + if (readnow_symbol_files) + { + flags |= OBJF_READNOW; + add_flags &= ~SYMFILE_NO_READ; + } my_cleanups = make_cleanup_bfd_close (abfd); @@ -1075,8 +1108,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, /* We either created a new mapped symbol table, mapped an existing symbol table file which has not had initial symbol reading - performed, or need to read an unmapped symbol table. */ - if (from_tty || info_verbose) + performed, or need to read an unmapped symbol table. */ + if (should_print) { if (deprecated_pre_add_symbol_hook) deprecated_pre_add_symbol_hook (name); @@ -1093,11 +1126,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, /* We now have at least a partial symbol table. Check to see if the user requested that all symbols be read on initial access via either the gdb startup command line or on a per symbol file basis. Expand - all partial symbol tables for this objfile if so. */ + all partial symbol tables for this objfile if so. */ - if ((flags & OBJF_READNOW) || readnow_symbol_files) + if ((flags & OBJF_READNOW)) { - if (from_tty || info_verbose) + if (should_print) { printf_unfiltered (_("expanding to full symbols...")); wrap_here (""); @@ -1108,15 +1141,14 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, objfile->sf->qf->expand_all_symtabs (objfile); } - if ((from_tty || info_verbose) - && !objfile_has_symbols (objfile)) + if (should_print && !objfile_has_symbols (objfile)) { wrap_here (""); printf_unfiltered (_("(no debugging symbols found)...")); wrap_here (""); } - if (from_tty || info_verbose) + if (should_print) { if (deprecated_post_add_symbol_hook) deprecated_post_add_symbol_hook (); @@ -1134,7 +1166,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, if (objfile->sf == NULL) { observer_notify_new_objfile (objfile); - return objfile; /* No symbols. */ + return objfile; /* No symbols. */ } new_symfile_objfile (objfile, add_flags); @@ -1267,7 +1299,7 @@ get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out) bfd_get_section_contents (objfile->obfd, sect, contents, (file_ptr)0, (bfd_size_type)debuglink_size); - /* Crc value is stored after the filename, aligned up to 4 bytes. */ + /* Crc value is stored after the filename, aligned up to 4 bytes. */ crc_offset = strlen (contents) + 1; crc_offset = (crc_offset + 3) & ~3; @@ -1291,9 +1323,9 @@ separate_debug_file_exists (const char *name, unsigned long crc, PARENT_OBJFILE itself this function would not be called. .gnu_debuglink section can contain just the basename of PARENT_OBJFILE without any ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where - the separate debug infos with the same basename can exist. */ + the separate debug infos with the same basename can exist. */ - if (strcmp (name, parent_objfile->name) == 0) + if (filename_cmp (name, parent_objfile->name) == 0) return 0; abfd = bfd_open_maybe_remote (name); @@ -1301,7 +1333,7 @@ separate_debug_file_exists (const char *name, unsigned long crc, if (!abfd) return 0; - /* Verify symlinks were not the cause of strcmp name difference above. + /* Verify symlinks were not the cause of filename_cmp name difference above. Some operating systems, e.g. Windows, do not provide a meaningful st_ino; they always set it to zero. (Windows does provide a @@ -1342,8 +1374,9 @@ static void show_debug_file_directory (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The directory where separate debug symbols are searched for is \"%s\".\n"), + fprintf_filtered (file, + _("The directory where separate debug " + "symbols are searched for is \"%s\".\n"), value); } @@ -1380,7 +1413,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) /* If I is -1 then no directory is present there and DIR will be "". */ dir[i+1] = '\0'; - /* Set I to max (strlen (canon_name), strlen (dir)). */ + /* Set I to max (strlen (canon_name), strlen (dir)). */ canon_name = lrealpath (dir); i = strlen (dir); if (canon_name && strlen (canon_name) > i) @@ -1438,7 +1471,8 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) /* If the file is in the sysroot, try using its base path in the global debugfile directory. */ if (canon_name - && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0 + && filename_ncmp (canon_name, gdb_sysroot, + strlen (gdb_sysroot)) == 0 && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)])) { memcpy (debugfile, debugdir, debugdir_end - debugdir); @@ -1533,12 +1567,18 @@ symbol_file_command (char *args, int from_tty) void set_initial_language (void) { - char *filename; enum language lang = language_unknown; - filename = find_main_filename (); - if (filename != NULL) - lang = deduce_language_from_filename (filename); + if (language_of_main != language_unknown) + lang = language_of_main; + else + { + const char *filename; + + filename = find_main_filename (); + if (filename != NULL) + lang = deduce_language_from_filename (filename); + } if (lang == language_unknown) { @@ -1619,7 +1659,7 @@ symfile_bfd_open (char *name) } /* Free 1st new malloc'd copy, but keep the 2nd malloc'd copy in - bfd. It'll be freed in free_objfile(). */ + bfd. It'll be freed in free_objfile(). */ xfree (name); name = absolute_name; @@ -1666,14 +1706,12 @@ get_section_index (struct objfile *objfile, char *section_name) /* Link SF into the global symtab_fns list. Called on startup by the _initialize routine in each object file format reader, to register - information about each format the the reader is prepared to - handle. */ + information about each format the reader is prepared to handle. */ void -add_symtab_fns (struct sym_fns *sf) +add_symtab_fns (const struct sym_fns *sf) { - sf->next = symtab_fns; - symtab_fns = sf; + VEC_safe_push (sym_fns_ptr, symtab_fns, sf); } /* Initialize OBJFILE to read symbols from its associated BFD. It @@ -1681,18 +1719,19 @@ add_symtab_fns (struct sym_fns *sf) struct sym_fns in the objfile structure, that contains cached information about the symbol file. */ -static struct sym_fns * +static const struct sym_fns * find_sym_fns (bfd *abfd) { - struct sym_fns *sf; + const struct sym_fns *sf; enum bfd_flavour our_flavour = bfd_get_flavour (abfd); + int i; if (our_flavour == bfd_target_srec_flavour || our_flavour == bfd_target_ihex_flavour || our_flavour == bfd_target_tekhex_flavour) return NULL; /* No symbols. */ - for (sf = symtab_fns; sf != NULL; sf = sf->next) + for (i = 0; VEC_iterate (sym_fns_ptr, symtab_fns, i, sf); ++i) if (our_flavour == sf->sym_flavour) return sf; @@ -1706,6 +1745,8 @@ find_sym_fns (bfd *abfd) static void load_command (char *arg, int from_tty) { + dont_repeat (); + /* The user might be reloading because the binary has changed. Take this opportunity to check. */ reopen_exec_file (); @@ -1890,7 +1931,8 @@ load_section_callback (bfd *abfd, asection *asec, void *data) memset (new_request, 0, sizeof (struct memory_write_request)); section_data = xcalloc (1, sizeof (struct load_progress_section_data)); new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset; - new_request->end = new_request->begin + size; /* FIXME Should size be in instead? */ + new_request->end = new_request->begin + size; /* FIXME Should size + be in instead? */ new_request->data = xmalloc (size); new_request->baton = section_data; @@ -1967,7 +2009,7 @@ generic_load (char *args, int from_tty) error (_("Too many parameters.")); } - /* Open the file for loading. */ + /* Open the file for loading. */ loadfile_bfd = bfd_openr (filename, gnutarget); if (loadfile_bfd == NULL) { @@ -2032,11 +2074,11 @@ generic_load (char *args, int from_tty) do_cleanups (old_cleanups); } -/* Report how fast the transfer went. */ +/* Report how fast the transfer went. */ /* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being replaced by print_transfer_performance (with a very different - function signature). */ + function signature). */ void report_transfer_performance (unsigned long data_count, time_t start_time, @@ -2108,7 +2150,7 @@ print_transfer_performance (struct ui_file *stream, monitor for Microware's OS-9 / OS-9000, see remote-os9k.c). In the rombug case, the user doesn't need to supply a text address, instead a call to target_link() (in target.c) would supply the - value to use. We are now discontinuing this type of ad hoc syntax. */ + value to use. We are now discontinuing this type of ad hoc syntax. */ static void add_symbol_file_command (char *args, int from_tty) @@ -2150,10 +2192,10 @@ add_symbol_file_command (char *args, int from_tty) for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt]) { - /* Process the argument. */ + /* Process the argument. */ if (argcnt == 0) { - /* The first argument is the file name. */ + /* The first argument is the file name. */ filename = tilde_expand (arg); make_cleanup (xfree, filename); } @@ -2161,7 +2203,7 @@ add_symbol_file_command (char *args, int from_tty) if (argcnt == 1) { /* The second argument is always the text address at which - to load the program. */ + to load the program. */ sect_opts[section_index].name = ".text"; sect_opts[section_index].value = arg; if (++section_index >= num_sect_opts) @@ -2176,7 +2218,7 @@ add_symbol_file_command (char *args, int from_tty) else { /* It's an option (starting with '-') or it's an argument - to an option */ + to an option. */ if (*arg == '-') { @@ -2210,7 +2252,8 @@ add_symbol_file_command (char *args, int from_tty) } } else - error (_("USAGE: add-symbol-file [-mapped] [-readnow] [-s ]*")); + error (_("USAGE: add-symbol-file " + " [-mapped] [-readnow] [-s ]*")); } } } @@ -2222,11 +2265,11 @@ add_symbol_file_command (char *args, int from_tty) if (section_index < 1) error (_("The address where %s has been loaded is missing"), filename); - /* Print the prompt for the query below. And save the arguments into + /* Print the prompt for the query below. And save the arguments into a sect_addr_info structure to be passed around to other functions. We have to split this up into separate print statements because hex_string returns a local static - string. */ + string. */ printf_unfiltered (_("add symbol table from file \"%s\" at\n"), filename); section_addrs = alloc_section_addr_info (section_index); @@ -2240,7 +2283,7 @@ add_symbol_file_command (char *args, int from_tty) addr = parse_and_eval_address (val); /* Here we store the section offsets in the order they were - entered on the command line. */ + entered on the command line. */ section_addrs->other[sec_num].name = sec; section_addrs->other[sec_num].addr = addr; printf_unfiltered ("\t%s_addr = %s\n", sec, @@ -2281,7 +2324,7 @@ reread_symbols (void) the load time should be saved in the partial symbol tables, since different tables may come from different source files. FIXME. This routine should then walk down each partial symbol table - and see if the symbol table that it originates from has been changed */ + and see if the symbol table that it originates from has been changed. */ for (objfile = object_files; objfile; objfile = objfile->next) { @@ -2303,7 +2346,7 @@ reread_symbols (void) res = stat (objfile->name, &new_statbuf); if (res != 0) { - /* FIXME, should use print_sys_errmsg but it's not filtered. */ + /* FIXME, should use print_sys_errmsg but it's not filtered. */ printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), objfile->name); continue; @@ -2333,8 +2376,9 @@ reread_symbols (void) /* We need to do this whenever any symbols go away. */ make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); - if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd), - bfd_get_filename (exec_bfd)) == 0) + if (exec_bfd != NULL + && filename_cmp (bfd_get_filename (objfile->obfd), + bfd_get_filename (exec_bfd)) == 0) { /* Reload EXEC_BFD without asking anything. */ @@ -2398,13 +2442,13 @@ reread_symbols (void) memset (&objfile->static_psymbols, 0, sizeof (objfile->static_psymbols)); - /* Free the obstacks for non-reusable objfiles */ - bcache_xfree (objfile->psymbol_cache); - objfile->psymbol_cache = bcache_xmalloc (); + /* Free the obstacks for non-reusable objfiles. */ + psymbol_bcache_free (objfile->psymbol_cache); + objfile->psymbol_cache = psymbol_bcache_init (); bcache_xfree (objfile->macro_cache); - objfile->macro_cache = bcache_xmalloc (); + objfile->macro_cache = bcache_xmalloc (NULL, NULL); bcache_xfree (objfile->filename_cache); - objfile->filename_cache = bcache_xmalloc (); + objfile->filename_cache = bcache_xmalloc (NULL,NULL); if (objfile->demangled_names_hash != NULL) { htab_delete (objfile->demangled_names_hash); @@ -2417,6 +2461,7 @@ reread_symbols (void) objfile->psymtabs_addrmap = NULL; objfile->free_psymtabs = NULL; objfile->cp_namespace_symtab = NULL; + objfile->template_symbols = NULL; objfile->msymbols = NULL; objfile->deprecated_sym_private = NULL; objfile->minimal_symbol_count = 0; @@ -2425,9 +2470,9 @@ reread_symbols (void) memset (&objfile->msymbol_demangled_hash, 0, sizeof (objfile->msymbol_demangled_hash)); - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_cache = bcache_xmalloc (); - objfile->filename_cache = bcache_xmalloc (); + objfile->psymbol_cache = psymbol_bcache_init (); + objfile->macro_cache = bcache_xmalloc (NULL, NULL); + objfile->filename_cache = bcache_xmalloc (NULL, NULL); /* obstack_init also initializes the obstack so it is empty. We could use obstack_specify_allocation but gdb_obstack.h specifies the alloc/dealloc @@ -2462,6 +2507,12 @@ reread_symbols (void) /* Do not set flags as this is safe and we don't want to be verbose. */ (*objfile->sf->sym_read) (objfile, 0); + if ((objfile->flags & OBJF_PSYMTABS_READ) != 0) + { + objfile->flags &= ~OBJF_PSYMTABS_READ; + require_partial_symbols (objfile, 0); + } + if (!objfile_has_symbols (objfile)) { wrap_here (""); @@ -2494,7 +2545,7 @@ reread_symbols (void) /* Notify objfiles that we've modified objfile sections. */ objfiles_changed (); - clear_symtab_users (); + clear_symtab_users (0); /* At least one objfile has changed, so we can consider that the executable we're debugging has changed too. */ observer_notify_executable_changed (); @@ -2534,8 +2585,9 @@ static void show_ext_args (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Mapping between filename extension and source language is \"%s\".\n"), + fprintf_filtered (file, + _("Mapping between filename extension " + "and source language is \"%s\".\n"), value); } @@ -2546,7 +2598,7 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) char *cp = ext_args; enum language lang; - /* First arg is filename extension, starting with '.' */ + /* First arg is filename extension, starting with '.' */ if (*cp != '.') error (_("'%s': Filename extension must begin with '.'"), ext_args); @@ -2555,10 +2607,11 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) cp++; if (*cp == '\0') - error (_("'%s': two arguments required -- filename extension and language"), + error (_("'%s': two arguments required -- " + "filename extension and language"), ext_args); - /* Null-terminate first arg */ + /* Null-terminate first arg. */ *cp++ = '\0'; /* Find beginning of second arg, which should be a source language. */ @@ -2566,7 +2619,8 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) cp++; if (*cp == '\0') - error (_("'%s': two arguments required -- filename extension and language"), + error (_("'%s': two arguments required -- " + "filename extension and language"), ext_args); /* Lookup the language from among those we know. */ @@ -2579,12 +2633,12 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) if (i >= fl_table_next) { - /* new file extension */ + /* New file extension. */ add_filename_language (ext_args, lang); } else { - /* redefining a previously known filename extension */ + /* Redefining a previously known filename extension. */ /* if (from_tty) */ /* query ("Really make files of type %s '%s'?", */ @@ -2612,7 +2666,7 @@ info_ext_lang_command (char *args, int from_tty) static void init_filename_language_table (void) { - if (fl_table_size == 0) /* protect against repetition */ + if (fl_table_size == 0) /* Protect against repetition. */ { fl_table_size = 20; fl_table_next = 0; @@ -2660,7 +2714,7 @@ init_filename_language_table (void) } enum language -deduce_language_from_filename (char *filename) +deduce_language_from_filename (const char *filename) { int i; char *cp; @@ -2688,7 +2742,7 @@ deduce_language_from_filename (char *filename) */ struct symtab * -allocate_symtab (char *filename, struct objfile *objfile) +allocate_symtab (const char *filename, struct objfile *objfile) { struct symtab *symtab; @@ -2701,7 +2755,7 @@ allocate_symtab (char *filename, struct objfile *objfile) symtab->language = deduce_language_from_filename (filename); symtab->debugformat = "unknown"; - /* Hook it to the objfile it comes from */ + /* Hook it to the objfile it comes from. */ symtab->objfile = objfile; symtab->next = objfile->symtabs; @@ -2712,10 +2766,10 @@ allocate_symtab (char *filename, struct objfile *objfile) /* Reset all data structures in gdb which may contain references to symbol - table data. */ + table data. ADD_FLAGS is a bitmask of enum symfile_add_flags. */ void -clear_symtab_users (void) +clear_symtab_users (int add_flags) { /* Someday, we should do better than this, by only blowing away the things that really need to be blown. */ @@ -2725,7 +2779,8 @@ clear_symtab_users (void) clear_current_source_symtab_and_line (); clear_displays (); - breakpoint_re_set (); + if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) + breakpoint_re_set (); set_default_breakpoint (0, NULL, 0, 0, 0); clear_pc_function_cache (); observer_notify_new_objfile (NULL); @@ -2744,7 +2799,7 @@ clear_symtab_users (void) static void clear_symtab_users_cleanup (void *ignore) { - clear_symtab_users (); + clear_symtab_users (0); } /* OVERLAYS: @@ -2793,13 +2848,12 @@ clear_symtab_users_cleanup (void *ignore) overlay_unmapped_address(...): map an address from section's VMA to LMA symbol_overlayed_address(...): Return a "current" address for symbol: either in VMA or LMA depending on whether - the symbol's section is currently mapped - */ + the symbol's section is currently mapped. */ /* Overlay debugging state: */ enum overlay_debugging_state overlay_debugging = ovly_off; -int overlay_cache_invalid = 0; /* True if need to refresh mapped state */ +int overlay_cache_invalid = 0; /* True if need to refresh mapped state. */ /* Function: section_is_overlay (SECTION) Returns true if SECTION has VMA not equal to LMA, ie. @@ -2860,7 +2914,7 @@ section_is_mapped (struct obj_section *osect) return 0; /* overlay debugging off */ case ovly_auto: /* overlay debugging automatic */ /* Unles there is a gdbarch_overlay_update function, - there's really nothing useful to do here (can't really go auto) */ + there's really nothing useful to do here (can't really go auto). */ gdbarch = get_objfile_arch (osect->objfile); if (gdbarch_overlay_update_p (gdbarch)) { @@ -2979,13 +3033,14 @@ symbol_overlayed_address (CORE_ADDR address, struct obj_section *section) { if (overlay_debugging) { - /* If the symbol has no section, just return its regular address. */ + /* If the symbol has no section, just return its regular address. */ if (section == 0) return address; - /* If the symbol's section is not an overlay, just return its address */ + /* If the symbol's section is not an overlay, just return its + address. */ if (!section_is_overlay (section)) return address; - /* If the symbol's section is mapped, just return its address */ + /* If the symbol's section is mapped, just return its address. */ if (section_is_mapped (section)) return address; /* @@ -3045,7 +3100,7 @@ find_pc_mapped_section (CORE_ADDR pc) } /* Function: list_overlays_command - Print a list of mapped sections and their PC ranges */ + Print a list of mapped sections and their PC ranges. */ void list_overlays_command (char *args, int from_tty) @@ -3094,22 +3149,22 @@ map_overlay_command (char *args, int from_tty) struct obj_section *sec, *sec2; if (!overlay_debugging) - error (_("\ -Overlay debugging not enabled. Use either the 'overlay auto' or\n\ -the 'overlay manual' command.")); + error (_("Overlay debugging not enabled. Use " + "either the 'overlay auto' or\n" + "the 'overlay manual' command.")); if (args == 0 || *args == 0) error (_("Argument required: name of an overlay section")); - /* First, find a section matching the user supplied argument */ + /* First, find a section matching the user supplied argument. */ ALL_OBJSECTIONS (objfile, sec) if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args)) { - /* Now, check to see if the section is an overlay. */ + /* Now, check to see if the section is an overlay. */ if (!section_is_overlay (sec)) continue; /* not an overlay section */ - /* Mark the overlay as "mapped" */ + /* Mark the overlay as "mapped". */ sec->ovly_mapped = 1; /* Next, make a pass and unmap any sections that are @@ -3121,7 +3176,7 @@ the 'overlay manual' command.")); printf_unfiltered (_("Note: section %s unmapped by overlap\n"), bfd_section_name (objfile->obfd, sec2->the_bfd_section)); - sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2 */ + sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2. */ } return; } @@ -3139,14 +3194,14 @@ unmap_overlay_command (char *args, int from_tty) struct obj_section *sec; if (!overlay_debugging) - error (_("\ -Overlay debugging not enabled. Use either the 'overlay auto' or\n\ -the 'overlay manual' command.")); + error (_("Overlay debugging not enabled. " + "Use either the 'overlay auto' or\n" + "the 'overlay manual' command.")); if (args == 0 || *args == 0) error (_("Argument required: name of an overlay section")); - /* First, find a section matching the user supplied argument */ + /* First, find a section matching the user supplied argument. */ ALL_OBJSECTIONS (objfile, sec) if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args)) { @@ -3160,7 +3215,7 @@ the 'overlay manual' command.")); /* Function: overlay_auto_command A utility command to turn on overlay debugging. - Possibly this should be done via a set/show command. */ + Possibly this should be done via a set/show command. */ static void overlay_auto_command (char *args, int from_tty) @@ -3173,7 +3228,7 @@ overlay_auto_command (char *args, int from_tty) /* Function: overlay_manual_command A utility command to turn on overlay debugging. - Possibly this should be done via a set/show command. */ + Possibly this should be done via a set/show command. */ static void overlay_manual_command (char *args, int from_tty) @@ -3186,7 +3241,7 @@ overlay_manual_command (char *args, int from_tty) /* Function: overlay_off_command A utility command to turn on overlay debugging. - Possibly this should be done via a set/show command. */ + Possibly this should be done via a set/show command. */ static void overlay_off_command (char *args, int from_tty) @@ -3209,9 +3264,9 @@ overlay_load_command (char *args, int from_tty) } /* Function: overlay_command - A place-holder for a mis-typed command */ + A place-holder for a mis-typed command. */ -/* Command list chain containing all defined "overlay" subcommands. */ +/* Command list chain containing all defined "overlay" subcommands. */ struct cmd_list_element *overlaylist; static void @@ -3254,28 +3309,18 @@ overlay_command (char *args, int from_tty) attempt to detect when the cached copy is invalidated. The main entry point is "simple_overlay_update(SECT), which looks up SECT in the cached table and re-reads only the entry for that section from - the target (whenever possible). - */ + the target (whenever possible). */ /* Cached, dynamically allocated copies of the target data structures: */ static unsigned (*cache_ovly_table)[4] = 0; -#if 0 -static unsigned (*cache_ovly_region_table)[3] = 0; -#endif static unsigned cache_novlys = 0; -#if 0 -static unsigned cache_novly_regions = 0; -#endif static CORE_ADDR cache_ovly_table_base = 0; -#if 0 -static CORE_ADDR cache_ovly_region_table_base = 0; -#endif enum ovly_index { VMA, SIZE, LMA, MAPPED }; -/* Throw away the cached copy of _ovly_table */ +/* Throw away the cached copy of _ovly_table. */ static void simple_free_overlay_table (void) { @@ -3286,26 +3331,13 @@ simple_free_overlay_table (void) cache_ovly_table_base = 0; } -#if 0 -/* Throw away the cached copy of _ovly_region_table */ -static void -simple_free_overlay_region_table (void) -{ - if (cache_ovly_region_table) - xfree (cache_ovly_region_table); - cache_novly_regions = 0; - cache_ovly_region_table = NULL; - cache_ovly_region_table_base = 0; -} -#endif - /* Read an array of ints of size SIZE from the target into a local buffer. - Convert to host order. int LEN is number of ints */ + Convert to host order. int LEN is number of ints. */ static void read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len, int size, enum bfd_endian byte_order) { - /* FIXME (alloca): Not safe if array is very large. */ + /* FIXME (alloca): Not safe if array is very large. */ gdb_byte *buf = alloca (len * size); int i; @@ -3315,7 +3347,7 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, } /* Find and grab a copy of the target _ovly_table - (and _novlys, which is needed for the table's size) */ + (and _novlys, which is needed for the table's size). */ static int simple_read_overlay_table (void) { @@ -3359,50 +3391,6 @@ simple_read_overlay_table (void) return 1; /* SUCCESS */ } -#if 0 -/* Find and grab a copy of the target _ovly_region_table - (and _novly_regions, which is needed for the table's size) */ -static int -simple_read_overlay_region_table (void) -{ - struct minimal_symbol *msym; - struct gdbarch *gdbarch; - int word_size; - enum bfd_endian byte_order; - - simple_free_overlay_region_table (); - msym = lookup_minimal_symbol ("_novly_regions", NULL, NULL); - if (msym == NULL) - return 0; /* failure */ - - gdbarch = get_objfile_arch (msymbol_objfile (msym)); - word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; - byte_order = gdbarch_byte_order (gdbarch); - - cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), - 4, byte_order); - - cache_ovly_region_table = (void *) xmalloc (cache_novly_regions * 12); - if (cache_ovly_region_table != NULL) - { - msym = lookup_minimal_symbol ("_ovly_region_table", NULL, NULL); - if (msym != NULL) - { - cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym); - read_target_long_array (cache_ovly_region_table_base, - (unsigned int *) cache_ovly_region_table, - cache_novly_regions * 3, - word_size, byte_order); - } - else - return 0; /* failure */ - } - else - return 0; /* failure */ - return 1; /* SUCCESS */ -} -#endif - /* Function: simple_overlay_update_1 A helper function for simple_overlay_update. Assuming a cached copy of _ovly_table exists, look through it to find an entry whose vma, @@ -3437,7 +3425,7 @@ simple_overlay_update_1 (struct obj_section *osect) osect->ovly_mapped = cache_ovly_table[i][MAPPED]; return 1; } - else /* Warning! Warning! Target's ovly table has changed! */ + else /* Warning! Warning! Target's ovly table has changed! */ return 0; } return 0; @@ -3456,17 +3444,28 @@ simple_overlay_update (struct obj_section *osect) { struct objfile *objfile; - /* Were we given an osect to look up? NULL means do all of them. */ + /* Were we given an osect to look up? NULL means do all of them. */ if (osect) - /* Have we got a cached copy of the target's overlay table? */ + /* Have we got a cached copy of the target's overlay table? */ if (cache_ovly_table != NULL) - /* Does its cached location match what's currently in the symtab? */ - if (cache_ovly_table_base == - SYMBOL_VALUE_ADDRESS (lookup_minimal_symbol ("_ovly_table", NULL, NULL))) - /* Then go ahead and try to look up this single section in the cache */ - if (simple_overlay_update_1 (osect)) - /* Found it! We're done. */ - return; + { + /* Does its cached location match what's currently in the + symtab? */ + struct minimal_symbol *minsym + = lookup_minimal_symbol ("_ovly_table", NULL, NULL); + + if (minsym == NULL) + error (_("Error reading inferior's overlay table: couldn't " + "find `_ovly_table' array\n" + "in inferior. Use `overlay manual' mode.")); + + if (cache_ovly_table_base == SYMBOL_VALUE_ADDRESS (minsym)) + /* Then go ahead and try to look up this single section in + the cache. */ + if (simple_overlay_update_1 (osect)) + /* Found it! We're done. */ + return; + } /* Cached table no good: need to read the entire table anew. Or else we want all the sections, in which case it's actually @@ -3475,7 +3474,7 @@ simple_overlay_update (struct obj_section *osect) if (! simple_read_overlay_table ()) return; - /* Now may as well update all sections, even if only one was requested. */ + /* Now may as well update all sections, even if only one was requested. */ ALL_OBJSECTIONS (objfile, osect) if (section_is_overlay (osect)) { @@ -3488,9 +3487,9 @@ simple_overlay_update (struct obj_section *osect) if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) /* && cache_ovly_table[i][SIZE] == size */ ) - { /* obj_section matches i'th entry in ovly_table */ + { /* obj_section matches i'th entry in ovly_table. */ osect->ovly_mapped = cache_ovly_table[i][MAPPED]; - break; /* finished with inner for loop: break out */ + break; /* finished with inner for loop: break out. */ } } } @@ -3554,7 +3553,7 @@ symfile_relocate_debug_section (struct objfile *objfile, struct symfile_segment_data * get_symfile_segment_data (bfd *abfd) { - struct sym_fns *sf = find_sym_fns (abfd); + const struct sym_fns *sf = find_sym_fns (abfd); if (sf == NULL) return NULL; @@ -3683,8 +3682,8 @@ to execute."), &cmdlist); c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, _("\ Load symbols from FILE, assuming FILE has been dynamically loaded.\n\ -Usage: add-symbol-file FILE ADDR [-s -s ...]\n\ -ADDR is the starting address of the file's text.\n\ +Usage: add-symbol-file FILE ADDR [-s -s \ + ...]\nADDR is the starting address of the file's text.\n\ The optional arguments are section-name section-address pairs and\n\ should be specified if the data and bss segments are not contiguous\n\ with the text. SECT is a section name to be loaded at SECT_ADDR."), diff --git a/contrib/gdb-7/gdb/symfile.h b/contrib/gdb-7/gdb/symfile.h index d53c465c6d..dad032031b 100644 --- a/contrib/gdb-7/gdb/symfile.h +++ b/contrib/gdb-7/gdb/symfile.h @@ -1,7 +1,7 @@ /* Definitions for reading symbol files into GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -32,6 +32,11 @@ struct obj_section; struct obstack; struct block; +/* Comparison function for symbol look ups. */ + +typedef int (symbol_compare_ftype) (const char *string1, + const char *string2); + /* Partial symbols are stored in the psymbol_cache and pointers to them are kept in a dynamically grown array that is obtained from malloc and grown as necessary via realloc. Each objfile typically @@ -75,7 +80,7 @@ struct section_addr_info /* The number of sections for which address information is available. */ size_t num_sections; - /* Sections whose names are file format dependent. */ + /* Sections whose names are file format dependent. */ struct other_sections { CORE_ADDR addr; @@ -171,6 +176,15 @@ struct quick_symbol_functions int kind, const char *name, domain_enum domain); + /* This is called to expand symbol tables before looking up a + symbol. A backend can choose to implement this and then have its + `lookup_symbol' hook always return NULL, or the reverse. (It + doesn't make sense to implement both.) The arguments are as for + `lookup_symbol'. */ + void (*pre_expand_symtabs_matching) (struct objfile *objfile, + int kind, const char *name, + domain_enum domain); + /* Print statistics about any indices loaded for OBJFILE. The statistics should be printed to gdb_stdout. This is used for "maint print statistics". */ @@ -195,45 +209,58 @@ struct quick_symbol_functions void (*expand_all_symtabs) (struct objfile *objfile); /* Read all symbol tables associated with OBJFILE which have the - file name FILENAME. */ + file name FILENAME. + This is for the purposes of examining code only, e.g., expand_line_sal. + The routine may ignore debug info that is known to not be useful with + code, e.g., DW_TAG_type_unit for dwarf debug info. */ void (*expand_symtabs_with_filename) (struct objfile *objfile, const char *filename); /* Return the file name of the file holding the symbol in OBJFILE named NAME. If no such symbol exists in OBJFILE, return NULL. */ - char *(*find_symbol_file) (struct objfile *objfile, const char *name); - - /* This method is specific to Ada. It walks the partial symbol - tables of OBJFILE looking for a name match. WILD_MATCH and - IS_NAME_SUFFIX are predicate functions that the implementation - may call to check for a match. - - This function is completely ad hoc and new implementations should - refer to the psymtab implementation to see what to do. */ - void (*map_ada_symtabs) (struct objfile *objfile, - int (*wild_match) (const char *, int, const char *), - int (*is_name_suffix) (const char *), - void (*callback) (struct objfile *, - struct symtab *, void *), - const char *name, int global, - domain_enum namespace, int wild, - void *data); + const char *(*find_symbol_file) (struct objfile *objfile, const char *name); + + /* Find global or static symbols in all tables that are in NAMESPACE + and for which MATCH (symbol name, NAME) == 0, passing each to + CALLBACK, reading in partial symbol symbol tables as needed. Look + through global symbols if GLOBAL and otherwise static symbols. + Passes NAME, NAMESPACE, and DATA to CALLBACK with each symbol + found. After each block is processed, passes NULL to CALLBACK. + MATCH must be weaker than strcmp_iw in the sense that + strcmp_iw(x,y) == 0 --> MATCH(x,y) == 0. ORDERED_COMPARE, if + non-null, must be an ordering relation compatible with strcmp_iw + in the sense that + strcmp(x,y) == 0 --> ORDERED_COMPARE(x,y) == 0 + and + strcmp(x,y) <= 0 --> ORDERED_COMPARE(x,y) <= 0 + (allowing strcmp(x,y) < 0 while ORDERED_COMPARE(x, y) == 0). + CALLBACK returns 0 to indicate that the scan should continue, or + non-zero to indicate that the scan should be terminated. */ + + void (*map_matching_symbols) (const char *name, domain_enum namespace, + struct objfile *, int global, + int (*callback) (struct block *, + struct symbol *, void *), + void *data, + symbol_compare_ftype *match, + symbol_compare_ftype *ordered_compare); /* Expand all symbol tables in OBJFILE matching some criteria. FILE_MATCHER is called for each file in OBJFILE. The file name and the DATA argument are passed to it. If it returns zero, this - file is skipped. + file is skipped. If FILE_MATCHER is NULL such file is not skipped. - Otherwise, if the file is not skipped, then NAME_MATCHER is - called for each symbol defined in the file. The symbol's - "natural" name and DATA are passed to NAME_MATCHER. + Otherwise, if KIND does not match this symbol is skipped. + + If even KIND matches, then NAME_MATCHER is called for each symbol defined + in the file. The symbol's "natural" name and DATA are passed to + NAME_MATCHER. If NAME_MATCHER returns zero, then this symbol is skipped. - Otherwise, if this symbol is not skipped, and it matches KIND, - then this symbol's symbol table is expanded. - + Otherwise, this symbol's symbol table is expanded. + DATA is user data that is passed unmodified to the callback functions. */ void (*expand_symtabs_matching) (struct objfile *objfile, @@ -254,16 +281,9 @@ struct quick_symbol_functions struct obj_section *section, int warn_if_readin); - /* Call a callback for every symbol defined in OBJFILE. FUN is the - callback. It is passed the symbol's natural name, and the DATA - passed to this function. */ - void (*map_symbol_names) (struct objfile *objfile, - void (*fun) (const char *, void *), - void *data); - - /* Call a callback for every file defined in OBJFILE. FUN is the - callback. It is passed the file's name, the file's full name, - and the DATA passed to this function. */ + /* Call a callback for every file defined in OBJFILE whose symtab is + not already read in. FUN is the callback. It is passed the file's name, + the file's full name, and the DATA passed to this function. */ void (*map_symbol_filenames) (struct objfile *objfile, void (*fun) (const char *, const char *, void *), @@ -300,6 +320,13 @@ struct sym_fns void (*sym_read) (struct objfile *, int); + /* Read the partial symbols for an objfile. This may be NULL, in which case + gdb has to check other ways if this objfile has any symbols. This may + only be non-NULL if the objfile actually does have debuginfo available. + */ + + void (*sym_read_psymbols) (struct objfile *); + /* Called when we are finished with an objfile. Should do all cleanup that is specific to the object file format for the particular objfile. */ @@ -336,18 +363,10 @@ struct sym_fns /* The "quick" (aka partial) symbol functions for this symbol reader. */ const struct quick_symbol_functions *qf; - - /* Finds the next struct sym_fns. They are allocated and - initialized in whatever module implements the functions pointed - to; an initializer calls add_symtab_fns to add them to the global - chain. */ - - struct sym_fns *next; - }; extern struct section_addr_info * - build_section_addr_info_from_objfile (const struct objfile *objfile); + build_section_addr_info_from_objfile (const struct objfile *objfile); extern void relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, int num_sections, @@ -373,25 +392,9 @@ extern struct symfile_segment_data *default_symfile_segments (bfd *abfd); extern bfd_byte *default_symfile_relocate (struct objfile *objfile, asection *sectp, bfd_byte *buf); -extern void extend_psymbol_list (struct psymbol_allocation_list *, - struct objfile *); +extern struct symtab *allocate_symtab (const char *, struct objfile *); -/* Add any kind of symbol to a psymbol_allocation_list. */ - -/* #include "demangle.h" */ - -extern const -struct partial_symbol *add_psymbol_to_list (char *, int, int, domain_enum, - enum address_class, - struct psymbol_allocation_list *, - long, CORE_ADDR, - enum language, struct objfile *); - -extern void init_psymbol_list (struct objfile *, int); - -extern struct symtab *allocate_symtab (char *, struct objfile *); - -extern void add_symtab_fns (struct sym_fns *); +extern void add_symtab_fns (const struct sym_fns *); /* This enum encodes bit-flags passed as ADD_FLAGS parameter to syms_from_objfile, symbol_file_add, etc. */ @@ -406,7 +409,11 @@ enum symfile_add_flags SYMFILE_MAINLINE = 1 << 2, /* Do not call breakpoint_re_set when adding this symbol file. */ - SYMFILE_DEFER_BP_RESET = 1 << 3 + SYMFILE_DEFER_BP_RESET = 1 << 3, + + /* Do not immediately read symbols for this file. By default, + symbols are read when the objfile is created. */ + SYMFILE_NO_READ = 1 << 4 }; extern void syms_from_objfile (struct objfile *, @@ -446,21 +453,16 @@ extern struct section_addr_info extern void free_section_addr_info (struct section_addr_info *); -extern struct partial_symtab *start_psymtab_common (struct objfile *, - struct section_offsets *, - const char *, CORE_ADDR, - struct partial_symbol **, - struct partial_symbol **); - /* Make a copy of the string at PTR with SIZE characters in the symbol obstack (and add a null character at the end in the copy). Returns the address of the copy. */ extern char *obsavestring (const char *, int, struct obstack *); -/* Concatenate NULL terminated variable argument list of `const char *' strings; - return the new string. Space is found in the OBSTACKP. Argument list must - be terminated by a sentinel expression `(char *) NULL'. */ +/* Concatenate NULL terminated variable argument list of `const char + *' strings; return the new string. Space is found in the OBSTACKP. + Argument list must be terminated by a sentinel expression `(char *) + NULL'. */ extern char *obconcat (struct obstack *obstackp, ...) ATTRIBUTE_SENTINEL; @@ -478,24 +480,10 @@ extern char *obconcat (struct obstack *obstackp, ...) ATTRIBUTE_SENTINEL; extern int auto_solib_add; -/* For systems that support it, a threshold size in megabytes. If - automatically adding a new library's symbol table to those already - known to the debugger would cause the total shared library symbol - size to exceed this threshhold, then the shlib's symbols are not - added. The threshold is ignored if the user explicitly asks for a - shlib to be added, such as when using the "sharedlibrary" command. */ - -extern int auto_solib_limit; - /* From symfile.c */ extern void set_initial_language (void); -extern struct partial_symtab *allocate_psymtab (const char *, - struct objfile *); - -extern void discard_psymtab (struct partial_symtab *); - extern void find_lowest_section (bfd *, asection *, void *); extern bfd *symfile_bfd_open (char *); @@ -566,6 +554,7 @@ extern struct cleanup *increment_reading_symtab (void); extern int dwarf2_has_info (struct objfile *); +extern int dwarf2_initialize_objfile (struct objfile *); extern void dwarf2_build_psymtabs (struct objfile *); extern void dwarf2_build_frame_info (struct objfile *); diff --git a/contrib/gdb-7/gdb/symmisc.c b/contrib/gdb-7/gdb/symmisc.c index 62e6b97263..66c2f05adb 100644 --- a/contrib/gdb-7/gdb/symmisc.c +++ b/contrib/gdb-7/gdb/symmisc.c @@ -1,8 +1,8 @@ /* Do various things to symbol tables (other than lookup), for GDB. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -23,6 +23,7 @@ #include "symtab.h" #include "gdbtypes.h" #include "bfd.h" +#include "filenames.h" #include "symfile.h" #include "objfiles.h" #include "breakpoint.h" @@ -109,7 +110,7 @@ free_symtab (struct symtab *s) if (s->free_func != NULL) s->free_func (s); - /* Free source-related stuff */ + /* Free source-related stuff. */ if (s->line_charpos != NULL) xfree (s->line_charpos); if (s->fullname != NULL) @@ -130,7 +131,8 @@ print_symbol_bcache_statistics (void) ALL_PSPACE_OBJFILES (pspace, objfile) { printf_filtered (_("Byte cache statistics for '%s':\n"), objfile->name); - print_bcache_statistics (objfile->psymbol_cache, "partial symbol cache"); + print_bcache_statistics (psymbol_bcache_get_bcache (objfile->psymbol_cache), + "partial symbol cache"); print_bcache_statistics (objfile->macro_cache, "preprocessor macro cache"); print_bcache_statistics (objfile->filename_cache, "file name cache"); } @@ -188,7 +190,8 @@ print_objfile_statistics (void) printf_filtered (_(" Total memory used for objfile obstack: %d\n"), obstack_memory_used (&objfile->objfile_obstack)); printf_filtered (_(" Total memory used for psymbol cache: %d\n"), - bcache_memory_used (objfile->psymbol_cache)); + bcache_memory_used (psymbol_bcache_get_bcache + (objfile->psymbol_cache))); printf_filtered (_(" Total memory used for macro cache: %d\n"), bcache_memory_used (objfile->macro_cache)); printf_filtered (_(" Total memory used for file name cache: %d\n"), @@ -262,6 +265,9 @@ dump_msymbols (struct objfile *objfile, struct ui_file *outfile) case mst_text: ms_type = 'T'; break; + case mst_text_gnu_ifunc: + ms_type = 'i'; + break; case mst_solib_trampoline: ms_type = 'S'; break; @@ -333,7 +339,8 @@ dump_symtab_1 (struct objfile *objfile, struct symtab *symtab, fprintf_filtered (outfile, "Read from object file %s (", objfile->name); gdb_print_host_address (objfile, outfile); fprintf_filtered (outfile, ")\n"); - fprintf_filtered (outfile, "Language: %s\n", language_str (symtab->language)); + fprintf_filtered (outfile, "Language: %s\n", + language_str (symtab->language)); /* First print the line table. */ l = LINETABLE (symtab); @@ -349,7 +356,7 @@ dump_symtab_1 (struct objfile *objfile, struct symtab *symtab, } } /* Now print the block info, but only for primary symtabs since we will - print lots of duplicate info otherwise. */ + print lots of duplicate info otherwise. */ if (symtab->primary) { fprintf_filtered (outfile, "\nBlockvector:\n\n"); @@ -446,8 +453,8 @@ maintenance_print_symbols (char *args, int from_tty) if (args == NULL) { - error (_("\ -Arguments missing: an output file name and an optional symbol file name")); + error (_("Arguments missing: an output file name " + "and an optional symbol file name")); } argv = gdb_buildargv (args); cleanups = make_cleanup_freeargv (argv); @@ -455,7 +462,7 @@ Arguments missing: an output file name and an optional symbol file name")); if (argv[0] != NULL) { filename = argv[0]; - /* If a second arg is supplied, it is a source file name to match on */ + /* If a second arg is supplied, it is a source file name to match on. */ if (argv[1] != NULL) { symname = argv[1]; @@ -472,7 +479,7 @@ Arguments missing: an output file name and an optional symbol file name")); immediate_quit++; ALL_SYMTABS (objfile, s) - if (symname == NULL || strcmp (symname, s->filename) == 0) + if (symname == NULL || filename_cmp (symname, s->filename) == 0) dump_symtab (objfile, s, outfile); immediate_quit--; do_cleanups (cleanups); @@ -666,7 +673,8 @@ maintenance_print_msymbols (char *args, int from_tty) if (args == NULL) { - error (_("print-msymbols takes an output file name and optional symbol file name")); + error (_("print-msymbols takes an output file " + "name and optional symbol file name")); } argv = gdb_buildargv (args); cleanups = make_cleanup_freeargv (argv); @@ -674,7 +682,7 @@ maintenance_print_msymbols (char *args, int from_tty) if (argv[0] != NULL) { filename = argv[0]; - /* If a second arg is supplied, it is a source file name to match on */ + /* If a second arg is supplied, it is a source file name to match on. */ if (argv[1] != NULL) { symname = xfullpath (argv[1]); @@ -695,8 +703,8 @@ maintenance_print_msymbols (char *args, int from_tty) immediate_quit++; ALL_PSPACES (pspace) ALL_PSPACE_OBJFILES (pspace, objfile) - if (symname == NULL - || (!stat (objfile->name, &obj_st) && sym_st.st_ino == obj_st.st_ino)) + if (symname == NULL || (!stat (objfile->name, &obj_st) + && sym_st.st_ino == obj_st.st_ino)) dump_msymbols (objfile, outfile); immediate_quit--; fprintf_filtered (outfile, "\n\n"); @@ -762,12 +770,15 @@ maintenance_info_symtabs (char *regexp, int from_tty) symtab->dirname ? symtab->dirname : "(null)"); printf_filtered (" fullname %s\n", symtab->fullname ? symtab->fullname : "(null)"); - printf_filtered (" blockvector ((struct blockvector *) %s)%s\n", + printf_filtered (" " + "blockvector ((struct blockvector *) %s)%s\n", host_address_to_string (symtab->blockvector), symtab->primary ? " (primary)" : ""); - printf_filtered (" linetable ((struct linetable *) %s)\n", + printf_filtered (" " + "linetable ((struct linetable *) %s)\n", host_address_to_string (symtab->linetable)); - printf_filtered (" debugformat %s\n", symtab->debugformat); + printf_filtered (" debugformat %s\n", + symtab->debugformat); printf_filtered (" }\n"); } } @@ -793,7 +804,7 @@ block_depth (struct block *block) } -/* Do early runtime initializations. */ +/* Do early runtime initializations. */ void _initialize_symmisc (void) { diff --git a/contrib/gdb-7/gdb/symtab.c b/contrib/gdb-7/gdb/symtab.c index 2c4c9e495e..4c1a78a153 100644 --- a/contrib/gdb-7/gdb/symtab.c +++ b/contrib/gdb-7/gdb/symtab.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -147,7 +147,7 @@ multiple_symbols_select_mode (void) /* Block in which the most recently searched-for symbol was found. Might be better to make this a parameter to lookup_symbol and - value_of_this. */ + value_of_this. */ const struct block *block_found; @@ -176,7 +176,7 @@ lookup_symtab (const char *name) got_symtab: - /* First, search for an exact match */ + /* First, search for an exact match. */ ALL_SYMTABS (objfile, s) { @@ -215,7 +215,7 @@ got_symtab: } } - /* Now, search for a matching tail (only if name doesn't have any dirs) */ + /* Now, search for a matching tail (only if name doesn't have any dirs). */ if (lbasename (name) == name) ALL_SYMTABS (objfile, s) @@ -251,14 +251,14 @@ got_symtab: been created. So, we need to run through the symtabs again in order to find the file. XXX - This is a crock, and should be fixed inside of the the - symbol parsing routines. */ + symbol parsing routines. */ goto got_symtab; } /* Mangle a GDB method stub type. This actually reassembles the pieces of the full method name, which consist of the class name (from T), the unadorned method name from METHOD_ID, and the signature for the specific overload, - specified by SIGNATURE_ID. Note that this function is g++ specific. */ + specified by SIGNATURE_ID. Note that this function is g++ specific. */ char * gdb_mangle_name (struct type *type, int method_id, int signature_id) @@ -291,8 +291,8 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) is_full_physname_constructor = is_constructor_name (physname); - is_constructor = - is_full_physname_constructor || (newname && strcmp (field_name, newname) == 0); + is_constructor = is_full_physname_constructor + || (newname && strcmp (field_name, newname) == 0); if (!is_destructor) is_destructor = (strncmp (physname, "__dt", 4) == 0); @@ -332,7 +332,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) strcat (mangled_name, buf); /* If the class doesn't have a name, i.e. newname NULL, then we just mangle it using 0 for the length of the class. Thus it gets mangled - as something starting with `::' rather than `classname::'. */ + as something starting with `::' rather than `classname::'. */ if (newname != NULL) strcat (mangled_name, newname); @@ -340,22 +340,74 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) return (mangled_name); } +/* Initialize the cplus_specific structure. 'cplus_specific' should + only be allocated for use with cplus symbols. */ + +static void +symbol_init_cplus_specific (struct general_symbol_info *gsymbol, + struct objfile *objfile) +{ + /* A language_specific structure should not have been previously + initialized. */ + gdb_assert (gsymbol->language_specific.cplus_specific == NULL); + gdb_assert (objfile != NULL); + + gsymbol->language_specific.cplus_specific = + OBSTACK_ZALLOC (&objfile->objfile_obstack, struct cplus_specific); +} + +/* Set the demangled name of GSYMBOL to NAME. NAME must be already + correctly allocated. For C++ symbols a cplus_specific struct is + allocated so OBJFILE must not be NULL. If this is a non C++ symbol + OBJFILE can be NULL. */ +void +symbol_set_demangled_name (struct general_symbol_info *gsymbol, + char *name, + struct objfile *objfile) +{ + if (gsymbol->language == language_cplus) + { + if (gsymbol->language_specific.cplus_specific == NULL) + symbol_init_cplus_specific (gsymbol, objfile); + + gsymbol->language_specific.cplus_specific->demangled_name = name; + } + else + gsymbol->language_specific.mangled_lang.demangled_name = name; +} + +/* Return the demangled name of GSYMBOL. */ +char * +symbol_get_demangled_name (const struct general_symbol_info *gsymbol) +{ + if (gsymbol->language == language_cplus) + { + if (gsymbol->language_specific.cplus_specific != NULL) + return gsymbol->language_specific.cplus_specific->demangled_name; + else + return NULL; + } + else + return gsymbol->language_specific.mangled_lang.demangled_name; +} + /* Initialize the language dependent portion of a symbol - depending upon the language for the symbol. */ + depending upon the language for the symbol. */ void -symbol_init_language_specific (struct general_symbol_info *gsymbol, - enum language language) +symbol_set_language (struct general_symbol_info *gsymbol, + enum language language) { gsymbol->language = language; - if (gsymbol->language == language_cplus - || gsymbol->language == language_d + if (gsymbol->language == language_d || gsymbol->language == language_java || gsymbol->language == language_objc || gsymbol->language == language_fortran) { - gsymbol->language_specific.cplus_specific.demangled_name = NULL; + symbol_set_demangled_name (gsymbol, NULL, NULL); } + else if (gsymbol->language == language_cplus) + gsymbol->language_specific.cplus_specific = NULL; else { memset (&gsymbol->language_specific, 0, @@ -438,7 +490,7 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol, || gsymbol->language == language_auto) { demangled = - cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); + cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI); if (demangled != NULL) { gsymbol->language = language_cplus; @@ -537,7 +589,7 @@ symbol_set_names (struct general_symbol_info *gsymbol, memcpy (gsymbol->name, linkage_name, len); gsymbol->name[len] = '\0'; } - gsymbol->language_specific.cplus_specific.demangled_name = NULL; + symbol_set_demangled_name (gsymbol, NULL, NULL); return; } @@ -633,10 +685,9 @@ symbol_set_names (struct general_symbol_info *gsymbol, gsymbol->name = (*slot)->mangled + lookup_len - len; if ((*slot)->demangled[0] != '\0') - gsymbol->language_specific.cplus_specific.demangled_name - = (*slot)->demangled; + symbol_set_demangled_name (gsymbol, (*slot)->demangled, objfile); else - gsymbol->language_specific.cplus_specific.demangled_name = NULL; + symbol_set_demangled_name (gsymbol, NULL, objfile); } /* Return the source code name of a symbol. In languages where @@ -652,12 +703,12 @@ symbol_natural_name (const struct general_symbol_info *gsymbol) case language_java: case language_objc: case language_fortran: - if (gsymbol->language_specific.cplus_specific.demangled_name != NULL) - return gsymbol->language_specific.cplus_specific.demangled_name; + if (symbol_get_demangled_name (gsymbol) != NULL) + return symbol_get_demangled_name (gsymbol); break; case language_ada: - if (gsymbol->language_specific.cplus_specific.demangled_name != NULL) - return gsymbol->language_specific.cplus_specific.demangled_name; + if (symbol_get_demangled_name (gsymbol) != NULL) + return symbol_get_demangled_name (gsymbol); else return ada_decode_symbol (gsymbol); break; @@ -668,7 +719,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol) } /* Return the demangled name for a symbol based on the language for - that symbol. If no demangled name exists, return NULL. */ + that symbol. If no demangled name exists, return NULL. */ char * symbol_demangled_name (const struct general_symbol_info *gsymbol) { @@ -679,12 +730,12 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol) case language_java: case language_objc: case language_fortran: - if (gsymbol->language_specific.cplus_specific.demangled_name != NULL) - return gsymbol->language_specific.cplus_specific.demangled_name; + if (symbol_get_demangled_name (gsymbol) != NULL) + return symbol_get_demangled_name (gsymbol); break; case language_ada: - if (gsymbol->language_specific.cplus_specific.demangled_name != NULL) - return gsymbol->language_specific.cplus_specific.demangled_name; + if (symbol_get_demangled_name (gsymbol) != NULL) + return symbol_get_demangled_name (gsymbol); else return ada_decode_symbol (gsymbol); break; @@ -697,7 +748,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol) /* Return the search name of a symbol---generally the demangled or linkage name of the symbol, depending on how it will be searched for. If there is no distinct demangled name, then returns the same value - (same pointer) as SYMBOL_LINKAGE_NAME. */ + (same pointer) as SYMBOL_LINKAGE_NAME. */ char * symbol_search_name (const struct general_symbol_info *gsymbol) { @@ -944,7 +995,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile) NAME is a field of the current implied argument `this'. If so set *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. BLOCK_FOUND is set to the block in which NAME is found (in the case of - a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ + a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ /* This function has a bunch of loops in it and it would seem to be attractive to put in some QUIT's (though I'm not really sure @@ -969,7 +1020,7 @@ lookup_symbol_in_language (const char *name, const struct block *block, modified_name = name; /* If we are using C++, D, or Java, demangle the name before doing a - lookup, so we can always binary search. */ + lookup, so we can always binary search. */ if (lang == language_cplus) { demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); @@ -1129,7 +1180,7 @@ lookup_symbol_aux (const char *name, const struct block *block, /* Search all static file-level symbols for NAME from DOMAIN. Do the symtabs first, then check the psymtabs. If a psymtab indicates the existence of the desired name as a file-level static, then do psymtab-to-symtab conversion on - the fly and return the found symbol. */ + the fly and return the found symbol. */ struct symbol * lookup_static_symbol_aux (const char *name, const domain_enum domain) @@ -1176,12 +1227,8 @@ lookup_symbol_aux_local (const char *name, const struct block *block, if (language == language_cplus || language == language_fortran) { - sym = cp_lookup_symbol_imports (scope, - name, - block, - domain, - 1, - 1); + sym = cp_lookup_symbol_imports_or_template (scope, name, block, + domain); if (sym != NULL) return sym; } @@ -1295,16 +1342,25 @@ lookup_symbol_aux_symtabs (int block_index, const char *name, const struct block *block; struct symtab *s; - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_OBJFILES (objfile) { - bv = BLOCKVECTOR (s); - block = BLOCKVECTOR_BLOCK (bv, block_index); - sym = lookup_block_symbol (block, name, domain); - if (sym) - { - block_found = block; - return fixup_symbol_section (sym, objfile); - } + if (objfile->sf) + objfile->sf->qf->pre_expand_symtabs_matching (objfile, + block_index, + name, domain); + + ALL_OBJFILE_SYMTABS (objfile, s) + if (s->primary) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, block_index); + sym = lookup_block_symbol (block, name, domain); + if (sym) + { + block_found = block; + return fixup_symbol_section (sym, objfile); + } + } } return NULL; @@ -1335,7 +1391,7 @@ lookup_symbol_aux_quick (struct objfile *objfile, int kind, { /* This shouldn't be necessary, but as a last resort try looking in the statics even though the psymtab claimed - the symbol was global, or vice-versa. It's possible + the symbol was global, or vice-versa. It's possible that the psymtab gets it wrong in some cases. */ /* FIXME: carlton/2002-09-30: Should we really do that? @@ -1349,7 +1405,10 @@ lookup_symbol_aux_quick (struct objfile *objfile, int kind, STATIC_BLOCK : GLOBAL_BLOCK); sym = lookup_block_symbol (block, name, domain); if (!sym) - error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s)."), + error (_("\ +Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s)."), kind == GLOBAL_BLOCK ? "global" : "static", name, symtab->filename, name, name); } @@ -1508,14 +1567,15 @@ basic_lookup_transparent_type_quick (struct objfile *objfile, int kind, /* This shouldn't be necessary, but as a last resort * try looking in the 'other kind' even though the psymtab - * claimed the symbol was one thing. It's possible that + * claimed the symbol was one thing. It's possible that * the psymtab gets it wrong in some cases. */ block = BLOCKVECTOR_BLOCK (bv, other_kind); sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); if (!sym) - /* FIXME; error is wrong in one case */ - error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\ + /* FIXME; error is wrong in one case. */ + error (_("\ +Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\ %s may be an inlined function, or may be a template function\n\ (if a template, try specifying an instantiation: %s)."), name, symtab->filename, name, name); @@ -1543,19 +1603,28 @@ basic_lookup_transparent_type (const char *name) struct type *t; /* Now search all the global symbols. Do the symtab's first, then - check the psymtab's. If a psymtab indicates the existence + check the psymtab's. If a psymtab indicates the existence of the desired name as a global, then do psymtab-to-symtab conversion on the fly and return the found symbol. */ - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_OBJFILES (objfile) { - bv = BLOCKVECTOR (s); - block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); - sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); - if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) - { - return SYMBOL_TYPE (sym); - } + if (objfile->sf) + objfile->sf->qf->pre_expand_symtabs_matching (objfile, + GLOBAL_BLOCK, + name, STRUCT_DOMAIN); + + ALL_OBJFILE_SYMTABS (objfile, s) + if (s->primary) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } + } } ALL_OBJFILES (objfile) @@ -1568,19 +1637,25 @@ basic_lookup_transparent_type (const char *name) /* Now search the static file-level symbols. Not strictly correct, but more useful than an error. Do the symtab's first, then - check the psymtab's. If a psymtab indicates the existence + check the psymtab's. If a psymtab indicates the existence of the desired name as a file-level static, then do psymtab-to-symtab - conversion on the fly and return the found symbol. - */ + conversion on the fly and return the found symbol. */ - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_OBJFILES (objfile) { - bv = BLOCKVECTOR (s); - block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); - sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); - if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + if (objfile->sf) + objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK, + name, STRUCT_DOMAIN); + + ALL_OBJFILE_SYMTABS (objfile, s) { - return SYMBOL_TYPE (sym); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_DOMAIN); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } } } @@ -1595,18 +1670,20 @@ basic_lookup_transparent_type (const char *name) } -/* Find the name of the file containing main(). */ +/* Find the name of the file containing main(). */ /* FIXME: What about languages without main() or specially linked - executables that have no main() ? */ + executables that have no main() ? */ -char * +const char * find_main_filename (void) { struct objfile *objfile; - char *result, *name = main_name (); + char *name = main_name (); ALL_OBJFILES (objfile) { + const char *result; + if (!objfile->sf) continue; result = objfile->sf->qf->find_symbol_file (objfile, name); @@ -1625,8 +1702,7 @@ find_main_filename (void) binary search terminates, we drop through and do a straight linear search on the symbols. Each symbol which is marked as being a ObjC/C++ symbol (language_cplus or language_objc set) has both the encoded and - non-encoded names tested for a match. -*/ + non-encoded names tested for a match. */ struct symbol * lookup_block_symbol (const struct block *block, const char *name, @@ -1671,12 +1747,12 @@ lookup_block_symbol (const struct block *block, const char *name, } } } - return (sym_found); /* Will be NULL if not found. */ + return (sym_found); /* Will be NULL if not found. */ } } /* Find the symtab associated with PC and SECTION. Look through the - psymtabs and read in another symtab if necessary. */ + psymtabs and read in another symtab if necessary. */ struct symtab * find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) @@ -1713,7 +1789,7 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) 0x1000-0x4000, but for address 0x2345 we want to return symtab b. This happens for native ecoff format, where code from included files - gets its own symtab. The symtab for the included file should have + gets its own symtab. The symtab for the included file should have been read in already via the dependency mechanism. It might be swifter to create several symtabs with the same name like xcoff does (I'm not sure). @@ -1736,7 +1812,7 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) and we simply return its corresponding symtab. */ /* In order to better support objfiles that contain both stabs and coff debugging info, we continue on if a psymtab - can't be found. */ + can't be found. */ if ((objfile->flags & OBJF_REORDERED) && objfile->sf) { struct symtab *result; @@ -1761,7 +1837,8 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) break; } if (sym == NULL) - continue; /* no symbol in this symtab matches section */ + continue; /* No symbol in this symtab matches + section. */ } distance = BLOCK_END (b) - BLOCK_START (b); best_s = s; @@ -1788,8 +1865,8 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) return NULL; } -/* Find the symtab associated with PC. Look through the psymtabs and - read in another symtab if necessary. Backward compatibility, no section */ +/* Find the symtab associated with PC. Look through the psymtabs and read + in another symtab if necessary. Backward compatibility, no section. */ struct symtab * find_pc_symtab (CORE_ADDR pc) @@ -1827,6 +1904,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) struct blockvector *bv; struct minimal_symbol *msymbol; struct minimal_symbol *mfunsym; + struct objfile *objfile; /* Info on best line seen so far, and where it starts, and its file. */ @@ -1868,10 +1946,10 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) /* elz: added this because this function returned the wrong information if the pc belongs to a stub (import/export) - to call a shlib function. This stub would be anywhere between + to call a shlib function. This stub would be anywhere between two functions in the target, and the line info was erroneously - taken to be the one of the line before the pc. - */ + taken to be the one of the line before the pc. */ + /* RT: Further explanation: * We have stubs (trampolines) inserted between procedures. @@ -1880,7 +1958,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) * exists in the main image. * * In the minimal symbol table, we have a bunch of symbols - * sorted by start address. The stubs are marked as "trampoline", + * sorted by start address. The stubs are marked as "trampoline", * the others appear as text. E.g.: * * Minimal symbol table for main image @@ -1900,13 +1978,13 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) * * Assumptions being made about the minimal symbol table: * 1. lookup_minimal_symbol_by_pc() will return a trampoline only - * if we're really in the trampoline. If we're beyond it (say + * if we're really in the trampoline.s If we're beyond it (say * we're in "foo" in the above example), it'll have a closer * symbol (the "foo" text symbol for example) and will not * return the trampoline. * 2. lookup_minimal_symbol_text() will find a real text symbol * corresponding to the trampoline, and whose address will - * be different than the trampoline address. I put in a sanity + * be different than the trampoline address. I put in a sanity * check for the address being the same, to avoid an * infinite recursion. */ @@ -1925,13 +2003,18 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) * In the above situation, the shared lib is not loaded yet, * so of course we can't find the real func/line info, * but the "break" still works, and the warning is annoying. - * So I commented out the warning. RT */ - /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_LINKAGE_NAME (msymbol)) */ ; + * So I commented out the warning. RT */ + /* warning ("In stub for %s; unable to find real function/line info", + SYMBOL_LINKAGE_NAME (msymbol)); */ + ; /* fall through */ - else if (SYMBOL_VALUE_ADDRESS (mfunsym) == SYMBOL_VALUE_ADDRESS (msymbol)) + else if (SYMBOL_VALUE_ADDRESS (mfunsym) + == SYMBOL_VALUE_ADDRESS (msymbol)) /* Avoid infinite recursion */ - /* See above comment about why warning is commented out */ - /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_LINKAGE_NAME (msymbol)) */ ; + /* See above comment about why warning is commented out. */ + /* warning ("In stub for %s; unable to find real function/line info", + SYMBOL_LINKAGE_NAME (msymbol)); */ + ; /* fall through */ else return find_pc_line (SYMBOL_VALUE_ADDRESS (mfunsym), 0); @@ -1941,7 +2024,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) s = find_pc_sect_symtab (pc, section); if (!s) { - /* if no symbol information, return previous pc */ + /* If no symbol information, return previous pc. */ if (notcurrent) pc++; val.pc = pc; @@ -1949,13 +2032,17 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) } bv = BLOCKVECTOR (s); + objfile = s->objfile; /* Look at all the symtabs that share this blockvector. They all have the same apriori range, that we found was right; but they have different line tables. */ - for (; s && BLOCKVECTOR (s) == bv; s = s->next) + ALL_OBJFILE_SYMTABS (objfile, s) { + if (BLOCKVECTOR (s) != bv) + continue; + /* Find the best line in this symtab. */ l = LINETABLE (s); if (!l) @@ -1971,7 +2058,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) } prev = NULL; - item = l->item; /* Get first line info */ + item = l->item; /* Get first line info. */ /* Is this file's first line closer than the first lines of other files? If so, record this file, and its first line, as best alternate. */ @@ -2031,7 +2118,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) { /* If our best fit is in a range of PC's for which no line number info is available (line number is zero) then we didn't - find any valid line information. */ + find any valid line information. */ val.pc = pc; } else @@ -2050,7 +2137,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) return val; } -/* Backward compatibility (no section) */ +/* Backward compatibility (no section). */ struct symtab_and_line find_pc_line (CORE_ADDR pc, int notcurrent) @@ -2372,12 +2459,13 @@ skip_prologue_sal (struct symtab_and_line *sal) struct symbol *sym; struct symtab_and_line start_sal; struct cleanup *old_chain; - CORE_ADDR pc; + CORE_ADDR pc, saved_pc; struct obj_section *section; const char *name; struct objfile *objfile; struct gdbarch *gdbarch; struct block *b, *function_block; + int force_skip, skip; /* Do not change the SAL is PC was specified explicitly. */ if (sal->explicit_pc) @@ -2415,46 +2503,69 @@ skip_prologue_sal (struct symtab_and_line *sal) gdbarch = get_objfile_arch (objfile); - /* If the function is in an unmapped overlay, use its unmapped LMA address, - so that gdbarch_skip_prologue has something unique to work on. */ - if (section_is_overlay (section) && !section_is_mapped (section)) - pc = overlay_unmapped_address (pc, section); + /* Process the prologue in two passes. In the first pass try to skip the + prologue (SKIP is true) and verify there is a real need for it (indicated + by FORCE_SKIP). If no such reason was found run a second pass where the + prologue is not skipped (SKIP is false). */ - /* Skip "first line" of function (which is actually its prologue). */ - pc += gdbarch_deprecated_function_start_offset (gdbarch); - pc = gdbarch_skip_prologue (gdbarch, pc); + skip = 1; + force_skip = 1; - /* For overlays, map pc back into its mapped VMA range. */ - pc = overlay_mapped_address (pc, section); + /* Be conservative - allow direct PC (without skipping prologue) only if we + have proven the CU (Compilation Unit) supports it. sal->SYMTAB does not + have to be set by the caller so we use SYM instead. */ + if (sym && SYMBOL_SYMTAB (sym)->locations_valid) + force_skip = 0; - /* Calculate line number. */ - start_sal = find_pc_sect_line (pc, section, 0); - - /* Check if gdbarch_skip_prologue left us in mid-line, and the next - line is still part of the same function. */ - if (start_sal.pc != pc - && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end - && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) - : (lookup_minimal_symbol_by_pc_section (start_sal.end, section) - == lookup_minimal_symbol_by_pc_section (pc, section)))) + saved_pc = pc; + do { - /* First pc of next line */ - pc = start_sal.end; - /* Recalculate the line number (might not be N+1). */ - start_sal = find_pc_sect_line (pc, section, 0); - } + pc = saved_pc; - /* On targets with executable formats that don't have a concept of - constructors (ELF with .init has, PE doesn't), gcc emits a call - to `__main' in `main' between the prologue and before user - code. */ - if (gdbarch_skip_main_prologue_p (gdbarch) - && name && strcmp (name, "main") == 0) - { - pc = gdbarch_skip_main_prologue (gdbarch, pc); - /* Recalculate the line number (might not be N+1). */ + /* If the function is in an unmapped overlay, use its unmapped LMA address, + so that gdbarch_skip_prologue has something unique to work on. */ + if (section_is_overlay (section) && !section_is_mapped (section)) + pc = overlay_unmapped_address (pc, section); + + /* Skip "first line" of function (which is actually its prologue). */ + pc += gdbarch_deprecated_function_start_offset (gdbarch); + if (skip) + pc = gdbarch_skip_prologue (gdbarch, pc); + + /* For overlays, map pc back into its mapped VMA range. */ + pc = overlay_mapped_address (pc, section); + + /* Calculate line number. */ start_sal = find_pc_sect_line (pc, section, 0); + + /* Check if gdbarch_skip_prologue left us in mid-line, and the next + line is still part of the same function. */ + if (skip && start_sal.pc != pc + && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end + && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + : (lookup_minimal_symbol_by_pc_section (start_sal.end, section) + == lookup_minimal_symbol_by_pc_section (pc, section)))) + { + /* First pc of next line */ + pc = start_sal.end; + /* Recalculate the line number (might not be N+1). */ + start_sal = find_pc_sect_line (pc, section, 0); + } + + /* On targets with executable formats that don't have a concept of + constructors (ELF with .init has, PE doesn't), gcc emits a call + to `__main' in `main' between the prologue and before user + code. */ + if (gdbarch_skip_main_prologue_p (gdbarch) + && name && strcmp (name, "main") == 0) + { + pc = gdbarch_skip_main_prologue (gdbarch, pc); + /* Recalculate the line number (might not be N+1). */ + start_sal = find_pc_sect_line (pc, section, 0); + force_skip = 1; + } } + while (!force_skip && skip--); /* If we still don't have a valid source line, try to find the first PC in the lineinfo table that belongs to the same function. This @@ -2464,7 +2575,7 @@ skip_prologue_sal (struct symtab_and_line *sal) the case with the DJGPP target using "gcc -gcoff" when the compiler inserted code after the prologue to make sure the stack is aligned. */ - if (sym && start_sal.symtab == NULL) + if (!force_skip && sym && start_sal.symtab == NULL) { pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym)); /* Recalculate the line number. */ @@ -2531,7 +2642,7 @@ operator_chars (char *p, char **end) while (*p == ' ' || *p == '\t') p++; - /* Recognize 'operator TYPENAME'. */ + /* Recognize 'operator TYPENAME'. */ if (isalpha (*p) || *p == '_' || *p == '$') { @@ -2549,7 +2660,7 @@ operator_chars (char *p, char **end) case '\\': /* regexp quoting */ if (p[1] == '*') { - if (p[2] == '=') /* 'operator\*=' */ + if (p[2] == '=') /* 'operator\*=' */ *end = p + 3; else /* 'operator\*' */ *end = p + 2; @@ -2558,7 +2669,8 @@ operator_chars (char *p, char **end) else if (p[1] == '[') { if (p[2] == ']') - error (_("mismatched quoting on brackets, try 'operator\\[\\]'")); + error (_("mismatched quoting on brackets, " + "try 'operator\\[\\]'")); else if (p[2] == '\\' && p[3] == ']') { *end = p + 4; /* 'operator\[\]' */ @@ -2569,7 +2681,7 @@ operator_chars (char *p, char **end) } else { - /* Gratuitous qoute: skip it and move on. */ + /* Gratuitous qoute: skip it and move on. */ p++; continue; } @@ -2593,7 +2705,7 @@ operator_chars (char *p, char **end) case '|': if (p[0] == '-' && p[1] == '>') { - /* Struct pointer member operator 'operator->'. */ + /* Struct pointer member operator 'operator->'. */ if (p[2] == '*') { *end = p + 3; /* 'operator->*' */ @@ -2621,17 +2733,20 @@ operator_chars (char *p, char **end) return p; case '(': if (p[1] != ')') - error (_("`operator ()' must be specified without whitespace in `()'")); + error (_("`operator ()' must be specified " + "without whitespace in `()'")); *end = p + 2; return p; case '?': if (p[1] != ':') - error (_("`operator ?:' must be specified without whitespace in `?:'")); + error (_("`operator ?:' must be specified " + "without whitespace in `?:'")); *end = p + 2; return p; case '[': if (p[1] != ']') - error (_("`operator []' must be specified without whitespace in `[]'")); + error (_("`operator []' must be specified " + "without whitespace in `[]'")); *end = p + 2; return p; default: @@ -2670,7 +2785,7 @@ filename_seen (const char *file, int add, int *first) /* Is FILE in tab? */ for (p = tab; p < tab + tab_cur_size; p++) - if (strcmp (*p, file) == 0) + if (filename_cmp (*p, file) == 0) return 1; /* No; maybe add it to tab. */ @@ -2725,7 +2840,7 @@ output_source_filename (const char *name, int *first) /* A callback for map_partial_symbol_filenames. */ static void -output_partial_symbol_filename (const char *fullname, const char *filename, +output_partial_symbol_filename (const char *filename, const char *fullname, void *data) { output_source_filename (fullname ? fullname : filename, data); @@ -2754,7 +2869,8 @@ sources_info (char *ignore, int from_tty) } printf_filtered ("\n\n"); - printf_filtered ("Source files for which symbols will be read in on demand:\n\n"); + printf_filtered ("Source files for which symbols " + "will be read in on demand:\n\n"); first = 1; map_partial_symbol_filenames (output_partial_symbol_filename, &first); @@ -2770,7 +2886,7 @@ file_matches (const char *file, char *files[], int nfiles) { for (i = 0; i < nfiles; i++) { - if (strcmp (files[i], lbasename (file)) == 0) + if (filename_cmp (files[i], lbasename (file)) == 0) return 1; } } @@ -2779,7 +2895,7 @@ file_matches (const char *file, char *files[], int nfiles) return 0; } -/* Free any memory associated with a search. */ +/* Free any memory associated with a search. */ void free_search_symbols (struct symbol_search *symbols) { @@ -2887,12 +3003,13 @@ search_symbols_name_matches (const char *symname, void *user_data) TYPES_DOMAIN - search all type names VARIABLES_DOMAIN - search all symbols, excluding functions, type names, and constants (enums) + ALL_DOMAIN - an internal error for this function free_search_symbols should be called when *MATCHES is no longer needed. The results are sorted locally; each symtab's global and static blocks are - separately alphabetized. - */ + separately alphabetized. */ + void search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], struct symbol_search **matches) @@ -2907,14 +3024,14 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], struct minimal_symbol *msymbol; char *val; int found_misc = 0; - static enum minimal_symbol_type types[] + static const enum minimal_symbol_type types[] = {mst_data, mst_text, mst_abs, mst_unknown}; - static enum minimal_symbol_type types2[] + static const enum minimal_symbol_type types2[] = {mst_bss, mst_file_text, mst_abs, mst_unknown}; - static enum minimal_symbol_type types3[] + static const enum minimal_symbol_type types3[] = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; - static enum minimal_symbol_type types4[] - = {mst_file_bss, mst_text, mst_abs, mst_unknown}; + static const enum minimal_symbol_type types4[] + = {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown}; enum minimal_symbol_type ourtype; enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; @@ -2925,7 +3042,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], struct cleanup *old_chain = NULL; struct search_symbols_data datum; - if (kind < VARIABLES_DOMAIN) + if (kind < VARIABLES_DOMAIN || kind >= ALL_DOMAIN) error (_("must search on specific domain")); ourtype = types[(int) (kind - VARIABLES_DOMAIN)]; @@ -2941,27 +3058,28 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], /* Make sure spacing is right for C++ operators. This is just a courtesy to make the matching less sensitive to how many spaces the user leaves between 'operator' - and or . */ + and or . */ char *opend; char *opname = operator_chars (regexp, &opend); if (*opname) { - int fix = -1; /* -1 means ok; otherwise number of spaces needed. */ + int fix = -1; /* -1 means ok; otherwise number of + spaces needed. */ if (isalpha (*opname) || *opname == '_' || *opname == '$') { - /* There should 1 space between 'operator' and 'TYPENAME'. */ + /* There should 1 space between 'operator' and 'TYPENAME'. */ if (opname[-1] != ' ' || opname[-2] == ' ') fix = 1; } else { - /* There should 0 spaces between 'operator' and 'OPERATOR'. */ + /* There should 0 spaces between 'operator' and 'OPERATOR'. */ if (opname[-1] == ' ') fix = 0; } - /* If wrong number of spaces, fix it. */ + /* If wrong number of spaces, fix it. */ if (fix >= 0) { char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1); @@ -2977,7 +3095,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], /* Search through the partial symtabs *first* for all symbols matching the regexp. That way we don't have to reproduce all of - the machinery below. */ + the machinery below. */ datum.nfiles = nfiles; datum.files = files; @@ -3002,8 +3120,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], for the function, for variables we have to call lookup_symbol to determine if the variable has debug info. If the lookup fails, set found_misc so that we will rescan to print - any matching symbols without debug info. - */ + any matching symbols without debug info. */ if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN)) { @@ -3065,12 +3182,16 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], e.g., c++ static const members. We only want to skip enums here. */ && !(SYMBOL_CLASS (sym) == LOC_CONST - && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM)) - || (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (sym) == LOC_BLOCK) - || (kind == TYPES_DOMAIN && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))) + && TYPE_CODE (SYMBOL_TYPE (sym)) + == TYPE_CODE_ENUM)) + || (kind == FUNCTIONS_DOMAIN + && SYMBOL_CLASS (sym) == LOC_BLOCK) + || (kind == TYPES_DOMAIN + && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))) { /* match */ - psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); + psr = (struct symbol_search *) + xmalloc (sizeof (struct symbol_search)); psr->block = i; psr->symtab = real_symtab; psr->symbol = sym; @@ -3119,17 +3240,18 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], if (regexp == NULL || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0) { - /* Functions: Look up by address. */ + /* Functions: Look up by address. */ if (kind != FUNCTIONS_DOMAIN || (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))) { - /* Variables/Absolutes: Look up by name */ + /* Variables/Absolutes: Look up by name. */ if (lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol), (struct block *) NULL, VAR_DOMAIN, 0) == NULL) { /* match */ - psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search)); + psr = (struct symbol_search *) + xmalloc (sizeof (struct symbol_search)); psr->block = i; psr->msymbol = msymbol; psr->symtab = NULL; @@ -3157,13 +3279,13 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], /* Helper function for symtab_symbol_info, this function uses the data returned from search_symbols() to print information - regarding the match to gdb_stdout. - */ + regarding the match to gdb_stdout. */ + static void print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym, int block, char *last) { - if (last == NULL || strcmp (last, s->filename) != 0) + if (last == NULL || filename_cmp (last, s->filename) != 0) { fputs_filtered ("\nFile ", gdb_stdout); fputs_filtered (s->filename, gdb_stdout); @@ -3173,11 +3295,11 @@ print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym, if (kind != TYPES_DOMAIN && block == STATIC_BLOCK) printf_filtered ("static "); - /* Typedef that is not a C++ class */ + /* Typedef that is not a C++ class. */ if (kind == TYPES_DOMAIN && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN) typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout); - /* variable, func, or typedef-that-is-c++-class */ + /* variable, func, or typedef-that-is-c++-class. */ else if (kind < TYPES_DOMAIN || (kind == TYPES_DOMAIN && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN)) @@ -3192,8 +3314,8 @@ print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym, } /* This help function for symtab_symbol_info() prints information - for non-debugging symbols to gdb_stdout. - */ + for non-debugging symbols to gdb_stdout. */ + static void print_msymbol_info (struct minimal_symbol *msymbol) { @@ -3212,21 +3334,22 @@ print_msymbol_info (struct minimal_symbol *msymbol) } /* This is the guts of the commands "info functions", "info types", and - "info variables". It calls search_symbols to find all matches and then + "info variables". It calls search_symbols to find all matches and then print_[m]symbol_info to print out some useful information about the - matches. - */ + matches. */ + static void symtab_symbol_info (char *regexp, domain_enum kind, int from_tty) { - static char *classnames[] = {"variable", "function", "type", "method"}; + static const char * const classnames[] = + {"variable", "function", "type", "method"}; struct symbol_search *symbols; struct symbol_search *p; struct cleanup *old_chain; char *last_filename = NULL; int first = 1; - /* must make sure that if we're interrupted, symbols gets freed */ + /* Must make sure that if we're interrupted, symbols gets freed. */ search_symbols (regexp, kind, 0, (char **) NULL, &symbols); old_chain = make_cleanup_free_search_symbols (symbols); @@ -3281,7 +3404,7 @@ types_info (char *regexp, int from_tty) symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty); } -/* Breakpoint all functions matching regular expression. */ +/* Breakpoint all functions matching regular expression. */ void rbreak_command_wrapper (char *regexp, int from_tty) @@ -3305,7 +3428,7 @@ rbreak_command (char *regexp, int from_tty) struct cleanup *old_chain; char *string = NULL; int len = 0; - char **files = NULL; + char **files = NULL, *file_name; int nfiles = 0; if (regexp) @@ -3315,7 +3438,6 @@ rbreak_command (char *regexp, int from_tty) if (colon && *(colon + 1) != ':') { int colon_index; - char * file_name; colon_index = colon - regexp; file_name = alloca (colon_index + 1); @@ -3383,6 +3505,36 @@ rbreak_command (char *regexp, int from_tty) } +/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN. + + Either sym_text[sym_text_len] != '(' and then we search for any + symbol starting with SYM_TEXT text. + + Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to + be terminated at that point. Partial symbol tables do not have parameters + information. */ + +static int +compare_symbol_name (const char *name, const char *sym_text, int sym_text_len) +{ + if (strncmp (name, sym_text, sym_text_len) != 0) + return 0; + + if (sym_text[sym_text_len] == '(') + { + /* User searches for `name(someth...'. Require NAME to be terminated. + Normally psymtabs and gdbindex have no parameter types so '\0' will be + present but accept even parameters presence. In this case this + function is in fact strcmp_iw but whitespace skipping is not supported + for tab completion. */ + + if (name[sym_text_len] != '\0' && name[sym_text_len] != '(') + return 0; + } + + return 1; +} + /* Helper routine for make_symbol_completion_list. */ static int return_val_size; @@ -3395,7 +3547,7 @@ static char **return_val; /* Test to see if the symbol specified by SYMNAME (which is already demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN - characters. If so, add it to the current completion list. */ + characters. If so, add it to the current completion list. */ static void completion_list_add_name (char *symname, char *sym_text, int sym_text_len, @@ -3403,15 +3555,12 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len, { int newsize; - /* clip symbols that cannot match */ - - if (strncmp (symname, sym_text, sym_text_len) != 0) - { - return; - } + /* Clip symbols that cannot match. */ + if (!compare_symbol_name (symname, sym_text, sym_text_len)) + return; /* We have a match for a completion, so add SYMNAME to the current list - of matches. Note that the name is moved to freshly malloc'd space. */ + of matches. Note that the name is moved to freshly malloc'd space. */ { char *new; @@ -3506,7 +3655,7 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol, char *sym_text, } /* Break the non-quoted text based on the characters which are in - symbols. FIXME: This should probably be language-specific. */ + symbols. FIXME: This should probably be language-specific. */ static char * language_search_unquoted_string (char *text, char *p) @@ -3519,12 +3668,12 @@ language_search_unquoted_string (char *text, char *p) { if ((current_language->la_language == language_objc)) { - if (p[-1] == ':') /* might be part of a method name */ + if (p[-1] == ':') /* Might be part of a method name. */ continue; else if (p[-1] == '[' && (p[-2] == '-' || p[-2] == '+')) - p -= 2; /* beginning of a method name */ + p -= 2; /* Beginning of a method name. */ else if (p[-1] == ' ' || p[-1] == '(' || p[-1] == ')') - { /* might be part of a method name */ + { /* Might be part of a method name. */ char *t = p; /* Seeing a ' ' or a '(' is not conclusive evidence @@ -3541,8 +3690,8 @@ language_search_unquoted_string (char *text, char *p) break; if (t[-1] == '[' && (t[-2] == '-' || t[-2] == '+')) - p = t - 2; /* method name detected */ - /* else we leave with p unchanged */ + p = t - 2; /* Method name detected. */ + /* Else we leave with p unchanged. */ } } break; @@ -3570,7 +3719,7 @@ completion_list_add_fields (struct symbol *sym, char *sym_text, } /* Type of the user_data argument passed to add_macro_name or - add_partial_symbol_name. The contents are simply whatever is + expand_partial_symbol_name. The contents are simply whatever is needed by completion_list_add_name. */ struct add_name_data { @@ -3593,15 +3742,13 @@ add_macro_name (const char *name, const struct macro_definition *ignore, datum->text, datum->word); } -/* A callback for map_partial_symbol_names. */ -static void -add_partial_symbol_name (const char *name, void *user_data) +/* A callback for expand_partial_symbol_names. */ +static int +expand_partial_symbol_name (const char *name, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; - completion_list_add_name ((char *) name, - datum->sym_text, datum->sym_text_len, - datum->text, datum->word); + return compare_symbol_name (name, datum->sym_text, datum->sym_text_len); } char ** @@ -3680,6 +3827,22 @@ default_make_symbol_completion_list_break_on (char *text, char *word, sym_text_len = strlen (sym_text); + /* Prepare SYM_TEXT_LEN for compare_symbol_name. */ + + if (current_language->la_language == language_cplus + || current_language->la_language == language_java + || current_language->la_language == language_fortran) + { + /* These languages may have parameters entered by user but they are never + present in the partial symbol tables. */ + + const char *cs = memchr (sym_text, '(', sym_text_len); + + if (cs) + sym_text_len = cs - sym_text; + } + gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '('); + return_val_size = 100; return_val_index = 0; return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *)); @@ -3691,8 +3854,9 @@ default_make_symbol_completion_list_break_on (char *text, char *word, datum.word = word; /* Look through the partial symtabs for all symbols which begin - by matching SYM_TEXT. Add each one that you find to the list. */ - map_partial_symbol_names (add_partial_symbol_name, &datum); + by matching SYM_TEXT. Expand all CUs that you find to the list. + The real names will get added by COMPLETION_LIST_ADD_SYMBOL below. */ + expand_partial_symbol_names (expand_partial_symbol_name, &datum); /* At this point scan through the misc symbol vectors and add each symbol you find to the list. Eventually we want to ignore @@ -3710,7 +3874,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, /* Search upwards from currently selected frame (so that we can complete on local vars). Also catch fields of types defined in this places which match our text string. Only complete on types - visible from current context. */ + visible from current context. */ b = get_selected_block (0); surrounding_static_block = block_static_block (b); @@ -3976,7 +4140,7 @@ not_interesting_fname (const char *fname) for (i = 0; illegal_aliens[i]; i++) { - if (strcmp (fname, illegal_aliens[i]) == 0) + if (filename_cmp (fname, illegal_aliens[i]) == 0) return 1; } return 0; @@ -4005,12 +4169,7 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname, if (not_interesting_fname (filename)) return; if (!filename_seen (filename, 1, data->first) -#if HAVE_DOS_BASED_FILE_SYSTEM - && strncasecmp (filename, data->text, data->text_len) == 0 -#else - && strncmp (filename, data->text, data->text_len) == 0 -#endif - ) + && filename_ncmp (filename, data->text, data->text_len) == 0) { /* This file matches for a completion; add it to the current list of matches. */ @@ -4023,12 +4182,7 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname, if (base_name != filename && !filename_seen (base_name, 1, data->first) -#if HAVE_DOS_BASED_FILE_SYSTEM - && strncasecmp (base_name, data->text, data->text_len) == 0 -#else - && strncmp (base_name, data->text, data->text_len) == 0 -#endif - ) + && filename_ncmp (base_name, data->text, data->text_len) == 0) add_filename_to_list (base_name, data->text, data->word, data->list, data->list_used, data->list_alloced); } @@ -4062,12 +4216,7 @@ make_source_files_completion_list (char *text, char *word) if (not_interesting_fname (s->filename)) continue; if (!filename_seen (s->filename, 1, &first) -#if HAVE_DOS_BASED_FILE_SYSTEM - && strncasecmp (s->filename, text, text_len) == 0 -#else - && strncmp (s->filename, text, text_len) == 0 -#endif - ) + && filename_ncmp (s->filename, text, text_len) == 0) { /* This file matches for a completion; add it to the current list of matches. */ @@ -4083,12 +4232,7 @@ make_source_files_completion_list (char *text, char *word) base_name = lbasename (s->filename); if (base_name != s->filename && !filename_seen (base_name, 1, &first) -#if HAVE_DOS_BASED_FILE_SYSTEM - && strncasecmp (base_name, text, text_len) == 0 -#else - && strncmp (base_name, text, text_len) == 0 -#endif - ) + && filename_ncmp (base_name, text, text_len) == 0) add_filename_to_list (base_name, text, word, &list, &list_used, &list_alloced); } @@ -4111,8 +4255,7 @@ make_source_files_completion_list (char *text, char *word) Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. If non-zero, func_start is where we think the prologue starts, possibly - by previous examination of symbol table information. - */ + by previous examination of symbol table information. */ int in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) @@ -4236,7 +4379,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) /* If there is only one sal that covers the entire function, then it is probably a single line function, like - "foo(){}". */ + "foo(){}". */ if (prologue_sal.end >= end_pc) return 0; @@ -4276,7 +4419,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) corresponding line number is less the first one that we found for the function. This is more conservative then refine_prologue_limit which scans a large number of SALs - looking for any in the prologue */ + looking for any in the prologue. */ prologue_sal = sal; } } @@ -4299,13 +4442,13 @@ decode_line_spec (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - /* We use whatever is set as the current source line. We do not try - and get a default or it will recursively call us! */ + /* We use whatever is set as the current source line. We do not try + and get a default or it will recursively call us! */ cursal = get_current_source_symtab_and_line (); sals = decode_line_1 (&string, funfirstline, cursal.symtab, cursal.line, - (char ***) NULL, NULL); + NULL); if (*string) error (_("Junk at end of line specification: %s"), string); @@ -4314,6 +4457,7 @@ decode_line_spec (char *string, int funfirstline) /* Track MAIN */ static char *name_of_main; +enum language language_of_main = language_unknown; void set_main_name (const char *name) @@ -4322,10 +4466,12 @@ set_main_name (const char *name) { xfree (name_of_main); name_of_main = NULL; + language_of_main = language_unknown; } if (name != NULL) { name_of_main = xstrdup (name); + language_of_main = language_unknown; } } @@ -4344,12 +4490,12 @@ find_main_name (void) name. This would allow us to remove this hard-coded call to an Ada function. It is not clear that this is a better approach at this point, because all methods need to be written in a way - such that false positives never be returned. For instance, it is + such that false positives never be returned. For instance, it is important that a method does not return a wrong name for the main procedure if the main procedure is actually written in a different language. It is easy to guaranty this with Ada, since we use a special symbol generated only when the main in Ada to find the name - of the main procedure. It is difficult however to see how this can + of the main procedure. It is difficult however to see how this can be guarantied for languages such as C, for instance. This suggests that order of call for these methods becomes important, which means a more complicated approach. */ diff --git a/contrib/gdb-7/gdb/symtab.h b/contrib/gdb-7/gdb/symtab.h index bedc10a739..9d236850ad 100644 --- a/contrib/gdb-7/gdb/symtab.h +++ b/contrib/gdb-7/gdb/symtab.h @@ -1,8 +1,8 @@ /* Symbol table definitions for GDB. Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -44,7 +44,7 @@ struct program_space; These structures are laid out to encourage good packing. They use ENUM_BITFIELD and short int fields, and they order the structure members so that fields less than a word are next - to each other so they can be packed together. */ + to each other so they can be packed together. */ /* Rearranged: used ENUM_BITFIELD and rearranged field order in all the space critical structures (plus struct minimal_symbol). @@ -75,14 +75,19 @@ struct program_space; --chastain 2003-08-21 */ +/* Struct for storing C++ specific information. Allocated when needed. */ +struct cplus_specific +{ + char *demangled_name; +}; /* Define a structure for the information that is common to all symbol types, including minimal symbols, partial symbols, and full symbols. In a multilanguage environment, some language specific information may need to - be recorded along with each symbol. */ + be recorded along with each symbol. */ -/* This structure is space critical. See space comments at the top. */ +/* This structure is space critical. See space comments at the top. */ struct general_symbol_info { @@ -113,29 +118,32 @@ struct general_symbol_info CORE_ADDR address; - /* for opaque typedef struct chain */ + /* For opaque typedef struct chain. */ struct symbol *chain; } value; /* Since one and only one language can apply, wrap the language specific - information inside a union. */ + information inside a union. */ union { - struct cplus_specific + /* This is used by languages which wish to store a demangled name. + currently used by Ada, Java, and Objective C. */ + struct mangled_lang { - /* This is in fact used for C++, Java, and Objective C. */ char *demangled_name; } - cplus_specific; + mangled_lang; + + struct cplus_specific *cplus_specific; } language_specific; /* Record the source code language that applies to this symbol. This is used to select one of the fields from the language specific - union above. */ + union above. */ ENUM_BITFIELD(language) language : 8; @@ -153,12 +161,17 @@ struct general_symbol_info struct obj_section *obj_section; }; +extern void symbol_set_demangled_name (struct general_symbol_info *, char *, + struct objfile *); + +extern char *symbol_get_demangled_name (const struct general_symbol_info *); + extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *); /* Note that all the following SYMBOL_* macros are used with the SYMBOL argument being either a partial symbol, a minimal symbol or a full symbol. All three types have a ginfo field. In particular - the SYMBOL_INIT_LANGUAGE_SPECIFIC, SYMBOL_DEMANGLED_NAME, etc. + the SYMBOL_SET_LANGUAGE, SYMBOL_DEMANGLED_NAME, etc. macros cannot be entirely substituted by functions, unless the callers are changed to pass in the ginfo field only, instead of the SYMBOL parameter. */ @@ -173,11 +186,11 @@ extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *); #define SYMBOL_OBJ_SECTION(symbol) (symbol)->ginfo.obj_section /* Initializes the language dependent portion of a symbol - depending upon the language for the symbol. */ -#define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \ - (symbol_init_language_specific (&(symbol)->ginfo, (language))) -extern void symbol_init_language_specific (struct general_symbol_info *symbol, - enum language language); + depending upon the language for the symbol. */ +#define SYMBOL_SET_LANGUAGE(symbol,language) \ + (symbol_set_language (&(symbol)->ginfo, (language))) +extern void symbol_set_language (struct general_symbol_info *symbol, + enum language language); /* Set just the linkage name of a symbol; do not try to demangle it. Used for constructs which do not have a mangled name, @@ -220,7 +233,7 @@ extern char *symbol_natural_name (const struct general_symbol_info *symbol); #define SYMBOL_LINKAGE_NAME(symbol) (symbol)->ginfo.name /* Return the demangled name for a symbol based on the language for - that symbol. If no demangled name exists, return NULL. */ + that symbol. If no demangled name exists, return NULL. */ #define SYMBOL_DEMANGLED_NAME(symbol) \ (symbol_demangled_name (&(symbol)->ginfo)) extern char *symbol_demangled_name (const struct general_symbol_info *symbol); @@ -241,7 +254,7 @@ extern char *symbol_demangled_name (const struct general_symbol_info *symbol); name if it exists. Note that whitespace is ignored while attempting to match a C++ encoded name, so that "foo::bar(int,long)" is the same as "foo :: bar (int, long)". - Evaluates to zero if the match fails, or nonzero if it succeeds. */ + Evaluates to zero if the match fails, or nonzero if it succeeds. */ /* Macro that tests a symbol for a match against a specified name string. It tests against SYMBOL_NATURAL_NAME, and it ignores @@ -251,11 +264,11 @@ extern char *symbol_demangled_name (const struct general_symbol_info *symbol); #define SYMBOL_MATCHES_NATURAL_NAME(symbol, name) \ (strcmp_iw (SYMBOL_NATURAL_NAME (symbol), (name)) == 0) -/* Macro that returns the name to be used when sorting and searching symbols. +/* Macro that returns the name to be used when sorting and searching symbols. In C++, Chill, and Java, we search for the demangled form of a name, and so sort symbols accordingly. In Ada, however, we search by mangled name. If there is no distinct demangled name, then SYMBOL_SEARCH_NAME - returns the same value (same pointer) as SYMBOL_LINKAGE_NAME. */ + returns the same value (same pointer) as SYMBOL_LINKAGE_NAME. */ #define SYMBOL_SEARCH_NAME(symbol) \ (symbol_search_name (&(symbol)->ginfo)) extern char *symbol_search_name (const struct general_symbol_info *); @@ -271,12 +284,15 @@ extern char *symbol_search_name (const struct general_symbol_info *); guess when it can't figure out which is a better match between two types (mst_data versus mst_bss) for example. Since the minimal symbol info is sometimes derived from the BFD library's view of a - file, we need to live with what information bfd supplies. */ + file, we need to live with what information bfd supplies. */ enum minimal_symbol_type { mst_unknown = 0, /* Unknown type, the default */ mst_text, /* Generally executable instructions */ + mst_text_gnu_ifunc, /* Executable code returning address + of executable code */ + mst_slot_got_plt, /* GOT entries for .plt sections */ mst_data, /* Generally initialized data */ mst_bss, /* Generally uninitialized data */ mst_abs, /* Generally absolute (nonrelocatable) */ @@ -306,7 +322,7 @@ enum minimal_symbol_type Even when a file contains enough debugging information to build a full symbol table, these minimal symbols are still useful for quickly mapping between names and addresses, and vice versa. They are also sometimes - used to figure out what full symbol table entries need to be read in. */ + used to figure out what full symbol table entries need to be read in. */ struct minimal_symbol { @@ -356,44 +372,46 @@ struct minimal_symbol /* Represent one symbol name; a variable, constant, function or typedef. */ /* Different name domains for symbols. Looking up a symbol specifies a - domain and ignores symbol definitions in other name domains. */ + domain and ignores symbol definitions in other name domains. */ typedef enum domain_enum_tag { /* UNDEF_DOMAIN is used when a domain has not been discovered or none of the following apply. This usually indicates an error either - in the symbol information or in gdb's handling of symbols. */ + in the symbol information or in gdb's handling of symbols. */ UNDEF_DOMAIN, /* VAR_DOMAIN is the usual domain. In C, this contains variables, - function names, typedef names and enum type values. */ + function names, typedef names and enum type values. */ VAR_DOMAIN, /* STRUCT_DOMAIN is used in C to hold struct, union and enum type names. Thus, if `struct foo' is used in a C program, it produces a symbol named - `foo' in the STRUCT_DOMAIN. */ + `foo' in the STRUCT_DOMAIN. */ STRUCT_DOMAIN, - /* LABEL_DOMAIN may be used for names of labels (for gotos); - currently it is not used and labels are not recorded at all. */ + /* LABEL_DOMAIN may be used for names of labels (for gotos). */ LABEL_DOMAIN, - /* Searching domains. These overlap with VAR_DOMAIN, providing - some granularity with the search_symbols function. */ + /* Searching domains. These overlap with VAR_DOMAIN, providing + some granularity with the search_symbols function. */ /* Everything in VAR_DOMAIN minus FUNCTIONS_DOMAIN and TYPES_DOMAIN. */ VARIABLES_DOMAIN, - /* All functions -- for some reason not methods, though. */ + /* All functions -- for some reason not methods, though. */ FUNCTIONS_DOMAIN, /* All defined types */ - TYPES_DOMAIN + TYPES_DOMAIN, + + /* Any type. */ + ALL_DOMAIN } domain_enum; @@ -401,15 +419,15 @@ domain_enum; enum address_class { - /* Not used; catches errors */ + /* Not used; catches errors. */ LOC_UNDEF, - /* Value is constant int SYMBOL_VALUE, host byteorder */ + /* Value is constant int SYMBOL_VALUE, host byteorder. */ LOC_CONST, - /* Value is at fixed address SYMBOL_VALUE_ADDRESS */ + /* Value is at fixed address SYMBOL_VALUE_ADDRESS. */ LOC_STATIC, @@ -437,7 +455,7 @@ enum address_class /* Value is in specified register. Just like LOC_REGISTER except the register holds the address of the argument instead of the argument - itself. This is currently used for the passing of structs and unions + itself. This is currently used for the passing of structs and unions on sparc and hppa. It is also used for call by reference where the address is in a register, at least by mipsread.c. */ @@ -452,13 +470,13 @@ enum address_class LOC_TYPEDEF, - /* Value is address SYMBOL_VALUE_ADDRESS in the code */ + /* Value is address SYMBOL_VALUE_ADDRESS in the code. */ LOC_LABEL, /* In a symbol table, value is SYMBOL_BLOCK_VALUE of a `struct block'. In a partial symbol table, SYMBOL_VALUE_ADDRESS is the start address - of the block. Function names have this class. */ + of the block. Function names have this class. */ LOC_BLOCK, @@ -538,12 +556,12 @@ struct symbol_register_ops int (*register_number) (struct symbol *symbol, struct gdbarch *gdbarch); }; -/* This structure is space critical. See space comments at the top. */ +/* This structure is space critical. See space comments at the top. */ struct symbol { - /* The general symbol info required for all types of symbols. */ + /* The general symbol info required for all types of symbols. */ struct general_symbol_info ginfo; @@ -577,6 +595,10 @@ struct symbol /* Whether this is an inlined function (class LOC_BLOCK only). */ unsigned is_inlined : 1; + /* True if this is a C++ function symbol with template arguments. + In this case the symbol is really a "struct template_symbol". */ + unsigned is_cplus_template_function : 1; + /* Line number of this symbol's definition, except for inlined functions. For an inlined function (class LOC_BLOCK and SYMBOL_INLINED set) this is the line number of the function's call @@ -624,12 +646,34 @@ struct symbol #define SYMBOL_CLASS(symbol) (symbol)->aclass #define SYMBOL_IS_ARGUMENT(symbol) (symbol)->is_argument #define SYMBOL_INLINED(symbol) (symbol)->is_inlined +#define SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION(symbol) \ + (symbol)->is_cplus_template_function #define SYMBOL_TYPE(symbol) (symbol)->type #define SYMBOL_LINE(symbol) (symbol)->line #define SYMBOL_SYMTAB(symbol) (symbol)->symtab #define SYMBOL_COMPUTED_OPS(symbol) (symbol)->ops.ops_computed #define SYMBOL_REGISTER_OPS(symbol) (symbol)->ops.ops_register #define SYMBOL_LOCATION_BATON(symbol) (symbol)->aux_value + +/* An instance of this type is used to represent a C++ template + function. It includes a "struct symbol" as a kind of base class; + users downcast to "struct template_symbol *" when needed. A symbol + is really of this type iff SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION is + true. */ + +struct template_symbol +{ + /* The base class. */ + struct symbol base; + + /* The number of template arguments. */ + int n_template_arguments; + + /* The template arguments. This is an array with + N_TEMPLATE_ARGUMENTS elements. */ + struct symbol **template_arguments; +}; + /* Each item represents a line-->pc (or the reverse) mapping. This is somewhat more wasteful of space than one might wish, but since only @@ -681,26 +725,26 @@ struct linetable struct section_offsets { - CORE_ADDR offsets[1]; /* As many as needed. */ + CORE_ADDR offsets[1]; /* As many as needed. */ }; #define ANOFFSET(secoff, whichone) \ - ((whichone == -1) \ - ? (internal_error (__FILE__, __LINE__, _("Section index is uninitialized")), -1) \ - : secoff->offsets[whichone]) + ((whichone == -1) \ + ? (internal_error (__FILE__, __LINE__, \ + _("Section index is uninitialized")), -1) \ + : secoff->offsets[whichone]) /* The size of a section_offsets table for N sections. */ #define SIZEOF_N_SECTION_OFFSETS(n) \ (sizeof (struct section_offsets) \ + sizeof (((struct section_offsets *) 0)->offsets) * ((n)-1)) -/* Each source file or header is represented by a struct symtab. +/* Each source file or header is represented by a struct symtab. These objects are chained through the `next' field. */ struct symtab { - - /* Chain of all existing symtabs. */ + /* Unordered chain of all existing symtabs of this objfile. */ struct symtab *next; @@ -724,7 +768,13 @@ struct symtab should be designated the primary, so that the blockvector is relocated exactly once by objfile_relocate. */ - int primary; + unsigned int primary : 1; + + /* Symtab has been compiled with both optimizations and debug info so that + GDB may stop skipping prologues as variables locations are valid already + at function entry points. */ + + unsigned int locations_valid : 1; /* The macro table for this symtab. Like the blockvector, this may be shared between different symtabs --- and normally is for @@ -773,7 +823,7 @@ struct symtab /* String that identifies the format of the debugging information, such as "stabs", "dwarf 1", "dwarf 2", "coff", etc. This is mostly useful for automated testing of gdb but may also be information that is - useful to the user. */ + useful to the user. */ char *debugformat; @@ -806,17 +856,17 @@ struct symtab virtual function should be applied. PFN is a pointer to the virtual function. - Note that this macro is g++ specific (FIXME). */ + Note that this macro is g++ specific (FIXME). */ #define VTBL_FNADDR_OFFSET 2 -/* External variables and functions for the objects described above. */ +/* External variables and functions for the objects described above. */ -/* See the comment in symfile.c about how current_objfile is used. */ +/* See the comment in symfile.c about how current_objfile is used. */ extern struct objfile *current_objfile; -/* True if we are nested inside psymtab_to_symtab. */ +/* True if we are nested inside psymtab_to_symtab. */ extern int currently_reading_symtab; @@ -836,7 +886,7 @@ int symbol_matches_domain (enum language symbol_language, domain_enum symbol_domain, domain_enum domain); -/* lookup a symbol table by source file name */ +/* lookup a symbol table by source file name. */ extern struct symtab *lookup_symtab (const char *); @@ -849,7 +899,7 @@ extern struct symbol *lookup_symbol_in_language (const char *, int *); /* lookup a symbol by name (optional block, optional symtab) - in the current language */ + in the current language. */ extern struct symbol *lookup_symbol (const char *, const struct block *, const domain_enum, int *); @@ -892,12 +942,12 @@ struct symbol *lookup_static_symbol_aux (const char *name, const domain_enum domain); -/* lookup a symbol by name, within a specified block */ +/* lookup a symbol by name, within a specified block. */ extern struct symbol *lookup_block_symbol (const struct block *, const char *, const domain_enum); -/* lookup a [struct, union, enum] by name, within a specified block */ +/* lookup a [struct, union, enum] by name, within a specified block. */ extern struct type *lookup_struct (char *, struct block *); @@ -907,31 +957,36 @@ extern struct type *lookup_enum (char *, struct block *); /* from blockframe.c: */ -/* lookup the function symbol corresponding to the address */ +/* lookup the function symbol corresponding to the address. */ extern struct symbol *find_pc_function (CORE_ADDR); -/* lookup the function corresponding to the address and section */ +/* lookup the function corresponding to the address and section. */ extern struct symbol *find_pc_sect_function (CORE_ADDR, struct obj_section *); -/* lookup function from address, return name, start addr and end addr */ +extern int find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, char **name, + CORE_ADDR *address, + CORE_ADDR *endaddr, + int *is_gnu_ifunc_p); + +/* lookup function from address, return name, start addr and end addr. */ extern int find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *, CORE_ADDR *); extern void clear_pc_function_cache (void); -/* lookup partial symbol table by address and section */ +/* lookup partial symbol table by address and section. */ extern struct symtab *find_pc_sect_symtab_via_partial (CORE_ADDR, struct obj_section *); -/* lookup full symbol table by address */ +/* lookup full symbol table by address. */ extern struct symtab *find_pc_symtab (CORE_ADDR); -/* lookup full symbol table by address and section */ +/* lookup full symbol table by address and section. */ extern struct symtab *find_pc_sect_symtab (CORE_ADDR, struct obj_section *); @@ -943,12 +998,12 @@ extern struct type *lookup_transparent_type (const char *); extern struct type *basic_lookup_transparent_type (const char *); -/* Macro for name of symbol to indicate a file compiled with gcc. */ +/* Macro for name of symbol to indicate a file compiled with gcc. */ #ifndef GCC_COMPILED_FLAG_SYMBOL #define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." #endif -/* Macro for name of symbol to indicate a file compiled with gcc2. */ +/* Macro for name of symbol to indicate a file compiled with gcc2. */ #ifndef GCC2_COMPILED_FLAG_SYMBOL #define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled." #endif @@ -996,6 +1051,35 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); +extern int in_gnu_ifunc_stub (CORE_ADDR pc); + +/* Functions for resolving STT_GNU_IFUNC symbols which are implemented only + for ELF symbol files. */ + +struct gnu_ifunc_fns +{ + /* See elf_gnu_ifunc_resolve_addr for its real implementation. */ + CORE_ADDR (*gnu_ifunc_resolve_addr) (struct gdbarch *gdbarch, CORE_ADDR pc); + + /* See elf_gnu_ifunc_resolve_name for its real implementation. */ + int (*gnu_ifunc_resolve_name) (const char *function_name, + CORE_ADDR *function_address_p); + + /* See elf_gnu_ifunc_resolver_stop for its real implementation. */ + void (*gnu_ifunc_resolver_stop) (struct breakpoint *b); + + /* See elf_gnu_ifunc_resolver_return_stop for its real implementation. */ + void (*gnu_ifunc_resolver_return_stop) (struct breakpoint *b); +}; + +#define gnu_ifunc_resolve_addr gnu_ifunc_fns_p->gnu_ifunc_resolve_addr +#define gnu_ifunc_resolve_name gnu_ifunc_fns_p->gnu_ifunc_resolve_name +#define gnu_ifunc_resolver_stop gnu_ifunc_fns_p->gnu_ifunc_resolver_stop +#define gnu_ifunc_resolver_return_stop \ + gnu_ifunc_fns_p->gnu_ifunc_resolver_return_stop + +extern const struct gnu_ifunc_fns *gnu_ifunc_fns_p; + extern struct minimal_symbol * lookup_minimal_symbol_and_objfile (const char *, struct objfile **); @@ -1048,10 +1132,10 @@ struct symtabs_and_lines /* Some types and macros needed for exception catchpoints. Can't put these in target.h because symtab_and_line isn't - known there. This file will be included by breakpoint.c, - hppa-tdep.c, etc. */ + known there. This file will be included by breakpoint.c, + hppa-tdep.c, etc. */ -/* Enums for exception-handling support */ +/* Enums for exception-handling support. */ enum exception_event_kind { EX_EVENT_THROW, @@ -1065,7 +1149,7 @@ enum exception_event_kind extern struct symtab_and_line find_pc_line (CORE_ADDR, int); -/* Same function, but specify a section as well as an address */ +/* Same function, but specify a section as well as an address. */ extern struct symtab_and_line find_pc_sect_line (CORE_ADDR, struct obj_section *, int); @@ -1137,7 +1221,7 @@ extern char **make_source_files_completion_list (char *, char *); int matching_obj_sections (struct obj_section *, struct obj_section *); -extern char *find_main_filename (void); +extern const char *find_main_filename (void); extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *); @@ -1148,9 +1232,9 @@ extern void skip_prologue_sal (struct symtab_and_line *); /* symfile.c */ -extern void clear_symtab_users (void); +extern void clear_symtab_users (int add_flags); -extern enum language deduce_language_from_filename (char *); +extern enum language deduce_language_from_filename (const char *); /* symtab.c */ @@ -1166,25 +1250,25 @@ extern struct symbol *fixup_symbol_section (struct symbol *, /* Symbol searching */ /* When using search_symbols, a list of the following structs is returned. - Callers must free the search list using free_search_symbols! */ + Callers must free the search list using free_search_symbols! */ struct symbol_search { - /* The block in which the match was found. Could be, for example, - STATIC_BLOCK or GLOBAL_BLOCK. */ + /* The block in which the match was found. Could be, for example, + STATIC_BLOCK or GLOBAL_BLOCK. */ int block; /* Information describing what was found. If symtab abd symbol are NOT NULL, then information was found - for this match. */ + for this match. */ struct symtab *symtab; struct symbol *symbol; /* If msymbol is non-null, then a match was made on something for - which only minimal_symbols exist. */ + which only minimal_symbols exist. */ struct minimal_symbol *msymbol; - /* A link to the next match, or NULL for the end. */ + /* A link to the next match, or NULL for the end. */ struct symbol_search *next; }; @@ -1197,12 +1281,13 @@ extern struct cleanup *make_cleanup_free_search_symbols (struct symbol_search /* The name of the ``main'' function. FIXME: cagney/2001-03-20: Can't make main_name() const since some of the calling code currently assumes that the string isn't - const. */ + const. */ extern void set_main_name (const char *name); extern /*const */ char *main_name (void); +extern enum language language_of_main; /* Check global symbols in objfile. */ -struct symbol *lookup_global_symbol_from_objfile (const struct objfile *objfile, +struct symbol *lookup_global_symbol_from_objfile (const struct objfile *, const char *name, const domain_enum domain); diff --git a/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd b/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd index 865eba6f5e..0735ecddcd 100644 --- a/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd +++ b/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd @@ -1,4 +1,4 @@ -