diff options
author | nobody <> | 2003-03-05 18:00:03 +0000 |
---|---|---|
committer | nobody <> | 2003-03-05 18:00:03 +0000 |
commit | 07297283f46fcad05679b32b8109625b0c7d8670 (patch) | |
tree | 4c13a6d3906b8ba33c9c9e1350998d1d49b19ecb | |
parent | 160e942aa15f9f939444eb3c3c29b2f9a63b786d (diff) | |
download | binutils-gdb-07297283f46fcad05679b32b8109625b0c7d8670.tar.gz |
This commit was manufactured by cvs2svn to create branch
'carlton_dictionary-branch'.
Cherrypick from master 2003-03-05 18:00:02 UTC Daniel Jacobowitz <drow@false.org> ' * dwarf2expr.c (new_dwarf_expr_context): Add (void) to definition.':
bfd/doc/fdl.texi
bfd/elf32-ppc.h
gdb/coff-pe-read.c
gdb/coff-pe-read.h
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2loc.h
gdb/observer.c
gdb/observer.h
gdb/tui/tui-interp.c
libiberty/acconfig.h
libiberty/lrealpath.c
libiberty/physmem.c
-rw-r--r-- | bfd/doc/fdl.texi | 366 | ||||
-rw-r--r-- | bfd/elf32-ppc.h | 23 | ||||
-rw-r--r-- | gdb/coff-pe-read.c | 346 | ||||
-rw-r--r-- | gdb/coff-pe-read.h | 32 | ||||
-rw-r--r-- | gdb/dwarf2expr.c | 687 | ||||
-rw-r--r-- | gdb/dwarf2expr.h | 103 | ||||
-rw-r--r-- | gdb/dwarf2loc.c | 356 | ||||
-rw-r--r-- | gdb/dwarf2loc.h | 39 | ||||
-rw-r--r-- | gdb/observer.c | 192 | ||||
-rw-r--r-- | gdb/observer.h | 35 | ||||
-rw-r--r-- | gdb/tui/tui-interp.c | 180 | ||||
-rw-r--r-- | libiberty/acconfig.h | 3 | ||||
-rw-r--r-- | libiberty/lrealpath.c | 128 | ||||
-rw-r--r-- | libiberty/physmem.c | 305 |
14 files changed, 2795 insertions, 0 deletions
diff --git a/bfd/doc/fdl.texi b/bfd/doc/fdl.texi new file mode 100644 index 00000000000..176233cb1b0 --- /dev/null +++ b/bfd/doc/fdl.texi @@ -0,0 +1,366 @@ +@c -*-texinfo-*- +@appendix GNU Free Documentation License +@center Version 1.1, March 2000 + +@display +Copyright (C) 2000, Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display +@sp 1 +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document ``free'' in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@sp 1 +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The ``Document'', below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as ``you.'' + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not ``Transparent'' is called ``Opaque.'' + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. +@sp 1 +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. +@sp 1 +@item +COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. +@sp 1 +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission.@* +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five).@* +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher.@* +D. Preserve all the copyright notices of the Document.@* +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices.@* +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below.@* +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice.@* +H. Include an unaltered copy of this License.@* +I. Preserve the section entitled ``History'', and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled ``History'' in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence.@* +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the ``History'' section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission.@* +K. In any section entitled ``Acknowledgements'' or ``Dedications'', + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein.@* +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles.@* +M. Delete any section entitled ``Endorsements.'' Such a section + may not be included in the Modified Version.@* +N. Do not retitle any existing section as ``Endorsements'' + or to conflict in title with any Invariant Section.@* +@sp 1 +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. +@sp 1 +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled ``History'' +in the various original documents, forming one section entitled +``History''; likewise combine any sections entitled ``Acknowledgements'', +and any sections entitled ``Dedications.'' You must delete all sections +entitled ``Endorsements.'' +@sp 1 +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. +@sp 1 +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an ``aggregate'', and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. +@sp 1 +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. +@sp 1 +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. +@sp 1 +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + +@end enumerate + +@unnumberedsec ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group +Copyright (C) @var{year} @var{your name}. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 +or any later version published by the Free Software Foundation; +with the Invariant Sections being @var{list their titles}, with the +Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. +A copy of the license is included in the section entitled "GNU +Free Documentation License." +@end group +@end smallexample + +If you have no Invariant Sections, write ``with no Invariant Sections'' +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write ``no Front-Cover Texts'' instead of +``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h new file mode 100644 index 00000000000..ead9c944d69 --- /dev/null +++ b/bfd/elf32-ppc.h @@ -0,0 +1,23 @@ +/* PowerPC-specific support for 64-bit ELF. + Copyright 2003 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +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 2 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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +bfd_boolean ppc_elf_tls_setup + PARAMS ((bfd *, struct bfd_link_info *)); +bfd_boolean ppc_elf_tls_optimize + PARAMS ((bfd *, struct bfd_link_info *)); diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c new file mode 100644 index 00000000000..2d1e8541fbe --- /dev/null +++ b/gdb/coff-pe-read.c @@ -0,0 +1,346 @@ +/* Read the export table symbols from a portable executable and + convert to internal format, for GDB. Used as a last resort if no + debugging symbols recognized. + + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ + +#include "coff-pe-read.h" + +#include "bfd.h" + +#include "defs.h" +#include "gdbtypes.h" + +#include "symtab.h" +#include "symfile.h" +#include "objfiles.h" + +/* Internal section information */ + +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. */ +}; + +#define PE_SECTION_INDEX_TEXT 0 +#define PE_SECTION_INDEX_DATA 1 +#define PE_SECTION_INDEX_BSS 2 +#define PE_SECTION_TABLE_SIZE 3 +#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. */ + +static int +read_pe_section_index (const char *section_name) +{ + if (strcmp (section_name, ".text") == 0) + { + return PE_SECTION_INDEX_TEXT; + } + + else if (strcmp (section_name, ".data") == 0) + { + return PE_SECTION_INDEX_DATA; + } + + else if (strcmp (section_name, ".bss") == 0) + { + return PE_SECTION_INDEX_BSS; + } + + else + { + return PE_SECTION_INDEX_INVALID; + } +} + +/* Record the virtual memory address of a section. */ + +static void +get_section_vmas (bfd *abfd, asection *sectp, void *context) +{ + struct read_pe_section_data *sections = context; + int sectix = read_pe_section_index (sectp->name); + + 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. */ + + sections[sectix].vma_offset + = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start; + } +} + +/* Create a minimal symbol entry for an exported symbol. */ + +static void +add_pe_exported_sym (char *sym_name, + unsigned long func_rva, + 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. */ + + CORE_ADDR vma = func_rva + section_data->vma_offset; + + char *qualified_name = 0; + int dll_name_len = strlen (dll_name); + int count; + + /* 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". */ + + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + + strncpy (qualified_name, dll_name, dll_name_len); + qualified_name[dll_name_len] = '!'; + strcpy (qualified_name + dll_name_len + 1, sym_name); + + prim_record_minimal_symbol (qualified_name, + vma, section_data->ms_type, objfile); + + 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); +} + +/* Truncate a dll_name at the first dot character. */ + +static void +read_pe_truncate_name (char *dll_name) +{ + while (*dll_name) + { + if ((*dll_name) == '.') + { + *dll_name = '\0'; /* truncates and causes loop exit. */ + } + + else + { + ++dll_name; + } + } +} + +/* Low-level support functions, direct from the ld module pe-dll.c. */ +static unsigned int +pe_get16 (bfd *abfd, int where) +{ + unsigned char b[2]; + + bfd_seek (abfd, (file_ptr) where, SEEK_SET); + bfd_bread (b, (bfd_size_type) 2, abfd); + return b[0] + (b[1] << 8); +} + +static unsigned int +pe_get32 (bfd *abfd, int where) +{ + unsigned char b[4]; + + bfd_seek (abfd, (file_ptr) where, SEEK_SET); + bfd_bread (b, (bfd_size_type) 4, abfd); + return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); +} + +static unsigned int +pe_as32 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); +} + +/* 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. */ + +void +read_pe_exported_syms (struct objfile *objfile) +{ + bfd *dll = objfile->obfd; + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + + /* 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. */ + struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] + = { {0, 1, 0, mst_text}, + {0, 1, 0, mst_data}, + {0, 1, 0, mst_bss} + }; + + struct cleanup *back_to = 0; + + char const *target = bfd_get_target (objfile->obfd); + + if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0)) + { + /* This is not an i386 format file. Abort now, because the code + is untested on anything else. *FIXME* test on further + architectures and loosen or remove this test. */ + return; + } + + /* Get pe_header, optional header and numbers of export entries. */ + pe_header_offset = pe_get32 (dll, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + num_entries = pe_get32 (dll, opthdr_ofs + 92); + + if (num_entries < 1) /* No exports. */ + { + return; + } + + export_rva = pe_get32 (dll, opthdr_ofs + 96); + export_size = pe_get32 (dll, opthdr_ofs + 100); + nsections = pe_get16 (dll, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (dll, pe_header_offset + 4 + 16)); + expptr = 0; + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long vsize = pe_get32 (dll, secptr1 + 16); + unsigned long fptr = pe_get32 (dll, secptr1 + 20); + + bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, dll); + + if (vaddr <= export_rva && vaddr + vsize > export_rva) + { + expptr = fptr + (export_rva - vaddr); + if (export_rva + export_size > vaddr + vsize) + export_size = vsize - (export_rva - vaddr); + break; + } + } + + if (export_size == 0) + { + /* Empty export table. */ + return; + } + + /* Scan sections and store the base and size of the relevant sections. */ + for (i = 0; i < nsections; i++) + { + unsigned long secptr1 = secptr + 40 * i; + unsigned long vsize = pe_get32 (dll, secptr1 + 8); + unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long flags = pe_get32 (dll, secptr1 + 36); + char sec_name[9]; + int sectix; + + sec_name[8] = '\0'; + bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); + bfd_bread (sec_name, (bfd_size_type) 8, dll); + + sectix = read_pe_section_index (sec_name); + + if (sectix != PE_SECTION_INDEX_INVALID) + { + section_data[sectix].rva_start = vaddr; + section_data[sectix].rva_end = vaddr + vsize; + } + } + + expdata = (unsigned char *) xmalloc (export_size); + back_to = make_cleanup (xfree, expdata); + + bfd_seek (dll, (file_ptr) expptr, SEEK_SET); + bfd_bread (expdata, (bfd_size_type) export_size, dll); + erva = expdata - export_rva; + + nexp = pe_as32 (expdata + 24); + name_rvas = pe_as32 (expdata + 32); + ordinals = pe_as32 (expdata + 36); + ordbase = pe_as32 (expdata + 16); + exp_funcbase = pe_as32 (expdata + 28); + + /* 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. */ + for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset + += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + } + + printf_filtered ("Minimal symbols from %s...", dll_name); + wrap_here (""); + + /* Truncate name at first dot. Should maybe also convert to all + lower case for convenience on Windows. */ + read_pe_truncate_name (dll_name); + + /* Iterate through the list of symbols. */ + for (i = 0; i < nexp; i++) + { + /* Pointer to the names vector. */ + unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + + /* 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. */ + int sectix = 0; + + for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + { + if ((func_rva >= section_data[sectix].rva_start) + && (func_rva < section_data[sectix].rva_end)) + { + add_pe_exported_sym (erva + name_rva, + func_rva, + section_data + sectix, dll_name, objfile); + break; + } + } + } + + /* discard expdata. */ + do_cleanups (back_to); +} diff --git a/gdb/coff-pe-read.h b/gdb/coff-pe-read.h new file mode 100644 index 00000000000..c5d4e68bc17 --- /dev/null +++ b/gdb/coff-pe-read.h @@ -0,0 +1,32 @@ +/* Interface to coff-pe-read.c (portable-executable-specific symbol reader). + + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + 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 */ +extern void read_pe_exported_syms (struct objfile *objfile); + +#endif /* !defined (COFF_PE_READ_H) */ diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c new file mode 100644 index 00000000000..7456979b91f --- /dev/null +++ b/gdb/dwarf2expr.c @@ -0,0 +1,687 @@ +/* Dwarf2 Expression Evaluator + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Daniel Berlin (dan@dberlin.org) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "value.h" +#include "gdbcore.h" +#include "elf/dwarf2.h" +#include "dwarf2expr.h" + +/* Local prototypes. */ + +static void execute_stack_op (struct dwarf_expr_context *, + unsigned char *, unsigned char *); + +/* Create a new context for the expression evaluator. */ + +struct dwarf_expr_context * +new_dwarf_expr_context (void) +{ + struct dwarf_expr_context *retval; + retval = xcalloc (1, sizeof (struct dwarf_expr_context)); + retval->stack_len = 10; + retval->stack = xmalloc (10 * sizeof (CORE_ADDR)); + return retval; +} + +/* Release the memory allocated to CTX. */ + +void +free_dwarf_expr_context (struct dwarf_expr_context *ctx) +{ + xfree (ctx->stack); + xfree (ctx); +} + +/* Expand the memory allocated to CTX's stack to contain at least + NEED more elements than are currently used. */ + +static void +dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need) +{ + if (ctx->stack_len + need > ctx->stack_allocated) + { + size_t templen = ctx->stack_len * 2; + while (templen < (ctx->stack_len + need)) + templen *= 2; + ctx->stack = xrealloc (ctx->stack, + templen * sizeof (CORE_ADDR)); + ctx->stack_allocated = templen; + } +} + +/* Push VALUE onto CTX's stack. */ + +void +dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value) +{ + dwarf_expr_grow_stack (ctx, 1); + ctx->stack[ctx->stack_len++] = value; +} + +/* Pop the top item off of CTX's stack. */ + +void +dwarf_expr_pop (struct dwarf_expr_context *ctx) +{ + if (ctx->stack_len <= 0) + error ("dwarf expression stack underflow"); + ctx->stack_len--; +} + +/* Retrieve the N'th item on CTX's stack. */ + +CORE_ADDR +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\n", + n, ctx->stack_len); + return ctx->stack[ctx->stack_len - (1 + n)]; + +} + +/* Evaluate the expression at ADDR (LEN bytes long) using the context + CTX. */ + +void +dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, + size_t len) +{ + execute_stack_op (ctx, addr, addr + len); +} + +/* Decode the unsigned LEB128 constant at BUF into the variable pointed to + by R, and return the new value of BUF. Verify that it doesn't extend + past BUF_END. */ + +unsigned char * +read_uleb128 (unsigned char *buf, unsigned char *buf_end, ULONGEST * r) +{ + unsigned shift = 0; + ULONGEST result = 0; + unsigned char byte; + + while (1) + { + if (buf >= buf_end) + error ("read_uleb128: Corrupted DWARF expression."); + + byte = *buf++; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + *r = result; + return buf; +} + +/* Decode the signed LEB128 constant at BUF into the variable pointed to + by R, and return the new value of BUF. Verify that it doesn't extend + past BUF_END. */ + +unsigned char * +read_sleb128 (unsigned char *buf, unsigned char *buf_end, LONGEST * r) +{ + unsigned shift = 0; + LONGEST result = 0; + unsigned char byte; + + while (1) + { + if (buf >= buf_end) + error ("read_sleb128: Corrupted DWARF expression."); + + byte = *buf++; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0) + result |= -(1 << shift); + + *r = result; + return buf; +} + +/* Read an address from BUF, and verify that it doesn't extend past + BUF_END. The address is returned, and *BYTES_READ is set to the + number of bytes read from BUF. */ + +static CORE_ADDR +read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read) +{ + CORE_ADDR result; + + if (buf_end - buf < TARGET_ADDR_BIT / TARGET_CHAR_BIT) + error ("read_address: Corrupted DWARF expression."); + + *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT; + result = extract_address (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT); + return result; +} + +/* Return the type of an address, for unsigned arithmetic. */ + +static struct type * +unsigned_address_type (void) +{ + switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT) + { + case 2: + return builtin_type_uint16; + case 4: + return builtin_type_uint32; + case 8: + return builtin_type_uint64; + default: + internal_error (__FILE__, __LINE__, + "Unsupported address size.\n"); + } +} + +/* Return the type of an address, for signed arithmetic. */ + +static struct type * +signed_address_type (void) +{ + switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT) + { + case 2: + return builtin_type_int16; + case 4: + return builtin_type_int32; + case 8: + return builtin_type_int64; + default: + internal_error (__FILE__, __LINE__, + "Unsupported address size.\n"); + } +} + +/* The engine for the expression evaluator. Using the context in CTX, + evaluate the expression between OP_PTR and OP_END. */ + +static void +execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr, + unsigned char *op_end) +{ + while (op_ptr < op_end) + { + enum dwarf_location_atom op = *op_ptr++; + CORE_ADDR result, memaddr; + ULONGEST uoffset, reg; + LONGEST offset; + int bytes_read; + enum lval_type expr_lval; + + ctx->in_reg = 0; + + 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: + result = op - DW_OP_lit0; + break; + + case DW_OP_addr: + result = read_address (op_ptr, op_end, &bytes_read); + op_ptr += bytes_read; + break; + + case DW_OP_const1u: + result = extract_unsigned_integer (op_ptr, 1); + op_ptr += 1; + break; + case DW_OP_const1s: + result = extract_signed_integer (op_ptr, 1); + op_ptr += 1; + break; + case DW_OP_const2u: + result = extract_unsigned_integer (op_ptr, 2); + op_ptr += 2; + break; + case DW_OP_const2s: + result = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + break; + case DW_OP_const4u: + result = extract_unsigned_integer (op_ptr, 4); + op_ptr += 4; + break; + case DW_OP_const4s: + result = extract_signed_integer (op_ptr, 4); + op_ptr += 4; + break; + case DW_OP_const8u: + result = extract_unsigned_integer (op_ptr, 8); + op_ptr += 8; + break; + case DW_OP_const8s: + result = extract_signed_integer (op_ptr, 8); + op_ptr += 8; + break; + case DW_OP_constu: + op_ptr = read_uleb128 (op_ptr, op_end, &uoffset); + result = uoffset; + break; + case DW_OP_consts: + op_ptr = read_sleb128 (op_ptr, op_end, &offset); + result = offset; + break; + + /* The DW_OP_reg operations are required to occur alone in + location expressions. */ + 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: + /* NOTE: in the presence of DW_OP_piece this check is incorrect. */ + if (op_ptr != op_end) + error ("DWARF-2 expression error: DW_OP_reg operations must be " + "used alone."); + + /* FIXME drow/2003-02-21: This call to read_reg could be pushed + into the evaluator's caller by changing the semantics for in_reg. + Then we wouldn't need to return an lval_type and a memaddr. */ + result = (ctx->read_reg) (ctx->baton, op - DW_OP_reg0, &expr_lval, + &memaddr); + + if (expr_lval == lval_register) + { + ctx->regnum = op - DW_OP_reg0; + ctx->in_reg = 1; + } + else + result = memaddr; + + break; + + case DW_OP_regx: + op_ptr = read_uleb128 (op_ptr, op_end, ®); + if (op_ptr != op_end) + error ("DWARF-2 expression error: DW_OP_reg operations must be " + "used alone."); + + result = (ctx->read_reg) (ctx->baton, reg, &expr_lval, &memaddr); + + if (expr_lval == lval_register) + { + ctx->regnum = reg; + ctx->in_reg = 1; + } + else + result = memaddr; + + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + { + op_ptr = read_sleb128 (op_ptr, op_end, &offset); + result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0, + &expr_lval, &memaddr); + result += offset; + } + break; + case DW_OP_bregx: + { + op_ptr = read_uleb128 (op_ptr, op_end, ®); + op_ptr = read_sleb128 (op_ptr, op_end, &offset); + result = (ctx->read_reg) (ctx->baton, reg, &expr_lval, &memaddr); + result += offset; + } + break; + case DW_OP_fbreg: + { + unsigned char *datastart; + size_t datalen; + unsigned int before_stack_len; + + op_ptr = read_sleb128 (op_ptr, op_end, &offset); + /* Rather than create a whole new context, we simply + record the stack length before execution, then reset it + afterwards, effectively erasing whatever the recursive + call put there. */ + before_stack_len = ctx->stack_len; + (ctx->get_frame_base) (ctx->baton, &datastart, &datalen); + dwarf_expr_eval (ctx, datastart, datalen); + result = dwarf_expr_fetch (ctx, 0); + if (! ctx->in_reg) + { + char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT); + int bytes_read; + + (ctx->read_mem) (ctx->baton, buf, result, + TARGET_ADDR_BIT / TARGET_CHAR_BIT); + result = read_address (buf, + buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT, + &bytes_read); + } + result = result + offset; + ctx->stack_len = before_stack_len; + ctx->in_reg = 0; + } + break; + case DW_OP_dup: + result = dwarf_expr_fetch (ctx, 0); + break; + + case DW_OP_drop: + dwarf_expr_pop (ctx); + goto no_push; + + case DW_OP_pick: + offset = *op_ptr++; + result = dwarf_expr_fetch (ctx, offset); + break; + + case DW_OP_over: + result = dwarf_expr_fetch (ctx, 1); + break; + + case DW_OP_rot: + { + CORE_ADDR t1, t2, t3; + + if (ctx->stack_len < 3) + error ("Not enough elements for DW_OP_rot. Need 3, have %d\n", + ctx->stack_len); + t1 = ctx->stack[ctx->stack_len - 1]; + t2 = ctx->stack[ctx->stack_len - 2]; + t3 = ctx->stack[ctx->stack_len - 3]; + ctx->stack[ctx->stack_len - 1] = t2; + ctx->stack[ctx->stack_len - 2] = t3; + ctx->stack[ctx->stack_len - 3] = t1; + goto no_push; + } + + case DW_OP_deref: + case DW_OP_deref_size: + case DW_OP_abs: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_plus_uconst: + /* Unary operations. */ + result = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); + + switch (op) + { + case DW_OP_deref: + { + char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT); + int bytes_read; + + (ctx->read_mem) (ctx->baton, buf, result, + TARGET_ADDR_BIT / TARGET_CHAR_BIT); + result = read_address (buf, + buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT, + &bytes_read); + } + break; + + case DW_OP_deref_size: + { + char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT); + int bytes_read; + + (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++); + result = read_address (buf, + buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT, + &bytes_read); + } + break; + + case DW_OP_abs: + if ((signed int) result < 0) + result = -result; + break; + case DW_OP_neg: + result = -result; + break; + case DW_OP_not: + result = ~result; + break; + case DW_OP_plus_uconst: + op_ptr = read_uleb128 (op_ptr, op_end, ®); + result += reg; + break; + } + break; + + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + case DW_OP_le: + case DW_OP_ge: + case DW_OP_eq: + case DW_OP_lt: + case DW_OP_gt: + case DW_OP_ne: + { + /* Binary operations. Use the value engine to do computations in + the right width. */ + CORE_ADDR first, second; + enum exp_opcode binop; + struct value *val1, *val2; + + second = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); + + first = dwarf_expr_fetch (ctx, 1); + dwarf_expr_pop (ctx); + + val1 = value_from_longest (unsigned_address_type (), first); + val2 = value_from_longest (unsigned_address_type (), second); + + switch (op) + { + case DW_OP_and: + binop = BINOP_BITWISE_AND; + break; + case DW_OP_div: + binop = BINOP_DIV; + case DW_OP_minus: + binop = BINOP_SUB; + break; + case DW_OP_mod: + binop = BINOP_MOD; + break; + case DW_OP_mul: + binop = BINOP_MUL; + break; + case DW_OP_or: + binop = BINOP_BITWISE_IOR; + break; + case DW_OP_plus: + binop = BINOP_ADD; + break; + case DW_OP_shl: + binop = BINOP_LSH; + break; + case DW_OP_shr: + binop = BINOP_RSH; + case DW_OP_shra: + binop = BINOP_RSH; + val1 = value_from_longest (signed_address_type (), first); + break; + case DW_OP_xor: + binop = BINOP_BITWISE_XOR; + break; + case DW_OP_le: + binop = BINOP_LEQ; + break; + case DW_OP_ge: + binop = BINOP_GEQ; + break; + case DW_OP_eq: + binop = BINOP_EQUAL; + break; + case DW_OP_lt: + binop = BINOP_LESS; + break; + case DW_OP_gt: + binop = BINOP_GTR; + break; + case DW_OP_ne: + binop = BINOP_NOTEQUAL; + break; + default: + internal_error (__FILE__, __LINE__, + "Can't be reached."); + } + result = value_as_long (value_binop (val1, val2, binop)); + } + break; + + case DW_OP_GNU_push_tls_address: + result = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); + result = (ctx->get_tls_address) (ctx->baton, result); + break; + + case DW_OP_skip: + offset = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + op_ptr += offset; + goto no_push; + + case DW_OP_bra: + offset = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + if (dwarf_expr_fetch (ctx, 0) != 0) + op_ptr += offset; + dwarf_expr_pop (ctx); + goto no_push; + + case DW_OP_nop: + goto no_push; + + default: + error ("Unhandled dwarf expression opcode"); + } + + /* Most things push a result value. */ + dwarf_expr_push (ctx, result); + no_push:; + } +} diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h new file mode 100644 index 00000000000..3d0fcb33e7b --- /dev/null +++ b/gdb/dwarf2expr.h @@ -0,0 +1,103 @@ +/* Dwarf2 Expression Evaluator + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Daniel Berlin (dan@dberlin.org) + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (DWARF2EXPR_H) +#define DWARF2EXPR_H + +/* The expression evaluator works with a dwarf_expr_context, describing + its current state and its callbacks. */ +struct dwarf_expr_context +{ + /* The stack of values, allocated with xmalloc. */ + CORE_ADDR *stack; + + /* The number of values currently pushed on the stack, and the + number of elements allocated to the stack. */ + int stack_len, stack_allocated; + + /* An opaque argument provided by the caller, which will be passed + to all of the callback functions. */ + void *baton; + + /* Return the value of register number REGNUM. LVALP will be set + to the kind of lval this register is (generally lval_register + for the current frame's registers or lval_memory for a register + saved to the stack). For lval_memory ADDRP will be set to the + saved location of the register. */ + CORE_ADDR (*read_reg) (void *baton, int regnum, enum lval_type *lvalp, + CORE_ADDR *addrp); + + /* Read LENGTH bytes at ADDR into BUF. */ + void (*read_mem) (void *baton, char *buf, CORE_ADDR addr, + size_t length); + + /* Return the location expression for the frame base attribute, in + START and LENGTH. The result must be live until the current + expression evaluation is complete. */ + void (*get_frame_base) (void *baton, unsigned char **start, + size_t *length); + + /* Return the thread-local storage address for + DW_OP_GNU_push_tls_address. */ + CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); + +#if 0 + /* Not yet implemented. */ + + /* Return the location expression for the dwarf expression + subroutine in the die at OFFSET in the current compilation unit. + The result must be live until the current expression evaluation + is complete. */ + unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length); + + /* Return the `object address' for DW_OP_push_object_address. */ + CORE_ADDR (*get_object_address) (void *baton); +#endif + + /* The current depth of dwarf expression recursion, via DW_OP_call*, + DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum + depth we'll tolerate before raising an error. */ + int recursion_depth, max_recursion_depth; + + /* Non-zero if the result is in a register. The register number + will be in REGNUM, and the result will be the contents of the + register. */ + int in_reg; + + /* If the result is in a register, the register number. */ + int regnum; +}; + +struct dwarf_expr_context *new_dwarf_expr_context (); +void free_dwarf_expr_context (struct dwarf_expr_context *ctx); + +void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value); +void dwarf_expr_pop (struct dwarf_expr_context *ctx); +void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, + size_t len); +CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); + + +unsigned char *read_uleb128 (unsigned char *buf, unsigned char *buf_end, + ULONGEST * r); +unsigned char *read_sleb128 (unsigned char *buf, unsigned char *buf_end, + LONGEST * r); + +#endif diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c new file mode 100644 index 00000000000..9ea9941f249 --- /dev/null +++ b/gdb/dwarf2loc.c @@ -0,0 +1,356 @@ +/* DWARF 2 location expression support for GDB. + Copyright 2003 Free Software Foundation, Inc. + Contributed by Daniel Jacobowitz, MontaVista Software, 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "ui-out.h" +#include "value.h" +#include "frame.h" +#include "gdbcore.h" +#include "target.h" +#include "inferior.h" +#include "ax.h" +#include "ax-gdb.h" +#include "regcache.h" + +#include "elf/dwarf2.h" +#include "dwarf2expr.h" +#include "dwarf2loc.h" + +#include "gdb_string.h" + +#ifndef DWARF2_REG_TO_REGNUM +#define DWARF2_REG_TO_REGNUM(REG) (REG) +#endif + +/* This is the baton used when performing dwarf2 expression + evaluation. */ +struct dwarf_expr_baton +{ + struct frame_info *frame; + struct objfile *objfile; +}; + +/* Helper functions for dwarf2_evaluate_loc_desc. */ + +/* Using the frame specified in BATON, read register REGNUM. The lval + type will be returned in LVALP, and for lval_memory the register + save address will be returned in ADDRP. */ +static CORE_ADDR +dwarf_expr_read_reg (void *baton, int dwarf_regnum, enum lval_type *lvalp, + CORE_ADDR *addrp) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + CORE_ADDR result; + char *buf; + int optimized, regnum, realnum, regsize; + + regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum); + regsize = register_size (current_gdbarch, regnum); + buf = (char *) alloca (regsize); + + frame_register (debaton->frame, regnum, &optimized, lvalp, addrp, &realnum, + buf); + result = extract_address (buf, regsize); + + return result; +} + +/* Read memory at ADDR (length LEN) into BUF. */ + +static void +dwarf_expr_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len) +{ + read_memory (addr, buf, len); +} + +/* Using the frame specified in BATON, find the location expression + describing the frame base. Return a pointer to it in START and + its length in LENGTH. */ +static void +dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length) +{ + struct symbol *framefunc; + struct dwarf2_locexpr_baton *symbaton; + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + framefunc = get_frame_function (debaton->frame); + symbaton = SYMBOL_LOCATION_BATON (framefunc); + *start = symbaton->data; + *length = symbaton->size; +} + +/* Using the objfile specified in BATON, find the address for the + current thread's thread-local storage with offset OFFSET. */ +static CORE_ADDR +dwarf_expr_tls_address (void *baton, CORE_ADDR offset) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + CORE_ADDR addr; + + if (target_get_thread_local_address_p ()) + addr = target_get_thread_local_address (inferior_ptid, + debaton->objfile, + offset); + else + error ("Cannot find thread-local variables on this target"); + + return addr; +} + +/* Evaluate a location description, starting at DATA and with length + SIZE, to find the current location of variable VAR in the context + of FRAME. */ +static struct value * +dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + unsigned char *data, unsigned short size, + struct objfile *objfile) +{ + CORE_ADDR result; + struct value *retval; + struct dwarf_expr_baton baton; + struct dwarf_expr_context *ctx; + + baton.frame = frame; + baton.objfile = objfile; + + ctx = new_dwarf_expr_context (); + ctx->baton = &baton; + ctx->read_reg = dwarf_expr_read_reg; + ctx->read_mem = dwarf_expr_read_mem; + ctx->get_frame_base = dwarf_expr_frame_base; + ctx->get_tls_address = dwarf_expr_tls_address; + + dwarf_expr_eval (ctx, data, size); + + retval = allocate_value (SYMBOL_TYPE (var)); + VALUE_BFD_SECTION (retval) = SYMBOL_BFD_SECTION (var); + + if (ctx->in_reg) + { + store_unsigned_integer (VALUE_CONTENTS_RAW (retval), + TYPE_LENGTH (SYMBOL_TYPE (var)), + dwarf_expr_fetch (ctx, 0)); + VALUE_LVAL (retval) = lval_register; + VALUE_REGNO (retval) = ctx->regnum; + } + else + { + result = dwarf_expr_fetch (ctx, 0); + VALUE_LVAL (retval) = lval_memory; + VALUE_LAZY (retval) = 1; + VALUE_ADDRESS (retval) = result; + } + + free_dwarf_expr_context (ctx); + + return retval; +} + + + + + +/* Helper functions and baton for dwarf2_loc_desc_needs_frame. */ + +struct needs_frame_baton +{ + int needs_frame; +}; + +/* Reads from registers do require a frame. */ +static CORE_ADDR +needs_frame_read_reg (void *baton, int regnum, enum lval_type *lvalp, + CORE_ADDR *addrp) +{ + struct needs_frame_baton *nf_baton = baton; + nf_baton->needs_frame = 1; + return 1; +} + +/* Reads from memory do not require a frame. */ +static void +needs_frame_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len) +{ + memset (buf, 0, len); +} + +/* Frame-relative accesses do require a frame. */ +static void +needs_frame_frame_base (void *baton, unsigned char **start, size_t * length) +{ + static char lit0 = DW_OP_lit0; + struct needs_frame_baton *nf_baton = baton; + + *start = &lit0; + *length = 1; + + nf_baton->needs_frame = 1; +} + +/* Thread-local accesses do require a frame. */ +static CORE_ADDR +needs_frame_tls_address (void *baton, CORE_ADDR offset) +{ + struct needs_frame_baton *nf_baton = baton; + nf_baton->needs_frame = 1; + return 1; +} + +/* Return non-zero iff the location expression at DATA (length SIZE) + requires a frame to evaluate. */ + +static int +dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size) +{ + struct needs_frame_baton baton; + struct dwarf_expr_context *ctx; + + baton.needs_frame = 0; + + ctx = new_dwarf_expr_context (); + ctx->baton = &baton; + ctx->read_reg = needs_frame_read_reg; + ctx->read_mem = needs_frame_read_mem; + ctx->get_frame_base = needs_frame_frame_base; + ctx->get_tls_address = needs_frame_tls_address; + + dwarf_expr_eval (ctx, data, size); + + free_dwarf_expr_context (ctx); + + return baton.needs_frame; +} + + + + +/* Return the value of SYMBOL in FRAME using the DWARF-2 expression + evaluator to calculate the location. */ +static struct value * +locexpr_read_variable (struct symbol *symbol, struct frame_info *frame) +{ + struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + struct value *val; + val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size, + dlbaton->objfile); + + return val; +} + +/* Return non-zero iff we need a frame to evaluate SYMBOL. */ +static int +locexpr_read_needs_frame (struct symbol *symbol) +{ + struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size); +} + +/* Print a natural-language description of SYMBOL to STREAM. */ +static int +locexpr_describe_location (struct symbol *symbol, struct ui_file *stream) +{ + /* FIXME: be more extensive. */ + struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + + if (dlbaton->size == 1 + && dlbaton->data[0] >= DW_OP_reg0 + && dlbaton->data[0] <= DW_OP_reg31) + { + int regno = DWARF2_REG_TO_REGNUM (dlbaton->data[0] - DW_OP_reg0); + fprintf_filtered (stream, + "a variable in register %s", REGISTER_NAME (regno)); + return 1; + } + + fprintf_filtered (stream, + "a variable with complex or multiple locations (DWARF2)"); + return 1; +} + + +/* Describe the location of SYMBOL as an agent value in VALUE, generating + any necessary bytecode in AX. + + NOTE drow/2003-02-26: This function is extremely minimal, because + doing it correctly is extremely complicated and there is no + publicly available stub with tracepoint support for me to test + against. When there is one this function should be revisited. */ + +void +locexpr_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax, + struct axs_value * value) +{ + struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + + if (dlbaton->size == 0) + error ("Symbol \"%s\" has been optimized out.", + SYMBOL_PRINT_NAME (symbol)); + + if (dlbaton->size == 1 + && dlbaton->data[0] >= DW_OP_reg0 + && dlbaton->data[0] <= DW_OP_reg31) + { + value->kind = axs_lvalue_register; + value->u.reg = dlbaton->data[0] - DW_OP_reg0; + } + else if (dlbaton->data[0] == DW_OP_regx) + { + ULONGEST reg; + read_uleb128 (dlbaton->data + 1, dlbaton->data + dlbaton->size, + ®); + value->kind = axs_lvalue_register; + value->u.reg = reg; + } + else if (dlbaton->data[0] == DW_OP_fbreg) + { + /* And this is worse than just minimal; we should honor the frame base + as above. */ + int frame_reg; + LONGEST frame_offset; + unsigned char *buf_end; + + buf_end = read_sleb128 (dlbaton->data + 1, dlbaton->data + dlbaton->size, + &frame_offset); + if (buf_end != dlbaton->data + dlbaton->size) + error ("Unexpected opcode after DW_OP_fbreg for symbol \"%s\".", + SYMBOL_PRINT_NAME (symbol)); + + TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset); + ax_reg (ax, frame_reg); + ax_const_l (ax, frame_offset); + ax_simple (ax, aop_add); + + ax_const_l (ax, frame_offset); + ax_simple (ax, aop_add); + value->kind = axs_lvalue_memory; + } + else + error ("Unsupported DWARF opcode in the location of \"%s\".", + SYMBOL_PRINT_NAME (symbol)); +} + +/* The set of location functions used with the DWARF-2 expression + evaluator. */ +struct location_funcs dwarf2_locexpr_funcs = { + locexpr_read_variable, + locexpr_read_needs_frame, + locexpr_describe_location, + locexpr_tracepoint_var_ref +}; diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h new file mode 100644 index 00000000000..fde132922ac --- /dev/null +++ b/gdb/dwarf2loc.h @@ -0,0 +1,39 @@ +/* Dwarf2 location expression support for GDB. + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (DWARF2LOC_H) +#define DWARF2LOC_H + +/* This header is private to the DWARF-2 reader. It is shared between + dwarf2read.c and dwarf2loc.c. */ + +/* The symbol location baton type used by the DWARF-2 reader (i.e. + SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). */ + +struct dwarf2_locexpr_baton +{ + unsigned char *data; + unsigned short size; + struct objfile *objfile; +}; + +extern struct location_funcs dwarf2_locexpr_funcs; + +#endif diff --git a/gdb/observer.c b/gdb/observer.c new file mode 100644 index 00000000000..92ec48e614f --- /dev/null +++ b/gdb/observer.c @@ -0,0 +1,192 @@ +/* GDB Notifications to Observers. + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* 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 + observers. + + This file implements an internal generic low-level event notification + mechanism based on the Observer paradigm described in the book "Design + Patterns". This generic event notification mechansim is then re-used + to implement the exported high-level notification management routines + 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 + 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, + 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 + deallocate the data when attaching the callback. + + This file is currently maintained by hand, but the long term plan + if the number of different notifications starts growing is to create + a new script (observer.sh) that would generate this file, and the + associated documentation. */ + +#include "defs.h" +#include "observer.h" + +/* The internal generic observer. */ + +typedef void (generic_observer_notification_ftype) (const void *data, + const void *args); + +struct observer +{ + generic_observer_notification_ftype *notify; + /* No memory management needed for the following field for now. */ + void *data; +}; + +/* A list of observers, maintained by the subject. A subject is + actually represented by its list of observers. */ + +struct observer_list +{ + struct observer_list *next; + struct observer *observer; +}; + +/* Allocate a struct observer_list, intended to be used as a node + in the list of observers maintained by a subject. */ + +static struct observer_list * +xalloc_observer_list_node (void) +{ + struct observer_list *node = XMALLOC (struct observer_list); + node->observer = XMALLOC (struct observer); + return node; +} + +/* The opposite of xalloc_observer_list_node, frees the memory for + the given node. */ + +static void +xfree_observer_list_node (struct observer_list *node) +{ + xfree (node->observer); + xfree (node); +} + +/* Attach the callback NOTIFY to a SUBJECT. The DATA is also stored, + in order for the subject to provide it back to the observer during + a notification. */ + +static struct observer * +generic_observer_attach (struct observer_list **subject, + generic_observer_notification_ftype * notify, + void *data) +{ + struct observer_list *observer_list = xalloc_observer_list_node (); + + observer_list->next = *subject; + observer_list->observer->notify = notify; + observer_list->observer->data = data; + *subject = observer_list; + + return observer_list->observer; +} + +/* Remove the given OBSERVER from the SUBJECT. Once detached, OBSERVER + should no longer be used, as it is no longer valid. */ + +static void +generic_observer_detach (struct observer_list **subject, + const struct observer *observer) +{ + struct observer_list *previous_node = NULL; + struct observer_list *current_node = *subject; + + while (current_node != NULL) + { + if (current_node->observer == observer) + { + if (previous_node != NULL) + previous_node->next = current_node->next; + else + *subject = current_node->next; + xfree_observer_list_node (current_node); + return; + } + previous_node = current_node; + current_node = current_node->next; + } + + /* We should never reach this point. However, this should not be + a very serious error, so simply report a warning to the user. */ + warning ("Failed to detach observer"); +} + +/* Send a notification to all the observers of SUBJECT. ARGS is passed to + all observers as an argument to the notification callback. */ + +static void +generic_observer_notify (struct observer_list *subject, const void *args) +{ + struct observer_list *current_node = subject; + + while (current_node != NULL) + { + (*current_node->observer->notify) (current_node->observer->data, args); + current_node = current_node->next; + } +} + +/* normal_stop notifications. */ + +static struct observer_list *normal_stop_subject = NULL; + +static void +observer_normal_stop_notification_stub (const void *data, + const void *unused_args) +{ + observer_normal_stop_ftype *notify = (observer_normal_stop_ftype *) data; + (*notify) (); +} + +struct observer * +observer_attach_normal_stop (observer_normal_stop_ftype *f) +{ + return generic_observer_attach (&normal_stop_subject, + &observer_normal_stop_notification_stub, + (void *) f); +} + +void +observer_detach_normal_stop (struct observer *observer) +{ + generic_observer_detach (&normal_stop_subject, observer); +} + +void +observer_notify_normal_stop (void) +{ + generic_observer_notify (normal_stop_subject, NULL); +} diff --git a/gdb/observer.h b/gdb/observer.h new file mode 100644 index 00000000000..8b9a6db5607 --- /dev/null +++ b/gdb/observer.h @@ -0,0 +1,35 @@ +/* GDB Notifications to Observers. + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef OBSERVER_H +#define OBSERVER_H + +struct observer; + +/* normal_stop notifications. */ + +typedef void (observer_normal_stop_ftype) (void); + +extern struct observer * + observer_attach_normal_stop (observer_normal_stop_ftype *f); +extern void observer_detach_normal_stop (struct observer *observer); +extern void observer_notify_normal_stop (void); + +#endif /* OBSERVER_H */ diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c new file mode 100644 index 00000000000..f935ea4094c --- /dev/null +++ b/gdb/tui/tui-interp.c @@ -0,0 +1,180 @@ +/* TUI Interpreter definitions for GDB, the GNU debugger. + + Copyright 2003 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "interps.h" +#include "top.h" +#include "event-top.h" +#include "event-loop.h" +#include "ui-out.h" +#include "tui/tuiData.h" +#include "readline/readline.h" +#include "tui/tuiWin.h" +#include "tui/tui.h" +#include "tui/tuiIO.h" + +/* Cleanup the tui before exiting. */ + +static void +tui_exit (void) +{ + /* Disable the tui. Curses mode is left leaving the screen + in a clean state (see endwin()). */ + tui_disable (); +} + +/* These implement the TUI interpreter. */ + +static void * +tui_init (void) +{ + /* Install exit handler to leave the screen in a good shape. */ + atexit (tui_exit); + + initializeStaticData (); + + tui_initialize_io (); + tui_initialize_readline (); + + return NULL; +} + +static int +tui_resume (void *data) +{ + gdb_setup_readline (); + tui_enable (); + return 1; +} + +static int +tui_suspend (void *data) +{ + tui_disable (); + return 1; +} + +/* Display the prompt if we are silent. */ + +static int +tui_display_prompt_p (void *data) +{ + if (interp_quiet_p (NULL)) + return 0; + else + return 1; +} + +static int +tui_exec (void *data, const char *command_str) +{ + internal_error (__FILE__, __LINE__, "tui_exec called"); +} + + +/* Initialize all the necessary variables, start the event loop, + register readline, and stdin, start the loop. */ + +static void +tui_command_loop (void *data) +{ + int length; + char *a_prompt; + char *gdb_prompt = get_prompt (); + + /* If we are using readline, set things up and display the first + prompt, otherwise just print the prompt. */ + if (async_command_editing_p) + { + /* 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 *) xmalloc (length); + strcpy (a_prompt, PREFIX (0)); + strcat (a_prompt, gdb_prompt); + strcat (a_prompt, SUFFIX (0)); + rl_callback_handler_install (a_prompt, input_handler); + } + else + display_gdb_prompt (0); + + /* 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. */ + while (1) + { + int result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); + if (result < 0) + break; + + /* Update gdb output according to TUI mode. Since catch_errors + preserves the uiout from changing, this must be done at top + level of event loop. */ + if (tui_active) + uiout = tui_out; + else + uiout = tui_old_uiout; + + if (result == 0) + { + /* FIXME: this should really be a call to a hook that is + interface specific, because interfaces can display the + 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, + after_char_processing_hook won't be called from + rl_callback_read_char_wrapper. Using a cleanup there + won't work, since we want this function to be called + after a new prompt is printed. */ + 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. */ + } + } + + /* We are done with the event loop. There are no more event sources + to listen to. So we exit GDB. */ + return; +} + +void +_initialize_tui_interp (void) +{ + static const struct interp_procs procs = { + tui_init, + tui_resume, + tui_suspend, + tui_exec, + tui_display_prompt_p, + tui_command_loop, + }; + struct interp *tui_interp; + + /* Create a default uiout builder for the TUI. */ + tui_out = tui_out_new (gdb_stdout); + interp_add (interp_new ("tui", NULL, tui_out, &procs)); +} diff --git a/libiberty/acconfig.h b/libiberty/acconfig.h new file mode 100644 index 00000000000..364cb41da7c --- /dev/null +++ b/libiberty/acconfig.h @@ -0,0 +1,3 @@ +/* Define to `unsigned long' if <sys/types.h> doesn't define. */ +#undef uintptr_t + diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c new file mode 100644 index 00000000000..b001b38ef66 --- /dev/null +++ b/libiberty/lrealpath.c @@ -0,0 +1,128 @@ +/* Libiberty realpath. Like realpath, but more consistent behavior. + Based on gdb_realpath from GDB. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of the libiberty library. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + +@deftypefn Replacement {const char*} lrealpath (const char *@var{name}) + +Given a pointer to a string containing a pathname, returns a canonical +version of the filename. Symlinks will be resolved, and ``.'' and ``..'' +components will be simplified. The returned value will be allocated using +@code{malloc}, or @code{NULL} will be returned on a memory allocation error. + +@end deftypefn + +*/ + +#include "config.h" +#include "ansidecl.h" +#include "libiberty.h" + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +/* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */ +#if defined(HAVE_CANONICALIZE_FILE_NAME) \ + && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME) +extern char *canonicalize_file_name (const char *); +#endif + +#if defined(HAVE_REALPATH) +# if defined (PATH_MAX) +# define REALPATH_LIMIT PATH_MAX +# else +# if defined (MAXPATHLEN) +# define REALPATH_LIMIT MAXPATHLEN +# endif +# endif +#endif + +char * +lrealpath (filename) + const char *filename; +{ + /* Method 1: The system has a compile time upper bound on a filename + path. Use that and realpath() to canonicalize the name. This is + the most common case. Note that, if there isn't a compile time + upper bound, you want to avoid realpath() at all costs. */ +#if defined(REALPATH_LIMIT) + { + char buf[REALPATH_LIMIT]; + const char *rp = realpath (filename, buf); + if (rp == NULL) + rp = filename; + return strdup (rp); + } +#endif /* REALPATH_LIMIT */ + + /* Method 2: The host system (i.e., GNU) has the function + canonicalize_file_name() which malloc's a chunk of memory and + returns that, use that. */ +#if defined(HAVE_CANONICALIZE_FILE_NAME) + { + char *rp = canonicalize_file_name (filename); + if (rp == NULL) + return strdup (filename); + else + return rp; + } +#endif + + /* Method 3: Now we're getting desperate! The system doesn't have a + compile time buffer size and no alternative function. Query the + OS, using pathconf(), for the buffer limit. Care is needed + though, some systems do not limit PATH_MAX (return -1 for + pathconf()) making it impossible to pass a correctly sized buffer + to realpath() (it could always overflow). On those systems, we + skip this. */ +#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) + { + /* Find out the max path size. */ + long path_max = pathconf ("/", _PC_PATH_MAX); + if (path_max > 0) + { + /* PATH_MAX is bounded. */ + char *buf, *rp, *ret; + buf = malloc (path_max); + if (buf == NULL) + return NULL; + rp = realpath (filename, buf); + ret = strdup (rp ? rp : filename); + free (buf); + return ret; + } + } +#endif + + /* This system is a lost cause, just duplicate the filename. */ + return strdup (filename); +} diff --git a/libiberty/physmem.c b/libiberty/physmem.c new file mode 100644 index 00000000000..9185c1224e8 --- /dev/null +++ b/libiberty/physmem.c @@ -0,0 +1,305 @@ +/* Calculate the size of physical memory. + Copyright 2000, 2001, 2003 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if HAVE_UNISTD_H +# include <unistd.h> +#endif + +#if HAVE_SYS_PSTAT_H +# include <sys/pstat.h> +#endif + +#if HAVE_SYS_SYSMP_H +# include <sys/sysmp.h> +#endif + +#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H +# include <sys/sysinfo.h> +# include <machine/hal_sysinfo.h> +#endif + +#if HAVE_SYS_TABLE_H +# include <sys/table.h> +#endif + +#include <sys/types.h> + +#if HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif + +#if HAVE_SYS_SYSCTL_H +# include <sys/sysctl.h> +#endif + +#if HAVE_SYS_SYSTEMCFG_H +# include <sys/systemcfg.h> +#endif + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +/* MEMORYSTATUSEX is missing from older windows headers, so define + a local replacement. */ +typedef struct +{ + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} lMEMORYSTATUSEX; +typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); +#endif + +#include "libiberty.h" + +/* Return the total amount of physical memory. */ +double +physmem_total () +{ +#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE + { /* This works on linux-gnu, solaris2 and cygwin. */ + double pages = sysconf (_SC_PHYS_PAGES); + double pagesize = sysconf (_SC_PAGESIZE); + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } +#endif + +#if HAVE_PSTAT_GETSTATIC + { /* This works on hpux11. */ + struct pst_static pss; + if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)) + { + double pages = pss.physical_memory; + double pagesize = pss.page_size; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE + { /* This works on irix6. */ + struct rminfo realmem; + if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) + { + double pagesize = sysconf (_SC_PAGESIZE); + double pages = realmem.physmem; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_GETSYSINFO && defined GSI_PHYSMEM + { /* This works on Tru64 UNIX V4/5. */ + int physmem; + + if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem), + NULL, NULL, NULL) == 1) + { + double kbytes = physmem; + + if (0 <= kbytes) + return kbytes * 1024.0; + } + } +#endif + +#if HAVE_SYSCTL && defined HW_PHYSMEM + { /* This works on *bsd and darwin. */ + unsigned int physmem; + size_t len = sizeof physmem; + static int mib[2] = { CTL_HW, HW_PHYSMEM }; + + if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0 + && len == sizeof (physmem)) + return (double) physmem; + } +#endif + +#if HAVE__SYSTEM_CONFIGURATION + /* This works on AIX. */ + return _system_configuration.physmem; +#endif + +#if defined _WIN32 + { /* this works on windows */ + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle ("kernel32.dll"); + + if (!h) + return 0.0; + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) + { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof lms_ex; + if (!pfnex (&lms_ex)) + return 0.0; + return (double) lms_ex.ullTotalPhys; + } + + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB. */ + else + { + MEMORYSTATUS ms; + GlobalMemoryStatus (&ms); + return (double) ms.dwTotalPhys; + } + } +#endif + + /* Return 0 if we can't determine the value. */ + return 0; +} + +/* Return the amount of physical memory available. */ +double +physmem_available () +{ +#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE + { /* This works on linux-gnu, solaris2 and cygwin. */ + double pages = sysconf (_SC_AVPHYS_PAGES); + double pagesize = sysconf (_SC_PAGESIZE); + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } +#endif + +#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC + { /* This works on hpux11. */ + struct pst_static pss; + struct pst_dynamic psd; + if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) + && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) + { + double pages = psd.psd_free; + double pagesize = pss.page_size; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE + { /* This works on irix6. */ + struct rminfo realmem; + if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) + { + double pagesize = sysconf (_SC_PAGESIZE); + double pages = realmem.availrmem; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_TABLE && defined TBL_VMSTATS + { /* This works on Tru64 UNIX V4/5. */ + struct tbl_vmstats vmstats; + + if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) + { + double pages = vmstats.free_count; + double pagesize = vmstats.pagesize; + + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSCTL && defined HW_USERMEM + { /* This works on *bsd and darwin. */ + unsigned int usermem; + size_t len = sizeof usermem; + static int mib[2] = { CTL_HW, HW_USERMEM }; + + if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 + && len == sizeof (usermem)) + return (double) usermem; + } +#endif + +#if defined _WIN32 + { /* this works on windows */ + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle ("kernel32.dll"); + + if (!h) + return 0.0; + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) + { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof lms_ex; + if (!pfnex (&lms_ex)) + return 0.0; + return (double) lms_ex.ullAvailPhys; + } + + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB */ + else + { + MEMORYSTATUS ms; + GlobalMemoryStatus (&ms); + return (double) ms.dwAvailPhys; + } + } +#endif + + /* Guess 25% of physical memory. */ + return physmem_total () / 4; +} + + +#if DEBUG + +# include <stdio.h> +# include <stdlib.h> + +int +main () +{ + printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); + exit (0); +} + +#endif /* DEBUG */ + +/* +Local Variables: +compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c" +End: +*/ |