summaryrefslogtreecommitdiff
path: root/chromium/third_party/codesighs
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/codesighs')
-rw-r--r--chromium/third_party/codesighs/LICENSE567
-rw-r--r--chromium/third_party/codesighs/Makefile.in75
-rw-r--r--chromium/third_party/codesighs/README.chromium18
-rwxr-xr-xchromium/third_party/codesighs/autosummary.unix.bash250
-rwxr-xr-xchromium/third_party/codesighs/autosummary.win.bash211
-rwxr-xr-xchromium/third_party/codesighs/basesummary.unix.bash254
-rwxr-xr-xchromium/third_party/codesighs/basesummary.win.bash224
-rw-r--r--chromium/third_party/codesighs/codesighs.c1075
-rw-r--r--chromium/third_party/codesighs/codesighs.gyp61
-rw-r--r--chromium/third_party/codesighs/maptsvdifftool.c1311
-rw-r--r--chromium/third_party/codesighs/msdump2symdb.c1090
-rw-r--r--chromium/third_party/codesighs/msmap.h149
-rw-r--r--chromium/third_party/codesighs/msmap2tsv.c2237
-rw-r--r--chromium/third_party/codesighs/nm2tsv.c505
-rwxr-xr-xchromium/third_party/codesighs/nm_wrap_osx.pl105
-rwxr-xr-xchromium/third_party/codesighs/readelf_wrap.pl192
16 files changed, 8324 insertions, 0 deletions
diff --git a/chromium/third_party/codesighs/LICENSE b/chromium/third_party/codesighs/LICENSE
new file mode 100644
index 00000000000..bc8f037c06d
--- /dev/null
+++ b/chromium/third_party/codesighs/LICENSE
@@ -0,0 +1,567 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
+ ----------------------------------------------------------------------
+
+ AMENDMENTS
+
+ The Netscape Public License Version 1.1 ("NPL") consists of the
+ Mozilla Public License Version 1.1 with the following Amendments,
+ including Exhibit A-Netscape Public License. Files identified with
+ "Exhibit A-Netscape Public License" are governed by the Netscape
+ Public License Version 1.1.
+
+ Additional Terms applicable to the Netscape Public License.
+ I. Effect.
+ These additional terms described in this Netscape Public
+ License -- Amendments shall apply to the Mozilla Communicator
+ client code and to all Covered Code under this License.
+
+ II. "Netscape's Branded Code" means Covered Code that Netscape
+ distributes and/or permits others to distribute under one or more
+ trademark(s) which are controlled by Netscape but which are not
+ licensed for use under this License.
+
+ III. Netscape and logo.
+ This License does not grant any rights to use the trademarks
+ "Netscape", the "Netscape N and horizon" logo or the "Netscape
+ lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
+ "Smart Browsing" even if such marks are included in the Original
+ Code or Modifications.
+
+ IV. Inability to Comply Due to Contractual Obligation.
+ Prior to licensing the Original Code under this License, Netscape
+ has licensed third party code for use in Netscape's Branded Code.
+ To the extent that Netscape is limited contractually from making
+ such third party code available under this License, Netscape may
+ choose to reintegrate such code into Covered Code without being
+ required to distribute such code in Source Code form, even if
+ such code would otherwise be considered "Modifications" under
+ this License.
+
+ V. Use of Modifications and Covered Code by Initial Developer.
+ V.1. In General.
+ The obligations of Section 3 apply to Netscape, except to
+ the extent specified in this Amendment, Section V.2 and V.3.
+
+ V.2. Other Products.
+ Netscape may include Covered Code in products other than the
+ Netscape's Branded Code which are released by Netscape
+ during the two (2) years following the release date of the
+ Original Code, without such additional products becoming
+ subject to the terms of this License, and may license such
+ additional products on different terms from those contained
+ in this License.
+
+ V.3. Alternative Licensing.
+ Netscape may license the Source Code of Netscape's Branded
+ Code, including Modifications incorporated therein, without
+ such Netscape Branded Code becoming subject to the terms of
+ this License, and may license such Netscape Branded Code on
+ different terms from those contained in this License.
+
+ VI. Litigation.
+ Notwithstanding the limitations of Section 11 above, the
+ provisions regarding litigation in Section 11(a), (b) and (c) of
+ the License shall apply to all disputes relating to this License.
+
+ EXHIBIT A-Netscape Public License.
+
+ "The contents of this file are subject to the Netscape Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/NPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1998-1999 Netscape Communications Corporation. All
+ Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the _____ license (the "[___] License"), in which case
+ the provisions of [______] License are applicable instead of
+ those above. If you wish to allow use of your version of this
+ file only under the terms of the [____] License and not to allow
+ others to use your version of this file under the NPL, indicate
+ your decision by deleting the provisions above and replace them
+ with the notice and other provisions required by the [___]
+ License. If you do not delete the provisions above, a recipient
+ may use your version of this file under either the NPL or the
+ [___] License."
diff --git a/chromium/third_party/codesighs/Makefile.in b/chromium/third_party/codesighs/Makefile.in
new file mode 100644
index 00000000000..e243f2d325b
--- /dev/null
+++ b/chromium/third_party/codesighs/Makefile.in
@@ -0,0 +1,75 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Garrett Arch Blythe
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+REQUIRES = $(NULL)
+
+CSRCS += \
+ codesighs.c \
+ maptsvdifftool.c \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+CSRCS += \
+ msmap2tsv.c \
+ msdump2symdb.c \
+ $(NULL)
+else
+CSRCS += \
+ nm2tsv.c \
+ $(NULL)
+endif
+
+SIMPLE_PROGRAMS = $(CSRCS:.c=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_ARCH),WINNT)
+OS_LIBS += \
+ imagehlp.lib \
+ $(NULL)
+endif
+
+
+include $(topsrcdir)/config/rules.mk
diff --git a/chromium/third_party/codesighs/README.chromium b/chromium/third_party/codesighs/README.chromium
new file mode 100644
index 00000000000..b738926ce61
--- /dev/null
+++ b/chromium/third_party/codesighs/README.chromium
@@ -0,0 +1,18 @@
+Name: codesighs
+URL: http://hg.mozilla.org/mozilla-central/tools/codesighs
+Version: unknown
+License: MPL 1.1/GPL 2.0/LGPL 2.1
+Security Critical: no
+
+Description:
+This is Chromium's copy of the Mozilla codesighs tool.
+
+Originally obtained from Mozilla's Mercurial repository
+on 17 April 2009.
+
+The LICENSE from http://hg.mozilla.org/mozilla-central has been copied
+here.
+
+There are no local changes to the code itself.
+
+A codesighs.gyp file has been added for building with Chromium.
diff --git a/chromium/third_party/codesighs/autosummary.unix.bash b/chromium/third_party/codesighs/autosummary.unix.bash
new file mode 100755
index 00000000000..a35f92a8906
--- /dev/null
+++ b/chromium/third_party/codesighs/autosummary.unix.bash
@@ -0,0 +1,250 @@
+#!/bin/bash
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is autosummary.linx.bash code, released
+# Oct 10, 2002.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Garrett Arch Blythe, 10-October-2002
+# Simon Fraser <sfraser@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Check for optional objdir
+#
+if [ "$1" = "-o" ]; then
+OBJROOT="$2"
+shift
+shift
+else
+OBJROOT="./mozilla"
+fi
+
+if [ "$1" = "-s" ]; then
+SRCROOT="$2"
+shift
+shift
+else
+SRCROOT="./mozilla"
+fi
+
+#
+# A little help for my friends.
+#
+if [ "-h" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "--help" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "" == "$1" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$2" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$3" ]; then
+ SHOWHELP="1"
+fi
+
+
+#
+# Show the help if required.
+#
+if [ $SHOWHELP ]; then
+ echo "usage: $0 <save_results> <old_results> <summary>"
+ echo " <save_results> is a file that will receive the results of this run."
+ echo " This file can be used in a future run as the old results."
+ echo " <old_results> is a results file from a previous run."
+ echo " It is used to diff with current results and come up with a summary"
+ echo " of changes."
+ echo " It is OK if the file does not exist, just supply the argument."
+ echo " <summary> is a file which will contain a human readable report."
+ echo " This file is most useful by providing more information than the"
+ echo " normally single digit output of this script."
+ echo ""
+ echo "Run this command from the parent directory of the mozilla tree."
+ echo ""
+ echo "This command will output two numbers to stdout that will represent"
+ echo " the total size of all code and data, and a delta from the prior."
+ echo " the old results."
+ echo "For much more detail on size drifts refer to the summary report."
+ echo ""
+ echo "This tool reports on all executables in the directory tree."
+ exit
+fi
+
+#
+# Stash our arguments away.
+#
+COPYSORTTSV="$1"
+OLDTSVFILE="$2"
+SUMMARYFILE="$3"
+
+OSTYPE=`uname -s`
+
+#
+# On Mac OS X, use the --zerodrift option to maptsvdifftool
+#
+if [ $OSTYPE == "Darwin" ]; then
+ZERODRIFT="--zerodrift"
+else
+ZERODRIFT=""
+fi
+
+#
+# Create our temporary directory.
+# mktemp on Darwin doesn't support -d (suckage)
+#
+if [ $OSTYPE == "Darwin" ]; then
+ZERODRIFT="--zerodrift"
+MYTMPDIR=`mktemp ./codesighs.tmp.XXXXXXXX`
+rm $MYTMPDIR
+mkdir $MYTMPDIR
+else
+MYTMPDIR=`mktemp -d ./codesighs.tmp.XXXXXXXX`
+fi
+
+#
+# Find all relevant files.
+#
+ALLFILES="$MYTMPDIR/allfiles.list"
+
+if [ $OSTYPE == "Darwin" ] || [ $OSTYPE == "SunOS" ]; then
+find $OBJROOT/dist/bin ! -type d > $ALLFILES
+else
+find $OBJROOT/dist/bin -not -type d > $ALLFILES
+fi
+
+# Check whether we have 'eu-readelf' or 'readelf' available.
+# If we do, it will give more accurate symbol sizes than nm.
+
+if [ $OSTYPE == "Darwin" ]; then
+ USE_READELF=
+else
+READELF_PROG=`which eu-readelf 2>/dev/null | grep /eu-readelf$`
+if test "$READELF_PROG"; then
+ USE_READELF=1
+else
+ READELF_PROG=`which readelf 2>/dev/null | grep /readelf$`
+ if test "$READELF_PROG"; then
+ # Check whether we need -W
+ if readelf --help | grep "\--wide" >&/dev/null; then
+ READELF_PROG="readelf -W"
+ else
+ READELF_PROG="readelf"
+ fi
+ USE_READELF=1
+ else
+ USE_READELF=
+ fi
+fi
+fi
+
+RAWTSVFILE="$MYTMPDIR/raw.tsv"
+if test "$USE_READELF"; then
+export READELF_PROG
+xargs -n 1 $SRCROOT/tools/codesighs/readelf_wrap.pl < $ALLFILES > $RAWTSVFILE 2> /dev/null
+else
+
+#
+# Produce the cumulative nm output.
+# We are very particular on what switches to use.
+# nm --format=bsd --size-sort --print-file-name --demangle
+#
+# Darwin (Mac OS X) has a lame nm that we have to wrap in a perl
+# script to get decent output.
+#
+NMRESULTS="$MYTMPDIR/nm.txt"
+if [ $OSTYPE == "Darwin" ]; then
+xargs -n 1 $SRCROOT/tools/codesighs/nm_wrap_osx.pl < $ALLFILES > $NMRESULTS 2> /dev/null
+else
+xargs -n 1 nm --format=bsd --size-sort --print-file-name --demangle < $ALLFILES > $NMRESULTS 2> /dev/null
+fi
+
+
+#
+# Produce the TSV output.
+#
+
+$OBJROOT/dist/bin/nm2tsv --input $NMRESULTS > $RAWTSVFILE
+
+fi # USE_READELF
+
+#
+# Sort the TSV output for useful diffing and eyeballing in general.
+#
+sort -r $RAWTSVFILE > $COPYSORTTSV
+
+
+#
+# If a historical file was specified, diff it with our sorted tsv values.
+# Run it through a tool to summaries the diffs to the module
+# level report.
+# Otherwise, generate the module level report from our new data.
+#
+
+rm -f $SUMMARYFILE
+DIFFFILE="$MYTMPDIR/diff.txt"
+if [ -e $OLDTSVFILE ]; then
+ diff $OLDTSVFILE $COPYSORTTSV > $DIFFFILE
+ $OBJROOT/dist/bin/maptsvdifftool $ZERODRIFT --input $DIFFFILE >> $SUMMARYFILE
+else
+ $OBJROOT/dist/bin/codesighs --modules --input $COPYSORTTSV >> $SUMMARYFILE
+fi
+
+
+#
+# Output our numbers, that will let tinderbox specify everything all
+# at once.
+# First number is in fact the total size of all code and data in the map
+# files parsed.
+# Second number, if present, is growth/shrinkage.
+#
+
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesize:"
+fi
+$OBJROOT/dist/bin/codesighs --totalonly --input $COPYSORTTSV
+
+if [ -e $DIFFFILE ]; then
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesizeDiff:"
+fi
+ $OBJROOT/dist/bin/maptsvdifftool $ZERODRIFT --summary --input $DIFFFILE
+fi
+
+#
+# Remove our temporary directory.
+#
+rm -rf $MYTMPDIR
diff --git a/chromium/third_party/codesighs/autosummary.win.bash b/chromium/third_party/codesighs/autosummary.win.bash
new file mode 100755
index 00000000000..d501625b0ae
--- /dev/null
+++ b/chromium/third_party/codesighs/autosummary.win.bash
@@ -0,0 +1,211 @@
+#!/bin/bash
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is autosummary.win.bash code, released
+# Oct 3, 2002.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Garrett Arch Blythe, 03-October-2002
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Check for optional objdir
+#
+if [ "$1" = "-o" ]; then
+OBJROOT="$2"
+shift
+shift
+else
+OBJROOT="./mozilla"
+fi
+
+if [ "$1" = "-s" ]; then
+SRCROOT="$2"
+shift
+shift
+else
+SRCROOT="./mozilla"
+fi
+
+#
+# A little help for my friends.
+#
+if [ "-h" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "--help" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "" == "$1" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$2" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$3" ]; then
+ SHOWHELP="1"
+fi
+
+
+#
+# Show the help if required.
+#
+if [ $SHOWHELP ]; then
+ echo "usage: $0 <save_results> <old_results> <summary>"
+ echo " <save_results> is a file that will receive the results of this run."
+ echo " This file can be used in a future run as the old results."
+ echo " <old_results> is a results file from a previous run."
+ echo " It is used to diff with current results and come up with a summary"
+ echo " of changes."
+ echo " It is OK if the file does not exist, just supply the argument."
+ echo " <summary> is a file which will contain a human readable report."
+ echo " This file is most useful by providing more information than the"
+ echo " normally single digit output of this script."
+ echo ""
+ echo "Run this command from the parent directory of the mozilla tree."
+ echo ""
+ echo "This command will output two numbers to stdout that will represent"
+ echo " the total size of all code and data, and a delta from the prior."
+ echo " the old results."
+ echo "For much more detail on size drifts refer to the summary report."
+ echo ""
+ echo "This tool reports on all executables in the directory tree."
+ exit
+fi
+
+
+#
+# Stash our arguments away.
+#
+COPYSORTTSV="$1"
+OLDTSVFILE="$2"
+SUMMARYFILE="$3"
+
+
+#
+# Create our temporary directory.
+#
+MYTMPDIR=`mktemp -d ./codesighs.tmp.XXXXXXXX`
+
+
+#
+# Find the types of files we are interested in.
+#
+ONEFINDPASS="$MYTMPDIR/onefind.list"
+/usr/bin/find $OBJROOT -type f -name "*.obj" -or -name "*.map" | while read FNAME; do
+ cygpath -m $FNAME >> $ONEFINDPASS
+done
+
+
+#
+# Find all object files.
+#
+ALLOBJSFILE="$MYTMPDIR/allobjs.list"
+grep -i "\.obj$" < $ONEFINDPASS > $ALLOBJSFILE
+
+
+#
+# Get a dump of the symbols in every object file.
+#
+ALLOBJSYMSFILE="$MYTMPDIR/allobjsyms.list"
+xargs -n 1 dumpbin.exe /symbols < $ALLOBJSFILE > $ALLOBJSYMSFILE 2> /dev/null
+
+
+#
+# Produce the symdb for the symbols in all object files.
+#
+SYMDBFILE="$MYTMPDIR/symdb.tsv"
+$OBJROOT/dist/bin/msdump2symdb --input $ALLOBJSYMSFILE | /usr/bin/sort > $SYMDBFILE 2> /dev/null
+
+
+#
+# Find all map files.
+#
+ALLMAPSFILE="$MYTMPDIR/allmaps.list"
+grep -i "\.map$" < $ONEFINDPASS > $ALLMAPSFILE
+
+
+#
+# Produce the TSV output.
+#
+RAWTSVFILE="$MYTMPDIR/raw.tsv"
+$OBJROOT/dist/bin/msmap2tsv --symdb $SYMDBFILE --batch < $ALLMAPSFILE > $RAWTSVFILE 2> /dev/null
+
+
+#
+# Sort the TSV output for useful diffing and eyeballing in general.
+#
+/usr/bin/sort -r $RAWTSVFILE > $COPYSORTTSV
+
+
+#
+# If a historical file was specified, diff it with our sorted tsv values.
+# Run it through a tool to summaries the diffs to the module
+# level report.
+# Otherwise, generate the module level report from our new data.
+#
+rm -f $SUMMARYFILE
+DIFFFILE="$MYTMPDIR/diff.txt"
+if [ -e $OLDTSVFILE ]; then
+ diff $OLDTSVFILE $COPYSORTTSV > $DIFFFILE
+ $OBJROOT/dist/bin/maptsvdifftool --negation --input $DIFFFILE | dos2unix >> $SUMMARYFILE
+else
+ $OBJROOT/dist/bin/codesighs --modules --input $COPYSORTTSV | dos2unix >> $SUMMARYFILE
+fi
+
+
+#
+# Output our numbers, that will let tinderbox specify everything all
+# at once.
+# First number is in fact the total size of all code and data in the map
+# files parsed.
+# Second number, if present, is growth/shrinkage.
+#
+
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesize:"
+fi
+$OBJROOT/dist/bin/codesighs --totalonly --input $COPYSORTTSV | dos2unix
+
+
+if [ -e $DIFFFILE ]; then
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesizeDiff:"
+fi
+ $OBJROOT/dist/bin/maptsvdifftool --negation --summary --input $DIFFFILE | dos2unix
+fi
+
+#
+# Remove our temporary directory.
+#
+rm -rf $MYTMPDIR
diff --git a/chromium/third_party/codesighs/basesummary.unix.bash b/chromium/third_party/codesighs/basesummary.unix.bash
new file mode 100755
index 00000000000..34cd298c7e3
--- /dev/null
+++ b/chromium/third_party/codesighs/basesummary.unix.bash
@@ -0,0 +1,254 @@
+#!/bin/bash
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is basesummary.linx.bash code, released
+# Nov 15, 2002.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Garrett Arch Blythe, 15-November-2002
+# Simon Fraser <sfraser@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Check for optional objdir
+#
+if [ "$1" = "-o" ]; then
+OBJROOT="$2"
+shift
+shift
+else
+OBJROOT="./mozilla"
+fi
+
+if [ "$1" = "-s" ]; then
+SRCROOT="$2"
+shift
+shift
+else
+SRCROOT="./mozilla"
+fi
+
+OSTYPE=`uname -s`
+
+if [ $OSTYPE == "Darwin" ]; then
+MANIFEST="$SRCROOT/embedding/config/basebrowser-mac-macho"
+else
+MANIFEST="$SRCROOT/embedding/config/basebrowser-unix"
+fi
+
+#
+# A little help for my friends.
+#
+if [ "-h" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "--help" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "" == "$1" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$2" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$3" ]; then
+ SHOWHELP="1"
+fi
+
+
+#
+# Show the help if required.
+#
+if [ $SHOWHELP ]; then
+ echo "usage: $0 <save_results> <old_results> <summary>"
+ echo " <save_results> is a file that will receive the results of this run."
+ echo " This file can be used in a future run as the old results."
+ echo " <old_results> is a results file from a previous run."
+ echo " It is used to diff with current results and come up with a summary"
+ echo " of changes."
+ echo " It is OK if the file does not exist, just supply the argument."
+ echo " <summary> is a file which will contain a human readable report."
+ echo " This file is most useful by providing more information than the"
+ echo " normally single digit output of this script."
+ echo ""
+ echo "Run this command from the parent directory of the mozilla tree."
+ echo ""
+ echo "This command will output two numbers to stdout that will represent"
+ echo " the total size of all code and data, and a delta from the prior."
+ echo " the old results."
+ echo "For much more detail on size drifts refer to the summary report."
+ echo ""
+ echo "This tool reports on executables listed in the following file:"
+ echo "$MANIFEST"
+ exit
+fi
+
+
+#
+# Stash our arguments away.
+#
+COPYSORTTSV="$1"
+OLDTSVFILE="$2"
+SUMMARYFILE="$3"
+
+
+#
+# On Mac OS X, use the --zerodrift option to maptsvdifftool
+#
+if [ $OSTYPE == "Darwin" ]; then
+ZERODRIFT="--zerodrift"
+else
+ZERODRIFT=""
+fi
+
+
+#
+# Create our temporary directory.
+# mktemp on Darwin doesn't support -d (suckage)
+#
+if [ $OSTYPE == "Darwin" ]; then
+MYTMPDIR=`mktemp ./codesighs.tmp.XXXXXXXX`
+rm $MYTMPDIR
+mkdir $MYTMPDIR
+else
+MYTMPDIR=`mktemp -d ./codesighs.tmp.XXXXXXXX`
+fi
+
+
+# Check whether we have 'eu-readelf' or 'readelf' available.
+# If we do, it will give more accurate symbol sizes than nm.
+
+if [ $OSTYPE == "Darwin" ]; then
+ USE_READELF=
+else
+READELF_PROG=`which eu-readelf 2>/dev/null | grep /eu-readelf$`
+if test "$READELF_PROG"; then
+ USE_READELF=1
+else
+ READELF_PROG=`which readelf 2>/dev/null | grep /readelf$`
+ if test "$READELF_PROG"; then
+ # Check whether we need -W
+ if readelf --help | grep "\--wide" >&/dev/null; then
+ READELF_PROG="readelf -W"
+ else
+ READELF_PROG="readelf"
+ fi
+ USE_READELF=1
+ else
+ USE_READELF=
+ fi
+fi
+fi
+
+#
+# Find all relevant files.
+#
+ALLFILES="$MYTMPDIR/allfiles.list"
+grep -v '[\;\[]' < $MANIFEST | grep -v '^$' | sed "s|^|${OBJROOT}/dist/bin/|" > $ALLFILES
+
+
+RAWTSVFILE="$MYTMPDIR/raw.tsv"
+
+if test "$USE_READELF"; then
+export READELF_PROG
+xargs -n 1 $SRCROOT/tools/codesighs/readelf_wrap.pl < $ALLFILES > $RAWTSVFILE
+else
+
+#
+# Produce the cumulative nm output.
+# We are very particular on what switches to use.
+# nm --format=bsd --size-sort --print-file-name --demangle
+#
+# Darwin (Mac OS X) has a lame nm that we have to wrap in a perl
+# script to get decent output.
+#
+NMRESULTS="$MYTMPDIR/nm.txt"
+if [ $OSTYPE == "Darwin" ]; then
+xargs -n 1 $SRCROOT/tools/codesighs/nm_wrap_osx.pl < $ALLFILES > $NMRESULTS 2> /dev/null
+else
+xargs -n 1 nm --format=bsd --size-sort --print-file-name --demangle < $ALLFILES > $NMRESULTS 2> /dev/null
+fi
+
+#
+# Produce the TSV output.
+#
+$OBJROOT/dist/bin/nm2tsv --input $NMRESULTS > $RAWTSVFILE
+
+fi # USE_READELF
+
+#
+# Sort the TSV output for useful diffing and eyeballing in general.
+#
+sort -r $RAWTSVFILE > $COPYSORTTSV
+
+
+#
+# If a historical file was specified, diff it with our sorted tsv values.
+# Run it through a tool to summaries the diffs to the module
+# level report.
+# Otherwise, generate the module level report from our new data.
+#
+rm -f $SUMMARYFILE
+DIFFFILE="$MYTMPDIR/diff.txt"
+if [ -e $OLDTSVFILE ]; then
+ diff $OLDTSVFILE $COPYSORTTSV > $DIFFFILE
+ $OBJROOT/dist/bin/maptsvdifftool $ZERODRIFT --input $DIFFFILE >> $SUMMARYFILE
+else
+ $OBJROOT/dist/bin/codesighs --modules --input $COPYSORTTSV >> $SUMMARYFILE
+fi
+
+
+#
+# Output our numbers, that will let tinderbox specify everything all
+# at once.
+# First number is in fact the total size of all code and data in the map
+# files parsed.
+# Second number, if present, is growth/shrinkage.
+#
+
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesize:"
+fi
+$OBJROOT/dist/bin/codesighs --totalonly --input $COPYSORTTSV
+
+if [ -e $DIFFFILE ]; then
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesizeDiff:"
+fi
+ $OBJROOT/dist/bin/maptsvdifftool $ZERODRIFT --summary --input $DIFFFILE
+fi
+
+#
+# Remove our temporary directory.
+#
+rm -rf $MYTMPDIR
diff --git a/chromium/third_party/codesighs/basesummary.win.bash b/chromium/third_party/codesighs/basesummary.win.bash
new file mode 100755
index 00000000000..1e058590607
--- /dev/null
+++ b/chromium/third_party/codesighs/basesummary.win.bash
@@ -0,0 +1,224 @@
+#!/bin/bash
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is basesummary.win.bash code, released
+# Nov 15, 2002.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Garrett Arch Blythe, 15-November-2002
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+
+#
+# Check for optional objdir
+#
+if [ "$1" = "-o" ]; then
+OBJROOT="$2"
+shift
+shift
+else
+OBJROOT="./mozilla"
+fi
+
+if [ "$1" = "-s" ]; then
+SRCROOT="$2"
+shift
+shift
+else
+SRCROOT="./mozilla"
+fi
+
+MANIFEST="$SRCROOT/embedding/config/basebrowser-win"
+
+#
+# A little help for my friends.
+#
+if [ "-h" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "--help" == "$1" ];then
+ SHOWHELP="1"
+fi
+if [ "" == "$1" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$2" ]; then
+ SHOWHELP="1"
+fi
+if [ "" == "$3" ]; then
+ SHOWHELP="1"
+fi
+
+
+#
+# Show the help if required.
+#
+if [ $SHOWHELP ]; then
+ echo "usage: $0 <save_results> <old_results> <summary>"
+ echo " <save_results> is a file that will receive the results of this run."
+ echo " This file can be used in a future run as the old results."
+ echo " <old_results> is a results file from a previous run."
+ echo " It is used to diff with current results and come up with a summary"
+ echo " of changes."
+ echo " It is OK if the file does not exist, just supply the argument."
+ echo " <summary> is a file which will contain a human readable report."
+ echo " This file is most useful by providing more information than the"
+ echo " normally single digit output of this script."
+ echo ""
+ echo "Run this command from the parent directory of the mozilla tree."
+ echo ""
+ echo "This command will output two numbers to stdout that will represent"
+ echo " the total size of all code and data, and a delta from the prior."
+ echo " the old results."
+ echo "For much more detail on size drifts refer to the summary report."
+ echo ""
+ echo "This tool reports on executables listed in the following file:"
+ echo "$MANIFEST"
+ exit
+fi
+
+
+#
+# Stash our arguments away.
+#
+COPYSORTTSV="$1"
+OLDTSVFILE="$2"
+SUMMARYFILE="$3"
+
+
+#
+# Create our temporary directory.
+#
+MYTMPDIR=`mktemp -d ./codesighs.tmp.XXXXXXXX`
+
+
+#
+# Find the types of files we are interested in.
+#
+ONEFINDPASS="$MYTMPDIR/onefind.list"
+/usr/bin/find $OBJROOT -type f -name "*.obj" -or -name "*.map" | while read FNAME; do
+ cygpath -m $FNAME >> $ONEFINDPASS
+done
+
+
+#
+# Find all object files.
+#
+ALLOBJSFILE="$MYTMPDIR/allobjs.list"
+grep -i "\.obj$" < $ONEFINDPASS > $ALLOBJSFILE
+
+
+#
+# Get a dump of the symbols in every object file.
+#
+ALLOBJSYMSFILE="$MYTMPDIR/allobjsyms.list"
+xargs -n 1 dumpbin.exe /symbols < $ALLOBJSFILE > $ALLOBJSYMSFILE 2> /dev/null
+
+
+#
+# Produce the symdb for the symbols in all object files.
+#
+SYMDBFILE="$MYTMPDIR/symdb.tsv"
+$OBJROOT/dist/bin/msdump2symdb --input $ALLOBJSYMSFILE | /usr/bin/sort > $SYMDBFILE 2> /dev/null
+
+
+#
+# Find all map files.
+#
+ALLMAPSFILE="$MYTMPDIR/allmaps.list"
+grep -i "\.map$" < $ONEFINDPASS > $ALLMAPSFILE
+
+
+#
+# Figure out which modules in specific we care about.
+# The relevant set meaning that the map file name prefix must be found
+# in the file mozilla/embedding/config/basebrowser-win.
+#
+RELEVANTSETFILE="$MYTMPDIR/relevant.set"
+grep -v '\;' < $MANIFEST | sed 's/.*\\//' | grep '\.[eEdD][xXlL][eElL]' | sed 's/\.[eEdD][xXlL][eElL]//' > $RELEVANTSETFILE
+RELEVANTARG=`xargs -n 1 echo --match-module < $RELEVANTSETFILE`
+
+
+#
+# Produce the TSV output.
+#
+RAWTSVFILE="$MYTMPDIR/raw.tsv"
+$OBJROOT/dist/bin/msmap2tsv --symdb $SYMDBFILE --batch $RELEVANTARG < $ALLMAPSFILE > $RAWTSVFILE 2> /dev/null
+
+
+#
+# Sort the TSV output for useful diffing and eyeballing in general.
+#
+/usr/bin/sort -r $RAWTSVFILE > $COPYSORTTSV
+
+
+#
+# If a historical file was specified, diff it with our sorted tsv values.
+# Run it through a tool to summaries the diffs to the module
+# level report.
+# Otherwise, generate the module level report from our new data.
+#
+rm -f $SUMMARYFILE
+DIFFFILE="$MYTMPDIR/diff.txt"
+if [ -e $OLDTSVFILE ]; then
+ diff $OLDTSVFILE $COPYSORTTSV > $DIFFFILE
+ $OBJROOT/dist/bin/maptsvdifftool --negation --input $DIFFFILE | dos2unix >> $SUMMARYFILE
+else
+ $OBJROOT/dist/bin/codesighs --modules --input $COPYSORTTSV | dos2unix >> $SUMMARYFILE
+fi
+
+
+#
+# Output our numbers, that will let tinderbox specify everything all
+# at once.
+# First number is in fact the total size of all code and data in the map
+# files parsed.
+# Second number, if present, is growth/shrinkage.
+#
+
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesize:"
+fi
+$OBJROOT/dist/bin/codesighs --totalonly --input $COPYSORTTSV | dos2unix
+
+if [ -e $DIFFFILE ]; then
+if [ $TINDERBOX_OUTPUT ]; then
+ echo -n "__codesizeDiff:"
+fi
+ $OBJROOT/dist/bin/maptsvdifftool --negation --summary --input $DIFFFILE | dos2unix
+fi
+
+#
+# Remove our temporary directory.
+#
+rm -rf $MYTMPDIR
diff --git a/chromium/third_party/codesighs/codesighs.c b/chromium/third_party/codesighs/codesighs.c
new file mode 100644
index 00000000000..f20fbb1e62d
--- /dev/null
+++ b/chromium/third_party/codesighs/codesighs.c
@@ -0,0 +1,1075 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is codesighs.c code, released
+ * Oct 3, 2002.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 03-October-2002
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg));
+#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0)
+
+
+typedef struct __struct_Options
+/*
+** Options to control how we perform.
+**
+** mProgramName Used in help text.
+** mInput File to read for input.
+** Default is stdin.
+** mInputName Name of the file.
+** mOutput Output file, append.
+** Default is stdout.
+** mOutputName Name of the file.
+** mHelp Whether or not help should be shown.
+** mModules Output module by module information.
+** mTotalOnly Only output one number, the total.
+** mMinSize Ignore lines below this size.
+** mMaxSize Ignore lines above this size.
+** mMatchScopes For a line to be processed, it should match.
+** mMachClasses For a line to be processed, it should match.
+** mMatchModules For a line to be processed, it should match.
+** mMatchSections For a line to be processed, it should match.
+** mMatchObjects For a line to be processed, it should match.
+** mMatchSymbols For a line to be processed, it should match.
+*/
+{
+ const char* mProgramName;
+ FILE* mInput;
+ char* mInputName;
+ FILE* mOutput;
+ char* mOutputName;
+ int mHelp;
+ int mModules;
+ int mTotalOnly;
+ unsigned long mMinSize;
+ unsigned long mMaxSize;
+ char** mMatchScopes;
+ unsigned mMatchScopeCount;
+ char** mMatchClasses;
+ unsigned mMatchClassCount;
+ char** mMatchModules;
+ unsigned mMatchModuleCount;
+ char** mMatchSections;
+ unsigned mMatchSectionCount;
+ char** mMatchObjects;
+ unsigned mMatchObjectCount;
+ char** mMatchSymbols;
+ unsigned mMatchSymbolCount;
+}
+Options;
+
+
+typedef struct __struct_Switch
+/*
+** Command line options.
+*/
+{
+ const char* mLongName;
+ const char* mShortName;
+ int mHasValue;
+ const char* mValue;
+ const char* mDescription;
+}
+Switch;
+
+#define DESC_NEWLINE "\n\t\t"
+
+static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."};
+static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."};
+static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."};
+static Switch gModuleSwitch = {"--modules", "-m", 0, NULL, "Output individual module numbers as well."};
+static Switch gTotalSwitch = {"--totalonly", "-t", 0, NULL, "Output only one number." DESC_NEWLINE "The total overall size." DESC_NEWLINE "Overrides other output options."};
+static Switch gMinSize = {"--min-size", "-min", 1, NULL, "Only consider symbols equal to or greater than this size." DESC_NEWLINE "The default is 0x00000000."};
+static Switch gMaxSize = {"--max-size", "-max", 1, NULL, "Only consider symbols equal to or smaller than this size." DESC_NEWLINE "The default is 0xFFFFFFFF."};
+static Switch gMatchScope = {"--match-scope", "-msco", 1, NULL, "Only consider scopes that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify a range of scopes," DESC_NEWLINE "though PUBLIC, STATIC, and UNDEF are your only choices."};
+static Switch gMatchClass = {"--match-class", "-mcla", 1, NULL, "Only consider classes that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify a range of classes," DESC_NEWLINE "though CODE and DATA are your only choices."};
+static Switch gMatchModule = {"--match-module", "-mmod", 1, NULL, "Only consider modules that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify an array of modules."};
+static Switch gMatchSection = {"--match-section", "-msec", 1, NULL, "Only consider sections that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify an array of sections." DESC_NEWLINE "Section is considered symbol type."};
+static Switch gMatchObject = {"--match-object", "-mobj", 1, NULL, "Only consider objects that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify an array of objects."};
+static Switch gMatchSymbol = {"--match-symbol", "-msym", 1, NULL, "Only consider symbols that have a substring match." DESC_NEWLINE "Multiple uses allowed to specify an array of symbols."};
+
+static Switch* gSwitches[] = {
+ &gInputSwitch,
+ &gOutputSwitch,
+ &gModuleSwitch,
+ &gTotalSwitch,
+ &gMinSize,
+ &gMaxSize,
+ &gMatchClass,
+ &gMatchScope,
+ &gMatchModule,
+ &gMatchSection,
+ &gMatchObject,
+ &gMatchSymbol,
+ &gHelpSwitch
+};
+
+
+typedef struct __struct_SizeStats
+/*
+** Track totals.
+**
+** mData Size of data.
+** mCode Size of code.
+*/
+{
+ unsigned long mData;
+ unsigned long mCode;
+}
+SizeStats;
+
+
+typedef struct __struct_ModuleStats
+/*
+** Track module level information.
+**
+** mModule Module name.
+** mSize Size of module.
+*/
+{
+ char* mModule;
+ SizeStats mSize;
+}
+ModuleStats;
+
+typedef enum __enum_SegmentClass
+{
+ CODE,
+ DATA
+}
+SegmentClass;
+
+
+static int moduleCompare(const void* in1, const void* in2)
+/*
+** qsort helper function.
+*/
+{
+ int retval = 0;
+
+ const ModuleStats* one = (const ModuleStats*)in1;
+ const ModuleStats* two = (const ModuleStats*)in2;
+ unsigned long oneSize = one->mSize.mCode + one->mSize.mData;
+ unsigned long twoSize = two->mSize.mCode + two->mSize.mData;
+
+ if(oneSize < twoSize)
+ {
+ retval = 1;
+ }
+ else if(oneSize > twoSize)
+ {
+ retval = -1;
+ }
+
+ return retval;
+}
+
+
+void trimWhite(char* inString)
+/*
+** Remove any whitespace from the end of the string.
+*/
+{
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+
+ if(isspace(*(inString + len)))
+ {
+ *(inString + len) = '\0';
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+int codesighs(Options* inOptions)
+/*
+** Output a simplistic report based on our options.
+*/
+{
+ int retval = 0;
+ char lineBuffer[0x1000];
+ int scanRes = 0;
+ unsigned long size;
+ char segClass[0x10];
+ char scope[0x10];
+ char module[0x100];
+ char segment[0x40];
+ char object[0x100];
+ char* symbol;
+ SizeStats overall;
+ ModuleStats* modules = NULL;
+ unsigned moduleCount = 0;
+
+ memset(&overall, 0, sizeof(overall));
+
+ /*
+ ** Read the file line by line, regardless of number of fields.
+ ** We assume tab separated value formatting, at least 7 lead values:
+ ** size class scope module segment object symbol ....
+ */
+ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput))
+ {
+ trimWhite(lineBuffer);
+
+ scanRes = sscanf(lineBuffer,
+ "%x\t%s\t%s\t%s\t%s\t%s\t",
+ (unsigned*)&size,
+ segClass,
+ scope,
+ module,
+ segment,
+ object);
+
+ if(6 == scanRes)
+ {
+ SegmentClass segmentClass = CODE;
+
+ symbol = strchr(lineBuffer, '\t') + 1;
+
+ /*
+ ** Qualify the segment class.
+ */
+ if(0 == strcmp(segClass, "DATA"))
+ {
+ segmentClass = DATA;
+ }
+ else if(0 == strcmp(segClass, "CODE"))
+ {
+ segmentClass = CODE;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, segClass, "Unable to determine segment class.");
+ }
+
+ if(0 == retval)
+ {
+ /*
+ ** Match any options required before continuing.
+ ** This is where you would want to add more restrictive totalling.
+ */
+
+ /*
+ ** Match size.
+ */
+ if(size < inOptions->mMinSize)
+ {
+ continue;
+ }
+ if(size > inOptions->mMaxSize)
+ {
+ continue;
+ }
+
+ /*
+ ** Match class.
+ */
+ if(0 != inOptions->mMatchClassCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchClassCount; loop++)
+ {
+ if(NULL != strstr(segClass, inOptions->mMatchClasses[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchClassCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Match scope.
+ */
+ if(0 != inOptions->mMatchScopeCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchScopeCount; loop++)
+ {
+ if(NULL != strstr(scope, inOptions->mMatchScopes[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchScopeCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Match modules.
+ */
+ if(0 != inOptions->mMatchModuleCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchModuleCount; loop++)
+ {
+ if(NULL != strstr(module, inOptions->mMatchModules[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchModuleCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Match sections.
+ */
+ if(0 != inOptions->mMatchSectionCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchSectionCount; loop++)
+ {
+ if(NULL != strstr(segment, inOptions->mMatchSections[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchSectionCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Match object.
+ */
+ if(0 != inOptions->mMatchObjectCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchObjectCount; loop++)
+ {
+ if(NULL != strstr(object, inOptions->mMatchObjects[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchObjectCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Match symbols.
+ */
+ if(0 != inOptions->mMatchSymbolCount)
+ {
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inOptions->mMatchSymbolCount; loop++)
+ {
+ if(NULL != strstr(symbol, inOptions->mMatchSymbols[loop]))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If there was no match, we skip the line.
+ */
+ if(loop == inOptions->mMatchSymbolCount)
+ {
+ continue;
+ }
+ }
+
+ /*
+ ** Update overall totals.
+ */
+ if(CODE == segmentClass)
+ {
+ overall.mCode += size;
+ }
+ else if(DATA == segmentClass)
+ {
+ overall.mData += size;
+ }
+
+ /*
+ ** See what else we should be tracking.
+ */
+ if(0 == inOptions->mTotalOnly)
+ {
+ if(inOptions->mModules)
+ {
+ unsigned index = 0;
+
+ /*
+ ** Find the module to modify.
+ */
+ for(index = 0; index < moduleCount; index++)
+ {
+ if(0 == strcmp(modules[index].mModule, module))
+ {
+ break;
+ }
+ }
+
+ /*
+ ** If the index is the same as the count, we need to
+ ** add a new module.
+ */
+ if(index == moduleCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(modules, sizeof(ModuleStats) * (moduleCount + 1));
+ if(NULL != moved)
+ {
+ modules = (ModuleStats*)moved;
+ moduleCount++;
+
+ memset(modules + index, 0, sizeof(ModuleStats));
+ modules[index].mModule = strdup(module);
+ if(NULL == modules[index].mModule)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, module, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate module memory.");
+ }
+ }
+
+ if(0 == retval)
+ {
+ if(CODE == segmentClass)
+ {
+ modules[index].mSize.mCode += size;
+ }
+ else if(DATA == segmentClass)
+ {
+ modules[index].mSize.mData += size;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Problem extracting values from file.");
+ }
+ }
+
+ if(0 == retval && 0 != ferror(inOptions->mInput))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file.");
+ }
+
+ /*
+ ** If all went well, time to report.
+ */
+ if(0 == retval)
+ {
+ if(inOptions->mTotalOnly)
+ {
+ fprintf(inOptions->mOutput, "%u\n", (unsigned)(overall.mCode + overall.mData));
+ }
+ else
+ {
+ fprintf(inOptions->mOutput, "Overall Size\n");
+ fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(overall.mCode + overall.mData));
+ fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)overall.mCode);
+ fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)overall.mData);
+ }
+
+ /*
+ ** Check options to see what else we should output.
+ */
+ if(inOptions->mModules && moduleCount)
+ {
+ unsigned loop = 0;
+
+ /*
+ ** Sort the modules by their size.
+ */
+ qsort(modules, (size_t)moduleCount, sizeof(ModuleStats), moduleCompare);
+
+ /*
+ ** Output each one.
+ ** Might as well clean up while we go too.
+ */
+ for(loop = 0; loop < moduleCount; loop++)
+ {
+ fprintf(inOptions->mOutput, "\n");
+ fprintf(inOptions->mOutput, "%s\n", modules[loop].mModule);
+ fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(modules[loop].mSize.mCode + modules[loop].mSize.mData));
+ fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)modules[loop].mSize.mCode);
+ fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)modules[loop].mSize.mData);
+
+ CLEANUP(modules[loop].mModule);
+ }
+
+ /*
+ ** Done with modules.
+ */
+ CLEANUP(modules);
+ moduleCount = 0;
+ }
+ }
+
+ return retval;
+}
+
+
+int initOptions(Options* outOptions, int inArgc, char** inArgv)
+/*
+** returns int 0 if successful.
+*/
+{
+ int retval = 0;
+ int loop = 0;
+ int switchLoop = 0;
+ int match = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ Switch* current = NULL;
+
+ /*
+ ** Set any defaults.
+ */
+ memset(outOptions, 0, sizeof(Options));
+ outOptions->mProgramName = inArgv[0];
+ outOptions->mInput = stdin;
+ outOptions->mInputName = strdup("stdin");
+ outOptions->mOutput = stdout;
+ outOptions->mOutputName = strdup("stdout");
+ outOptions->mMaxSize = 0xFFFFFFFFU;
+
+ if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup.");
+ }
+
+ /*
+ ** Go through and attempt to do the right thing.
+ */
+ for(loop = 1; loop < inArgc && 0 == retval; loop++)
+ {
+ match = 0;
+ current = NULL;
+
+ for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++)
+ {
+ if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+ else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+
+ if(match)
+ {
+ if(gSwitches[switchLoop]->mHasValue)
+ {
+ /*
+ ** Attempt to absorb next option to fullfill value.
+ */
+ if(loop + 1 < inArgc)
+ {
+ loop++;
+
+ current = gSwitches[switchLoop];
+ current->mValue = inArgv[loop];
+ }
+ }
+ else
+ {
+ current = gSwitches[switchLoop];
+ }
+
+ break;
+ }
+ }
+
+ if(0 == match)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch.");
+ }
+ else if(NULL == current)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value.");
+ }
+ else
+ {
+ /*
+ ** Do something based on address/swtich.
+ */
+ if(current == &gInputSwitch)
+ {
+ CLEANUP(outOptions->mInputName);
+ if(NULL != outOptions->mInput && stdin != outOptions->mInput)
+ {
+ fclose(outOptions->mInput);
+ outOptions->mInput = NULL;
+ }
+
+ outOptions->mInput = fopen(current->mValue, "r");
+ if(NULL == outOptions->mInput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open input file.");
+ }
+ else
+ {
+ outOptions->mInputName = strdup(current->mValue);
+ if(NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gOutputSwitch)
+ {
+ CLEANUP(outOptions->mOutputName);
+ if(NULL != outOptions->mOutput && stdout != outOptions->mOutput)
+ {
+ fclose(outOptions->mOutput);
+ outOptions->mOutput = NULL;
+ }
+
+ outOptions->mOutput = fopen(current->mValue, "a");
+ if(NULL == outOptions->mOutput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open output file.");
+ }
+ else
+ {
+ outOptions->mOutputName = strdup(current->mValue);
+ if(NULL == outOptions->mOutputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gHelpSwitch)
+ {
+ outOptions->mHelp = __LINE__;
+ }
+ else if(current == &gModuleSwitch)
+ {
+ outOptions->mModules = __LINE__;
+ }
+ else if(current == &gTotalSwitch)
+ {
+ outOptions->mTotalOnly = __LINE__;
+ }
+ else if(current == &gMinSize)
+ {
+ unsigned long arg = 0;
+ char* endScan = NULL;
+
+ errno = 0;
+ arg = strtoul(current->mValue, &endScan, 0);
+ if(0 == errno && endScan != current->mValue)
+ {
+ outOptions->mMinSize = arg;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to convert to a number.");
+ }
+ }
+ else if(current == &gMaxSize)
+ {
+ unsigned long arg = 0;
+ char* endScan = NULL;
+
+ errno = 0;
+ arg = strtoul(current->mValue, &endScan, 0);
+ if(0 == errno && endScan != current->mValue)
+ {
+ outOptions->mMaxSize = arg;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to convert to a number.");
+ }
+ }
+ else if(current == &gMatchClass)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchClasses, sizeof(char*) * (outOptions->mMatchClassCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchClasses = (char**)moved;
+ outOptions->mMatchClasses[outOptions->mMatchClassCount] = dupMatch;
+ outOptions->mMatchClassCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else if(current == &gMatchScope)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchScopes, sizeof(char*) * (outOptions->mMatchScopeCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchScopes = (char**)moved;
+ outOptions->mMatchScopes[outOptions->mMatchScopeCount] = dupMatch;
+ outOptions->mMatchScopeCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else if(current == &gMatchModule)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchModules, sizeof(char*) * (outOptions->mMatchModuleCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchModules = (char**)moved;
+ outOptions->mMatchModules[outOptions->mMatchModuleCount] = dupMatch;
+ outOptions->mMatchModuleCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else if(current == &gMatchSection)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchSections, sizeof(char*) * (outOptions->mMatchSectionCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchSections = (char**)moved;
+ outOptions->mMatchSections[outOptions->mMatchSectionCount] = dupMatch;
+ outOptions->mMatchSectionCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else if(current == &gMatchObject)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchObjects, sizeof(char*) * (outOptions->mMatchObjectCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchObjects = (char**)moved;
+ outOptions->mMatchObjects[outOptions->mMatchObjectCount] = dupMatch;
+ outOptions->mMatchObjectCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else if(current == &gMatchSymbol)
+ {
+ char* dupMatch = NULL;
+
+ dupMatch = strdup(current->mValue);
+ if(NULL != dupMatch)
+ {
+ void* moved = NULL;
+
+ moved = realloc(outOptions->mMatchSymbols, sizeof(char*) * (outOptions->mMatchSymbolCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchSymbols = (char**)moved;
+ outOptions->mMatchSymbols[outOptions->mMatchSymbolCount] = dupMatch;
+ outOptions->mMatchSymbolCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "Unable to expand array.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "No handler for command line switch.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanOptions(Options* inOptions)
+/*
+** Clean up any open handles.
+*/
+{
+ unsigned loop = 0;
+
+ CLEANUP(inOptions->mInputName);
+ if(NULL != inOptions->mInput && stdin != inOptions->mInput)
+ {
+ fclose(inOptions->mInput);
+ }
+ CLEANUP(inOptions->mOutputName);
+ if(NULL != inOptions->mOutput && stdout != inOptions->mOutput)
+ {
+ fclose(inOptions->mOutput);
+ }
+
+ for(loop = 0; loop < inOptions->mMatchClassCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchClasses[loop]);
+ }
+ CLEANUP(inOptions->mMatchClasses);
+
+ for(loop = 0; loop < inOptions->mMatchScopeCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchScopes[loop]);
+ }
+ CLEANUP(inOptions->mMatchScopes);
+
+ for(loop = 0; loop < inOptions->mMatchModuleCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchModules[loop]);
+ }
+ CLEANUP(inOptions->mMatchModules);
+
+ for(loop = 0; loop < inOptions->mMatchSectionCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchSections[loop]);
+ }
+ CLEANUP(inOptions->mMatchSections);
+
+ for(loop = 0; loop < inOptions->mMatchObjectCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchObjects[loop]);
+ }
+ CLEANUP(inOptions->mMatchObjects);
+
+ for(loop = 0; loop < inOptions->mMatchSymbolCount; loop++)
+ {
+ CLEANUP(inOptions->mMatchSymbols[loop]);
+ }
+ CLEANUP(inOptions->mMatchSymbols);
+
+ memset(inOptions, 0, sizeof(Options));
+}
+
+
+void showHelp(Options* inOptions)
+/*
+** Show some simple help text on usage.
+*/
+{
+ int loop = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ const char* valueText = NULL;
+
+ printf("usage:\t%s [arguments]\n", inOptions->mProgramName);
+ printf("\n");
+ printf("arguments:\n");
+
+ for(loop = 0; loop < switchCount; loop++)
+ {
+ if(gSwitches[loop]->mHasValue)
+ {
+ valueText = " <value>";
+ }
+ else
+ {
+ valueText = "";
+ }
+
+ printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText);
+ printf("\t %s%s", gSwitches[loop]->mShortName, valueText);
+ printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription);
+ }
+
+ printf("This tool takes a tsv file and reports composite code and data sizes.\n");
+}
+
+
+int main(int inArgc, char** inArgv)
+{
+ int retval = 0;
+ Options options;
+
+ retval = initOptions(&options, inArgc, inArgv);
+ if(options.mHelp)
+ {
+ showHelp(&options);
+ }
+ else if(0 == retval)
+ {
+ retval = codesighs(&options);
+ }
+
+ cleanOptions(&options);
+ return retval;
+}
+
diff --git a/chromium/third_party/codesighs/codesighs.gyp b/chromium/third_party/codesighs/codesighs.gyp
new file mode 100644
index 00000000000..6f7311e25e7
--- /dev/null
+++ b/chromium/third_party/codesighs/codesighs.gyp
@@ -0,0 +1,61 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'codesighs',
+ 'type': 'executable',
+ 'sources': [
+ 'codesighs.c',
+ ],
+ },
+ {
+ 'target_name': 'maptsvdifftool',
+ 'type': 'executable',
+ 'sources': [
+ 'maptsvdifftool.c',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'msmap2tsv',
+ 'type': 'executable',
+ 'sources': [
+ 'msmap2tsv.c',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-lDbgHelp.lib',
+ ],
+ },
+ },
+ {
+ 'target_name': 'msdump2symdb',
+ 'type': 'executable',
+ 'sources': [
+ 'msdump2symdb.c',
+ ],
+ },
+ ],
+ }, { # else: OS != "windows"
+ 'targets': [
+ {
+ 'target_name': 'nm2tsv',
+ 'type': 'executable',
+ 'sources': [
+ 'nm2tsv.c',
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/third_party/codesighs/maptsvdifftool.c b/chromium/third_party/codesighs/maptsvdifftool.c
new file mode 100644
index 00000000000..82070609cca
--- /dev/null
+++ b/chromium/third_party/codesighs/maptsvdifftool.c
@@ -0,0 +1,1311 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is maptsvdifftool.c code, released
+ * Oct 3, 2002.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 03-October-2002
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg));
+#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0)
+
+
+typedef struct __struct_Options
+/*
+** Options to control how we perform.
+**
+** mProgramName Used in help text.
+** mInput File to read for input.
+** Default is stdin.
+** mInputName Name of the file.
+** mOutput Output file, append.
+** Default is stdout.
+** mOutputName Name of the file.
+** mHelp Whether or not help should be shown.
+** mSummaryOnly Only output a signle line.
+** mZeroDrift Output zero drift data.
+** mNegation Perform negation heuristics on the symbol drifts.
+*/
+{
+ const char* mProgramName;
+ FILE* mInput;
+ char* mInputName;
+ FILE* mOutput;
+ char* mOutputName;
+ int mHelp;
+ int mSummaryOnly;
+ int mZeroDrift;
+ int mNegation;
+}
+Options;
+
+
+typedef struct __struct_Switch
+/*
+** Command line options.
+*/
+{
+ const char* mLongName;
+ const char* mShortName;
+ int mHasValue;
+ const char* mValue;
+ const char* mDescription;
+}
+Switch;
+
+#define DESC_NEWLINE "\n\t\t"
+
+static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."};
+static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."};
+static Switch gSummarySwitch = {"--summary", "-s", 0, NULL, "Only output a single line." DESC_NEWLINE "The cumulative size changes." DESC_NEWLINE "Overrides all other output options."};
+static Switch gZeroDriftSwitch = {"--zerodrift", "-z", 0, NULL, "Output zero drift data." DESC_NEWLINE "Reports symbol changes even when there is no net drift."};
+static Switch gNegationSwitch = {"--negation", "-n", 0, NULL, "Use negation heuristics." DESC_NEWLINE "When symbol sizes are inferred by offset, order changes cause noise." DESC_NEWLINE "This helps see through the noise by eliminating equal and opposite drifts."};
+static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."};
+
+static Switch* gSwitches[] = {
+ &gInputSwitch,
+ &gOutputSwitch,
+ &gSummarySwitch,
+ &gZeroDriftSwitch,
+ &gNegationSwitch,
+ &gHelpSwitch
+};
+
+
+typedef struct __struct_SizeComposition
+/*
+** Used to keep which parts positive and negative resulted in the total.
+*/
+{
+ int mPositive;
+ int mNegative;
+}
+SizeComposition;
+
+
+typedef struct __struct_SizeStats
+/*
+** Keep track of sizes.
+** Use signed integers so that negatives are valid, in which case we shrunk.
+*/
+{
+ int mCode;
+ SizeComposition mCodeComposition;
+
+ int mData;
+ SizeComposition mDataComposition;
+}
+SizeStats;
+
+
+typedef enum __enum_SegmentClass
+/*
+** What type of data a segment holds.
+*/
+{
+ CODE,
+ DATA
+}
+SegmentClass;
+
+
+typedef struct __struct_SymbolStats
+/*
+** Symbol level stats.
+*/
+{
+ char* mSymbol;
+ int mSize;
+}
+SymbolStats;
+
+
+typedef struct __struct_ObjectStats
+/*
+** Object level stats.
+*/
+{
+ char* mObject;
+ int mSize;
+ SizeComposition mComposition;
+ SymbolStats* mSymbols;
+ unsigned mSymbolCount;
+}
+ObjectStats;
+
+
+typedef struct __struct_SegmentStats
+/*
+** Segment level stats.
+*/
+{
+ char* mSegment;
+ SegmentClass mClass;
+ int mSize;
+ SizeComposition mComposition;
+ ObjectStats* mObjects;
+ unsigned mObjectCount;
+}
+SegmentStats;
+
+
+typedef struct __struct_ModuleStats
+/*
+** Module level stats.
+*/
+{
+ char* mModule;
+ SizeStats mSize;
+ SegmentStats* mSegments;
+ unsigned mSegmentCount;
+}
+ModuleStats;
+
+
+static int moduleCompare(const void* in1, const void* in2)
+/*
+** qsort helper.
+*/
+{
+ int retval = 0;
+
+ ModuleStats* one = (ModuleStats*)in1;
+ ModuleStats* two = (ModuleStats*)in2;
+
+ int oneSize = (one->mSize.mCode + one->mSize.mData);
+ int twoSize = (two->mSize.mCode + two->mSize.mData);
+
+ if(oneSize < twoSize)
+ {
+ retval = 1;
+ }
+ else if(oneSize > twoSize)
+ {
+ retval = -1;
+ }
+ else
+ {
+ retval = strcmp(one->mModule, two->mModule);
+ if(0 > oneSize && 0 > twoSize)
+ {
+ retval *= -1;
+ }
+ }
+
+ return retval;
+}
+
+
+static int segmentCompare(const void* in1, const void* in2)
+/*
+** qsort helper.
+*/
+{
+ int retval = 0;
+
+ SegmentStats* one = (SegmentStats*)in1;
+ SegmentStats* two = (SegmentStats*)in2;
+
+ if(one->mSize < two->mSize)
+ {
+ retval = 1;
+ }
+ else if(one->mSize > two->mSize)
+ {
+ retval = -1;
+ }
+ else
+ {
+ retval = strcmp(one->mSegment, two->mSegment);
+ if(0 > one->mSize && 0 > two->mSize)
+ {
+ retval *= -1;
+ }
+ }
+
+ return retval;
+}
+
+
+static int objectCompare(const void* in1, const void* in2)
+/*
+** qsort helper.
+*/
+{
+ int retval = 0;
+
+ ObjectStats* one = (ObjectStats*)in1;
+ ObjectStats* two = (ObjectStats*)in2;
+
+ if(one->mSize < two->mSize)
+ {
+ retval = 1;
+ }
+ else if(one->mSize > two->mSize)
+ {
+ retval = -1;
+ }
+ else
+ {
+ retval = strcmp(one->mObject, two->mObject);
+ if(0 > one->mSize && 0 > two->mSize)
+ {
+ retval *= -1;
+ }
+ }
+
+ return retval;
+}
+
+
+static int symbolCompare(const void* in1, const void* in2)
+/*
+** qsort helper.
+*/
+{
+ int retval = 0;
+
+ SymbolStats* one = (SymbolStats*)in1;
+ SymbolStats* two = (SymbolStats*)in2;
+
+ if(one->mSize < two->mSize)
+ {
+ retval = 1;
+ }
+ else if(one->mSize > two->mSize)
+ {
+ retval = -1;
+ }
+ else
+ {
+ retval = strcmp(one->mSymbol, two->mSymbol);
+ if(0 > one->mSize && 0 > two->mSize)
+ {
+ retval *= -1;
+ }
+ }
+
+ return retval;
+}
+
+
+void trimWhite(char* inString)
+/*
+** Remove any whitespace from the end of the string.
+*/
+{
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+
+ if(isspace(*(inString + len)))
+ {
+ *(inString + len) = '\0';
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+int difftool(Options* inOptions)
+/*
+** Read a diff file and spit out relevant information.
+*/
+{
+ int retval = 0;
+ char lineBuffer[0x500];
+ SizeStats overall;
+ ModuleStats* modules = NULL;
+ unsigned moduleCount = 0;
+ unsigned moduleLoop = 0;
+ ModuleStats* theModule = NULL;
+ unsigned segmentLoop = 0;
+ SegmentStats* theSegment = NULL;
+ unsigned objectLoop = 0;
+ ObjectStats* theObject = NULL;
+ unsigned symbolLoop = 0;
+ SymbolStats* theSymbol = NULL;
+ unsigned allSymbolCount = 0;
+
+ memset(&overall, 0, sizeof(overall));
+
+ /*
+ ** Read the entire diff file.
+ ** We're only interested in lines beginning with < or >
+ */
+ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput))
+ {
+ trimWhite(lineBuffer);
+
+ if(('<' == lineBuffer[0] || '>' == lineBuffer[0]) && ' ' == lineBuffer[1])
+ {
+ int additive = 0;
+ char* theLine = &lineBuffer[2];
+ int scanRes = 0;
+ int size;
+ char segClass[0x10];
+ char scope[0x10];
+ char module[0x100];
+ char segment[0x40];
+ char object[0x100];
+ char* symbol = NULL;
+
+ /*
+ ** Figure out if the line adds or subtracts from something.
+ */
+ if('>' == lineBuffer[0])
+ {
+ additive = __LINE__;
+ }
+
+
+ /*
+ ** Scan the line for information.
+ */
+ scanRes = sscanf(theLine,
+ "%x\t%s\t%s\t%s\t%s\t%s\t",
+ (unsigned*)&size,
+ segClass,
+ scope,
+ module,
+ segment,
+ object);
+
+ if(6 == scanRes)
+ {
+ SegmentClass segmentClass = DATA;
+
+ symbol = strrchr(theLine, '\t') + 1;
+
+ if(0 == strcmp(segClass, "CODE"))
+ {
+ segmentClass = CODE;
+ }
+ else if(0 == strcmp(segClass, "DATA"))
+ {
+ segmentClass = DATA;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, segClass, "Unable to determine segment class.");
+ }
+
+ if(0 == retval)
+ {
+ unsigned moduleIndex = 0;
+
+ /*
+ ** Find, in succession, the following things:
+ ** the module
+ ** the segment
+ ** the object
+ ** the symbol
+ ** Failure to find any one of these means to create it.
+ */
+
+ for(moduleIndex = 0; moduleIndex < moduleCount; moduleIndex++)
+ {
+ if(0 == strcmp(modules[moduleIndex].mModule, module))
+ {
+ break;
+ }
+ }
+
+ if(moduleIndex == moduleCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(modules, sizeof(ModuleStats) * (1 + moduleCount));
+ if(NULL != moved)
+ {
+ modules = (ModuleStats*)moved;
+ moduleCount++;
+ memset(modules + moduleIndex, 0, sizeof(ModuleStats));
+
+ modules[moduleIndex].mModule = strdup(module);
+ if(NULL == modules[moduleIndex].mModule)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, module, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase module array.");
+ }
+ }
+
+ if(0 == retval)
+ {
+ unsigned segmentIndex = 0;
+ theModule = (modules + moduleIndex);
+
+ for(segmentIndex = 0; segmentIndex < theModule->mSegmentCount; segmentIndex++)
+ {
+ if(0 == strcmp(segment, theModule->mSegments[segmentIndex].mSegment))
+ {
+ break;
+ }
+ }
+
+ if(segmentIndex == theModule->mSegmentCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(theModule->mSegments, sizeof(SegmentStats) * (theModule->mSegmentCount + 1));
+ if(NULL != moved)
+ {
+ theModule->mSegments = (SegmentStats*)moved;
+ theModule->mSegmentCount++;
+ memset(theModule->mSegments + segmentIndex, 0, sizeof(SegmentStats));
+
+ theModule->mSegments[segmentIndex].mClass = segmentClass;
+ theModule->mSegments[segmentIndex].mSegment = strdup(segment);
+ if(NULL == theModule->mSegments[segmentIndex].mSegment)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, segment, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase segment array.");
+ }
+ }
+
+ if(0 == retval)
+ {
+ unsigned objectIndex = 0;
+ theSegment = (theModule->mSegments + segmentIndex);
+
+ for(objectIndex = 0; objectIndex < theSegment->mObjectCount; objectIndex++)
+ {
+ if(0 == strcmp(object, theSegment->mObjects[objectIndex].mObject))
+ {
+ break;
+ }
+ }
+
+ if(objectIndex == theSegment->mObjectCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(theSegment->mObjects, sizeof(ObjectStats) * (1 + theSegment->mObjectCount));
+ if(NULL != moved)
+ {
+ theSegment->mObjects = (ObjectStats*)moved;
+ theSegment->mObjectCount++;
+ memset(theSegment->mObjects + objectIndex, 0, sizeof(ObjectStats));
+
+ theSegment->mObjects[objectIndex].mObject = strdup(object);
+ if(NULL == theSegment->mObjects[objectIndex].mObject)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, object, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase object array.");
+ }
+ }
+
+ if(0 == retval)
+ {
+ unsigned symbolIndex = 0;
+ theObject = (theSegment->mObjects + objectIndex);
+
+ for(symbolIndex = 0; symbolIndex < theObject->mSymbolCount; symbolIndex++)
+ {
+ if(0 == strcmp(symbol, theObject->mSymbols[symbolIndex].mSymbol))
+ {
+ break;
+ }
+ }
+
+ if(symbolIndex == theObject->mSymbolCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(theObject->mSymbols, sizeof(SymbolStats) * (1 + theObject->mSymbolCount));
+ if(NULL != moved)
+ {
+ theObject->mSymbols = (SymbolStats*)moved;
+ theObject->mSymbolCount++;
+ allSymbolCount++;
+ memset(theObject->mSymbols + symbolIndex, 0, sizeof(SymbolStats));
+
+ theObject->mSymbols[symbolIndex].mSymbol = strdup(symbol);
+ if(NULL == theObject->mSymbols[symbolIndex].mSymbol)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, symbol, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase symbol array.");
+ }
+ }
+
+ if(0 == retval)
+ {
+ theSymbol = (theObject->mSymbols + symbolIndex);
+
+ /*
+ ** Update our various totals.
+ */
+ if(additive)
+ {
+ if(CODE == segmentClass)
+ {
+ overall.mCode += size;
+ theModule->mSize.mCode += size;
+ }
+ else if(DATA == segmentClass)
+ {
+ overall.mData += size;
+ theModule->mSize.mData += size;
+ }
+
+ theSegment->mSize += size;
+ theObject->mSize += size;
+ theSymbol->mSize += size;
+ }
+ else
+ {
+ if(CODE == segmentClass)
+ {
+ overall.mCode -= size;
+ theModule->mSize.mCode -= size;
+ }
+ else if(DATA == segmentClass)
+ {
+ overall.mData -= size;
+ theModule->mSize.mData -= size;
+ }
+
+ theSegment->mSize -= size;
+ theObject->mSize -= size;
+ theSymbol->mSize -= size;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Unable to scan line data.");
+ }
+ }
+ }
+
+ if(0 == retval && 0 != ferror(inOptions->mInput))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file.");
+ }
+
+ /*
+ ** Next, it is time to perform revisionist history of sorts.
+ ** If the negation switch is in play, we perfrom the following
+ ** aggressive steps:
+ **
+ ** For each section, find size changes which have an equal and
+ ** opposite change, and set them both to zero.
+ ** However, you can only do this if the number of negating changes
+ ** is even, as if it is odd, then any one of the many could be
+ ** at fault for the actual change.
+ **
+ ** This orginally exists to make the win32 codesighs reports more
+ ** readable/meaningful.
+ */
+ if(0 == retval && 0 != inOptions->mNegation)
+ {
+ ObjectStats** objArray = NULL;
+ SymbolStats** symArray = NULL;
+
+ /*
+ ** Create arrays big enough to hold all symbols.
+ ** As well as an array to keep the owning object at the same index.
+ ** We will keep the object around as we may need to modify the size.
+ */
+ objArray = (ObjectStats**)malloc(allSymbolCount * sizeof(ObjectStats*));
+ symArray = (SymbolStats**)malloc(allSymbolCount * sizeof(SymbolStats*));
+ if(NULL == objArray || NULL == symArray)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate negation array memory.");
+ }
+ else
+ {
+ unsigned arrayCount = 0;
+ unsigned arrayLoop = 0;
+
+ /*
+ ** Go through and perform the steps on each section/segment.
+ */
+ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++)
+ {
+ theModule = modules + moduleLoop;
+
+ for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++)
+ {
+ theSegment = theModule->mSegments + segmentLoop;
+
+ /*
+ ** Collect all symbols under this section.
+ ** The symbols are spread out between all the objects,
+ ** so keep track of both independently at the
+ ** same index.
+ */
+ arrayCount = 0;
+
+ for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++)
+ {
+ theObject = theSegment->mObjects + objectLoop;
+
+ for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++)
+ {
+ theSymbol = theObject->mSymbols + symbolLoop;
+
+ objArray[arrayCount] = theObject;
+ symArray[arrayCount] = theSymbol;
+ arrayCount++;
+ }
+ }
+
+ /*
+ ** Now that we have a list of symbols, go through each
+ ** and see if there is a chance of negation.
+ */
+ for(arrayLoop = 0; arrayLoop < arrayCount; arrayLoop++)
+ {
+ /*
+ ** If the item is NULL, it was already negated.
+ ** Don't do this for items with a zero size.
+ */
+ if(NULL != symArray[arrayLoop] && 0 != symArray[arrayLoop]->mSize)
+ {
+ unsigned identicalValues = 0;
+ unsigned oppositeValues = 0;
+ unsigned lookLoop = 0;
+ const int lookingFor = symArray[arrayLoop]->mSize;
+
+ /*
+ ** Count the number of items with this value.
+ ** Count the number of items with the opposite equal value.
+ ** If they are equal, go through and negate all sizes.
+ */
+ for(lookLoop = arrayLoop; lookLoop < arrayCount; lookLoop++)
+ {
+ /*
+ ** Skip negated items.
+ ** Skip zero length items.
+ */
+ if(NULL == symArray[lookLoop] || 0 == symArray[lookLoop]->mSize)
+ {
+ continue;
+ }
+
+ if(lookingFor == symArray[lookLoop]->mSize)
+ {
+ identicalValues++;
+ }
+ else if((-1 * lookingFor) == symArray[lookLoop]->mSize)
+ {
+ oppositeValues++;
+ }
+ }
+
+ if(0 != identicalValues && identicalValues == oppositeValues)
+ {
+ unsigned negationLoop = 0;
+
+ for(negationLoop = arrayLoop; 0 != identicalValues || 0 != oppositeValues; negationLoop++)
+ {
+ /*
+ ** Skip negated items.
+ ** Skip zero length items.
+ */
+ if(NULL == symArray[negationLoop] || 0 == symArray[negationLoop]->mSize)
+ {
+ continue;
+ }
+
+ /*
+ ** Negate any size matches.
+ ** Reflect the change in the object as well.
+ ** Clear the symbol.
+ */
+ if(lookingFor == symArray[negationLoop]->mSize)
+ {
+ objArray[negationLoop]->mSize -= lookingFor;
+ symArray[negationLoop]->mSize = 0;
+ symArray[negationLoop] = NULL;
+
+ identicalValues--;
+ }
+ else if((-1 * lookingFor) == symArray[negationLoop]->mSize)
+ {
+ objArray[negationLoop]->mSize += lookingFor;
+ symArray[negationLoop]->mSize = 0;
+ symArray[negationLoop] = NULL;
+
+ oppositeValues--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ CLEANUP(objArray);
+ CLEANUP(symArray);
+ }
+
+
+ /*
+ ** If all went well, time to report.
+ */
+ if(0 == retval)
+ {
+ /*
+ ** Loop through our data once more, so that the symbols can
+ ** propigate their changes upwards in a positive/negative
+ ** fashion.
+ ** This will help give the composite change more meaning.
+ */
+ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++)
+ {
+ theModule = modules + moduleLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData))
+ {
+ continue;
+ }
+
+ for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++)
+ {
+ theSegment = theModule->mSegments + segmentLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize)
+ {
+ continue;
+ }
+
+ for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++)
+ {
+ theObject = theSegment->mObjects + objectLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize)
+ {
+ continue;
+ }
+
+ for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++)
+ {
+ theSymbol = theObject->mSymbols + symbolLoop;
+
+ /*
+ ** Propagate the composition all the way to the top.
+ ** Sizes of zero change are skipped.
+ */
+ if(0 < theSymbol->mSize)
+ {
+ theObject->mComposition.mPositive += theSymbol->mSize;
+ theSegment->mComposition.mPositive += theSymbol->mSize;
+ if(CODE == theSegment->mClass)
+ {
+ overall.mCodeComposition.mPositive += theSymbol->mSize;
+ theModule->mSize.mCodeComposition.mPositive += theSymbol->mSize;
+ }
+ else if(DATA == theSegment->mClass)
+ {
+ overall.mDataComposition.mPositive += theSymbol->mSize;
+ theModule->mSize.mDataComposition.mPositive += theSymbol->mSize;
+ }
+ }
+ else if(0 > theSymbol->mSize)
+ {
+ theObject->mComposition.mNegative += theSymbol->mSize;
+ theSegment->mComposition.mNegative += theSymbol->mSize;
+ if(CODE == theSegment->mClass)
+ {
+ overall.mCodeComposition.mNegative += theSymbol->mSize;
+ theModule->mSize.mCodeComposition.mNegative += theSymbol->mSize;
+ }
+ else if(DATA == theSegment->mClass)
+ {
+ overall.mDataComposition.mNegative += theSymbol->mSize;
+ theModule->mSize.mDataComposition.mNegative += theSymbol->mSize;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if(inOptions->mSummaryOnly)
+ {
+ fprintf(inOptions->mOutput, "%+d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative);
+ }
+ else
+ {
+ fprintf(inOptions->mOutput, "Overall Change in Size\n");
+ fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative);
+ fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", overall.mCode, overall.mCodeComposition.mPositive, overall.mCodeComposition.mNegative);
+ fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", overall.mData, overall.mDataComposition.mPositive, overall.mDataComposition.mNegative);
+ }
+
+ /*
+ ** Check what else we should output.
+ */
+ if(0 == inOptions->mSummaryOnly && NULL != modules && moduleCount)
+ {
+ const char* segmentType = NULL;
+
+ /*
+ ** We're going to sort everything.
+ */
+ qsort(modules, moduleCount, sizeof(ModuleStats), moduleCompare);
+ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++)
+ {
+ theModule = modules + moduleLoop;
+
+ qsort(theModule->mSegments, theModule->mSegmentCount, sizeof(SegmentStats), segmentCompare);
+
+ for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++)
+ {
+ theSegment = theModule->mSegments + segmentLoop;
+
+ qsort(theSegment->mObjects, theSegment->mObjectCount, sizeof(ObjectStats), objectCompare);
+
+ for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++)
+ {
+ theObject = theSegment->mObjects + objectLoop;
+
+ qsort(theObject->mSymbols, theObject->mSymbolCount, sizeof(SymbolStats), symbolCompare);
+ }
+ }
+ }
+
+ /*
+ ** Loop through for output.
+ */
+ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++)
+ {
+ theModule = modules + moduleLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData))
+ {
+ continue;
+ }
+
+ fprintf(inOptions->mOutput, "\n");
+ fprintf(inOptions->mOutput, "%s\n", theModule->mModule);
+ fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode + theModule->mSize.mData, theModule->mSize.mCodeComposition.mPositive + theModule->mSize.mDataComposition.mPositive, theModule->mSize.mCodeComposition.mNegative + theModule->mSize.mDataComposition.mNegative);
+ fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode, theModule->mSize.mCodeComposition.mPositive, theModule->mSize.mCodeComposition.mNegative);
+ fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", theModule->mSize.mData, theModule->mSize.mDataComposition.mPositive, theModule->mSize.mDataComposition.mNegative);
+
+ for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++)
+ {
+ theSegment = theModule->mSegments + segmentLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize)
+ {
+ continue;
+ }
+
+ if(CODE == theSegment->mClass)
+ {
+ segmentType = "CODE";
+ }
+ else if(DATA == theSegment->mClass)
+ {
+ segmentType = "DATA";
+ }
+
+ fprintf(inOptions->mOutput, "\t%+11d (%+d/%+d)\t%s (%s)\n", theSegment->mSize, theSegment->mComposition.mPositive, theSegment->mComposition.mNegative, theSegment->mSegment, segmentType);
+
+ for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++)
+ {
+ theObject = theSegment->mObjects + objectLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize)
+ {
+ continue;
+ }
+
+ fprintf(inOptions->mOutput, "\t\t%+11d (%+d/%+d)\t%s\n", theObject->mSize, theObject->mComposition.mPositive, theObject->mComposition.mNegative, theObject->mObject);
+
+ for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++)
+ {
+ theSymbol = theObject->mSymbols + symbolLoop;
+
+ /*
+ ** Skip if there is zero drift, or no net change.
+ */
+ if(0 == inOptions->mZeroDrift && 0 == theSymbol->mSize)
+ {
+ continue;
+ }
+
+ fprintf(inOptions->mOutput, "\t\t\t%+11d\t%s\n", theSymbol->mSize, theSymbol->mSymbol);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ ** Cleanup time.
+ */
+ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++)
+ {
+ theModule = modules + moduleLoop;
+
+ for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++)
+ {
+ theSegment = theModule->mSegments + segmentLoop;
+
+ for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++)
+ {
+ theObject = theSegment->mObjects + objectLoop;
+
+ for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++)
+ {
+ theSymbol = theObject->mSymbols + symbolLoop;
+
+ CLEANUP(theSymbol->mSymbol);
+ }
+
+ CLEANUP(theObject->mSymbols);
+ CLEANUP(theObject->mObject);
+ }
+
+ CLEANUP(theSegment->mObjects);
+ CLEANUP(theSegment->mSegment);
+ }
+
+ CLEANUP(theModule->mSegments);
+ CLEANUP(theModule->mModule);
+ }
+ CLEANUP(modules);
+
+ return retval;
+}
+
+
+int initOptions(Options* outOptions, int inArgc, char** inArgv)
+/*
+** returns int 0 if successful.
+*/
+{
+ int retval = 0;
+ int loop = 0;
+ int switchLoop = 0;
+ int match = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ Switch* current = NULL;
+
+ /*
+ ** Set any defaults.
+ */
+ memset(outOptions, 0, sizeof(Options));
+ outOptions->mProgramName = inArgv[0];
+ outOptions->mInput = stdin;
+ outOptions->mInputName = strdup("stdin");
+ outOptions->mOutput = stdout;
+ outOptions->mOutputName = strdup("stdout");
+
+ if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup.");
+ }
+
+ /*
+ ** Go through and attempt to do the right thing.
+ */
+ for(loop = 1; loop < inArgc && 0 == retval; loop++)
+ {
+ match = 0;
+ current = NULL;
+
+ for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++)
+ {
+ if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+ else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+
+ if(match)
+ {
+ if(gSwitches[switchLoop]->mHasValue)
+ {
+ /*
+ ** Attempt to absorb next option to fullfill value.
+ */
+ if(loop + 1 < inArgc)
+ {
+ loop++;
+
+ current = gSwitches[switchLoop];
+ current->mValue = inArgv[loop];
+ }
+ }
+ else
+ {
+ current = gSwitches[switchLoop];
+ }
+
+ break;
+ }
+ }
+
+ if(0 == match)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch.");
+ }
+ else if(NULL == current)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value.");
+ }
+ else
+ {
+ /*
+ ** Do something based on address/swtich.
+ */
+ if(current == &gInputSwitch)
+ {
+ CLEANUP(outOptions->mInputName);
+ if(NULL != outOptions->mInput && stdin != outOptions->mInput)
+ {
+ fclose(outOptions->mInput);
+ outOptions->mInput = NULL;
+ }
+
+ outOptions->mInput = fopen(current->mValue, "r");
+ if(NULL == outOptions->mInput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open input file.");
+ }
+ else
+ {
+ outOptions->mInputName = strdup(current->mValue);
+ if(NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gOutputSwitch)
+ {
+ CLEANUP(outOptions->mOutputName);
+ if(NULL != outOptions->mOutput && stdout != outOptions->mOutput)
+ {
+ fclose(outOptions->mOutput);
+ outOptions->mOutput = NULL;
+ }
+
+ outOptions->mOutput = fopen(current->mValue, "a");
+ if(NULL == outOptions->mOutput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open output file.");
+ }
+ else
+ {
+ outOptions->mOutputName = strdup(current->mValue);
+ if(NULL == outOptions->mOutputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gHelpSwitch)
+ {
+ outOptions->mHelp = __LINE__;
+ }
+ else if(current == &gSummarySwitch)
+ {
+ outOptions->mSummaryOnly = __LINE__;
+ }
+ else if(current == &gZeroDriftSwitch)
+ {
+ outOptions->mZeroDrift = __LINE__;
+ }
+ else if(current == &gNegationSwitch)
+ {
+ outOptions->mNegation = __LINE__;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "No handler for command line switch.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanOptions(Options* inOptions)
+/*
+** Clean up any open handles.
+*/
+{
+ CLEANUP(inOptions->mInputName);
+ if(NULL != inOptions->mInput && stdin != inOptions->mInput)
+ {
+ fclose(inOptions->mInput);
+ }
+ CLEANUP(inOptions->mOutputName);
+ if(NULL != inOptions->mOutput && stdout != inOptions->mOutput)
+ {
+ fclose(inOptions->mOutput);
+ }
+
+ memset(inOptions, 0, sizeof(Options));
+}
+
+
+void showHelp(Options* inOptions)
+/*
+** Show some simple help text on usage.
+*/
+{
+ int loop = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ const char* valueText = NULL;
+
+ printf("usage:\t%s [arguments]\n", inOptions->mProgramName);
+ printf("\n");
+ printf("arguments:\n");
+
+ for(loop = 0; loop < switchCount; loop++)
+ {
+ if(gSwitches[loop]->mHasValue)
+ {
+ valueText = " <value>";
+ }
+ else
+ {
+ valueText = "";
+ }
+
+ printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText);
+ printf("\t %s%s", gSwitches[loop]->mShortName, valueText);
+ printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription);
+ }
+
+ printf("This tool takes the diff of two sorted tsv files to form a summary report\n");
+ printf("of code and data size changes which is hoped to be human readable.\n");
+}
+
+
+int main(int inArgc, char** inArgv)
+{
+ int retval = 0;
+ Options options;
+
+ retval = initOptions(&options, inArgc, inArgv);
+ if(options.mHelp)
+ {
+ showHelp(&options);
+ }
+ else if(0 == retval)
+ {
+ retval = difftool(&options);
+ }
+
+ cleanOptions(&options);
+ return retval;
+}
+
diff --git a/chromium/third_party/codesighs/msdump2symdb.c b/chromium/third_party/codesighs/msdump2symdb.c
new file mode 100644
index 00000000000..705c3c41739
--- /dev/null
+++ b/chromium/third_party/codesighs/msdump2symdb.c
@@ -0,0 +1,1090 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is msdump2symdb.c code, released
+ * Jan 16, 2003.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 16-January-2003
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg));
+#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0)
+
+
+typedef struct __struct_Options
+/*
+** Options to control how we perform.
+**
+** mProgramName Used in help text.
+** mInput File to read for input.
+** Default is stdin.
+** mInputName Name of the file.
+** mOutput Output file, append.
+** Default is stdout.
+** mOutputName Name of the file.
+** mHelp Whether or not help should be shown.
+*/
+{
+ const char* mProgramName;
+ FILE* mInput;
+ char* mInputName;
+ FILE* mOutput;
+ char* mOutputName;
+ int mHelp;
+}
+Options;
+
+
+typedef struct __struct_Switch
+/*
+** Command line options.
+*/
+{
+ const char* mLongName;
+ const char* mShortName;
+ int mHasValue;
+ const char* mValue;
+ const char* mDescription;
+}
+Switch;
+
+#define DESC_NEWLINE "\n\t\t"
+
+static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."};
+static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."};
+static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."};
+
+static Switch* gSwitches[] = {
+ &gInputSwitch,
+ &gOutputSwitch,
+ &gHelpSwitch
+};
+
+
+typedef struct __struct_MSDump_Symbol
+/*
+** Struct to hold infomration on a symbol.
+**
+** mSize Size of the symbol once all work is complete.
+** mOffset Offset of the symbol in the section.
+** mName Symbolic name.
+*/
+{
+ unsigned mSize;
+ unsigned mOffset;
+ char* mName;
+}
+MSDump_Symbol;
+
+
+typedef struct __struct_MSDump_Section
+/*
+** Struct for holding information on a section.
+**
+** mLength Length of the section in bytes.
+** mUsed Number of bytes used in the section thus far.
+** Should eventually match mLength after work is done.
+** mType Type of section, as string (.data, .text, et. al.)
+** mSymbols Symbols found inside the section.
+** mSymbolCount Number of symbols in array.
+*/
+{
+ unsigned mLength;
+ unsigned mUsed;
+ char* mType;
+
+ MSDump_Symbol* mSymbols;
+ unsigned mSymbolCount;
+}
+MSDump_Section;
+
+
+typedef struct __struct_MSDump_Object
+/*
+** Struct for holding object's data.
+*/
+{
+ char* mObject;
+
+ MSDump_Section* mSections;
+ unsigned mSectionCount;
+}
+MSDump_Object;
+
+
+typedef struct __struct_MSDump_ReadState
+/*
+** State flags while reading the input gives us hints on what to do.
+**
+** mSkipLines Number of lines to skip without parsing.
+** mSectionDetails Section information next, like line length.
+** mCurrentObject Object file we are dealing with.
+*/
+{
+ unsigned mSkipLines;
+ unsigned mSectionDetails;
+ MSDump_Object* mCurrentObject;
+}
+MSDump_ReadState;
+
+
+typedef struct __struct_MSDump_Container
+/*
+** Umbrella container for all data encountered.
+*/
+{
+ MSDump_ReadState mReadState;
+
+ MSDump_Object* mObjects;
+ unsigned mObjectCount;
+}
+MSDump_Container;
+
+
+void trimWhite(char* inString)
+/*
+** Remove any whitespace from the end of the string.
+*/
+{
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+
+ if(isspace(*(inString + len)))
+ {
+ *(inString + len) = '\0';
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+const char* skipWhite(const char* inString)
+/*
+** Return pointer to first non white space character.
+*/
+{
+ const char* retval = inString;
+
+ while('\0' != *retval && isspace(*retval))
+ {
+ retval++;
+ }
+
+ return retval;
+}
+
+
+const char* skipNonWhite(const char* inString)
+/*
+** Return pointer to first white space character.
+*/
+{
+ const char* retval = inString;
+
+ while('\0' != *retval && !isspace(*retval))
+ {
+ retval++;
+ }
+
+ return retval;
+}
+
+
+void slash2bs(char* inString)
+/*
+** Change any forward slash to a backslash.
+*/
+{
+ char* slash = inString;
+
+ while(NULL != (slash = strchr(slash, '/')))
+ {
+ *slash = '\\';
+ slash++;
+ }
+}
+
+
+const char* skipToArg(const char* inString, unsigned inArgIndex)
+/*
+** Return pointer either to the arg or NULL.
+** 1 indexed.
+*/
+{
+ const char* retval = NULL;
+
+ while(0 != inArgIndex && '\0' != *inString)
+ {
+ inArgIndex--;
+
+ inString = skipWhite(inString);
+ if(0 != inArgIndex)
+ {
+ inString = skipNonWhite(inString);
+ }
+ }
+
+ if('\0' != *inString)
+ {
+ retval = inString;
+ }
+
+ return retval;
+}
+
+
+const char* getLastArg(const char* inString)
+/*
+** Return pointer to last arg in string.
+*/
+{
+ const char* retval = NULL;
+ int length = 0;
+ int sawString = 0;
+
+ length = strlen(inString);
+ while(0 != length)
+ {
+ length--;
+
+ if(0 == sawString)
+ {
+ if(0 == isspace(inString[length]))
+ {
+ sawString = __LINE__;
+ }
+ }
+ else
+ {
+ if(0 != isspace(inString[length]))
+ {
+ retval = inString + length + 1;
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+int processLine(Options* inOptions, MSDump_Container* inContainer, const char* inLine)
+/*
+** Handle one line at a time.
+** Looking for several different types of lines.
+** Ignore all other lines.
+** The container is the state machine.
+** returns 0 on no error.
+*/
+{
+ int retval = 0;
+
+ /*
+ ** Check to see if we were expecting section details.
+ */
+ if(0 != inContainer->mReadState.mSectionDetails)
+ {
+ const char* length = NULL;
+ unsigned sectionIndex = 0;
+
+ /*
+ ** Detail is a 1 based index....
+ ** Reset.
+ */
+ sectionIndex = inContainer->mReadState.mSectionDetails - 1;
+ inContainer->mReadState.mSectionDetails = 0;
+
+ if(0 == strncmp(" Section length", inLine, 18))
+ {
+ const char* sectionLength = NULL;
+ unsigned numericLength = 0;
+ char* endScan = NULL;
+
+ sectionLength = skipWhite(inLine + 18);
+
+ errno = 0;
+ numericLength = strtoul(sectionLength, &endScan, 16);
+ if(0 == errno && endScan != sectionLength)
+ {
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mLength = numericLength;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Cannot scan for section length.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Cannot parse section line.");
+ }
+ }
+ /*
+ ** Check for switching object file symbols.
+ */
+ else if(0 == strncmp("Dump of file ", inLine, 13))
+ {
+ const char* dupMe = inLine + 13;
+ char* dup = NULL;
+
+ dup = strdup(dupMe);
+ if(NULL != dup)
+ {
+ void* growth = NULL;
+
+ trimWhite(dup);
+ slash2bs(dup);
+
+
+ growth = realloc(inContainer->mObjects, (inContainer->mObjectCount + 1) * sizeof(MSDump_Object));
+ if(NULL != growth)
+ {
+ unsigned int index = inContainer->mObjectCount;
+
+ inContainer->mObjectCount++;
+ inContainer->mObjects = growth;
+ memset(inContainer->mObjects + index, 0, sizeof(MSDump_Object));
+
+ inContainer->mObjects[index].mObject = dup;
+
+ /*
+ ** Reset the read state for this new object.
+ */
+ memset(&inContainer->mReadState, 0, sizeof(MSDump_ReadState));
+
+ /*
+ ** Record our current object file.
+ */
+ inContainer->mReadState.mCurrentObject = inContainer->mObjects + index;
+
+ /*
+ ** We can skip a few lines.
+ */
+ inContainer->mReadState.mSkipLines = 4;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, dup, "Unable to grow object array.");
+ free(dup);
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, dupMe, "Unable to copy string.");
+
+ }
+ }
+ /*
+ ** Check for a symbol dump or a section header.
+ */
+ else if(isxdigit(*inLine) && isxdigit(*(inLine + 1)) && isxdigit(*(inLine + 2)))
+ {
+ const char* sectionString = NULL;
+
+ /*
+ ** Determine the section for this line.
+ ** Ignore DEBUG sections.
+ */
+ sectionString = skipToArg(inLine, 3);
+ if(NULL != sectionString)
+ {
+ if(0 != strncmp(sectionString, "DEBUG", 5) && 0 != strncmp(sectionString, "ABS", 3) && 0 != strncmp(sectionString, "UNDEF", 5))
+ {
+ /*
+ ** MUST start with "SECT"
+ */
+ if(0 == strncmp(sectionString, "SECT", 4))
+ {
+ unsigned sectionIndex1 = 0;
+
+ char *endScan = NULL;
+
+ sectionString += 4;
+
+ /*
+ ** Convert the remaining string to an index.
+ ** It will be 1 based.
+ */
+ errno = 0;
+ sectionIndex1 = strtoul(sectionString, &endScan, 16);
+ if(0 == errno && endScan != sectionString && 0 != sectionIndex1)
+ {
+ unsigned sectionIndex = sectionIndex1 - 1;
+
+ /*
+ ** Is this a new section? Assumed to be ascending.
+ ** Or is this a symbol in the section?
+ */
+ if(sectionIndex1 > inContainer->mReadState.mCurrentObject->mSectionCount)
+ {
+ const char* typeArg = NULL;
+
+ /*
+ ** New Section, figure out the type.
+ */
+ typeArg = skipToArg(sectionString, 5);
+ if(NULL != typeArg)
+ {
+ char* typeDup = NULL;
+
+ /*
+ ** Skip the leading period before duping.
+ */
+ if('.' == *typeArg)
+ {
+ typeArg++;
+ }
+ typeDup = strdup(typeArg);
+
+ if(NULL != typeDup)
+ {
+ void* moved = NULL;
+ char* nonWhite = NULL;
+
+ /*
+ ** Terminate the duplicate after the section type.
+ */
+ nonWhite = (char*)skipNonWhite(typeDup);
+ if(NULL != nonWhite)
+ {
+ *nonWhite = '\0';
+ }
+
+ /*
+ ** Create more space for the section in the object...
+ */
+ moved = realloc(inContainer->mReadState.mCurrentObject->mSections, sizeof(MSDump_Section) * sectionIndex1);
+ if(NULL != moved)
+ {
+ unsigned oldCount = inContainer->mReadState.mCurrentObject->mSectionCount;
+
+ inContainer->mReadState.mCurrentObject->mSections = (MSDump_Section*)moved;
+ inContainer->mReadState.mCurrentObject->mSectionCount = sectionIndex1;
+ memset(&inContainer->mReadState.mCurrentObject->mSections[oldCount], 0, sizeof(MSDump_Section) * (sectionIndex1 - oldCount));
+
+ /*
+ ** Other section details.
+ */
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mType = typeDup;
+
+
+ /*
+ ** Mark it so that we look for the length on the next line.
+ ** This happens on next entry into the read state.
+ */
+ inContainer->mReadState.mSectionDetails = sectionIndex1;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to grow for new section.");
+ free(typeDup);
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, typeArg, "Unable to duplicate type.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to determine section type.");
+ }
+
+ }
+ else
+ {
+ const char* offsetArg = NULL;
+ const char* classArg = NULL;
+ unsigned classWords = 1;
+ const char* symbolArg = NULL;
+
+ /*
+ ** This is an section we've seen before, and must list a symbol.
+ ** Figure out the things we want to know about the symbol, e.g. size.
+ ** We will ignore particular classes of symbols.
+ */
+
+ offsetArg = skipToArg(inLine, 2);
+
+ classArg = skipToArg(offsetArg, 4);
+ if(0 == strncmp(classArg, "()", 2))
+ {
+ classArg = skipToArg(classArg, 2);
+ }
+ if(0 == strncmp(classArg, ".bf or.ef", 9))
+ {
+ classWords = 2;
+ }
+
+ symbolArg = skipToArg(classArg, 3 + (classWords - 1));
+
+ /*
+ ** Skip particular lines/items.
+ */
+ if(
+ 0 != strncmp(classArg, "Label", 5) &&
+ 0 != strncmp(symbolArg, ".bf", 3) &&
+ 0 != strncmp(symbolArg, ".lf", 3) &&
+ 0 != strncmp(symbolArg, ".ef", 3)
+ )
+ {
+ char* endOffsetArg = NULL;
+ unsigned offset = 0;
+
+ /*
+ ** Convert the offset to something meaninful (size).
+ */
+ errno = 0;
+ offset = strtoul(offsetArg, &endOffsetArg, 16);
+ if(0 == errno && endOffsetArg != offsetArg)
+ {
+ void* moved = NULL;
+
+ /*
+ ** Increase the size of the symbol array in the section.
+ ** Assumed symbols are unique within each section.
+ */
+ moved = realloc(inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols, sizeof(MSDump_Symbol) * (inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbolCount + 1));
+ if(NULL != moved)
+ {
+ unsigned symIndex = 0;
+
+ /*
+ ** Record symbol details.
+ ** Assumed symbols are encountered in order for their section (size calc depends on it).
+ */
+ symIndex = inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbolCount;
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbolCount++;
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols = (MSDump_Symbol*)moved;
+ memset(&inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols[symIndex], 0, sizeof(MSDump_Symbol));
+
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols[symIndex].mOffset = offset;
+
+ /*
+ ** We could allocate smarter here if it ever mattered.
+ */
+ inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols[symIndex].mName = strdup(symbolArg);
+ if(NULL != inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols[symIndex].mName)
+ {
+ char* trim = NULL;
+
+ trim = (char*)skipNonWhite(inContainer->mReadState.mCurrentObject->mSections[sectionIndex].mSymbols[symIndex].mName);
+ if(NULL != trim)
+ {
+ *trim = '\0';
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to duplicate symbol name.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to grow symbol array for section.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to convert offset to a number.");
+ }
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to determine section index.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "No match for section prefix.");
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inLine, "Unable to scan for section.");
+ }
+ }
+
+ return retval;
+}
+
+
+void dumpCleanup(MSDump_Container* inContainer)
+/*
+** Attempt to be nice and free up what we have allocated.
+*/
+{
+ unsigned objectLoop = 0;
+ unsigned sectionLoop = 0;
+ unsigned symbolLoop = 0;
+
+ for(objectLoop = 0; objectLoop < inContainer->mObjectCount; objectLoop++)
+ {
+ for(sectionLoop = 0; sectionLoop < inContainer->mObjects[objectLoop].mSectionCount; sectionLoop++)
+ {
+ for(symbolLoop = 0; symbolLoop < inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbolCount; symbolLoop++)
+ {
+ CLEANUP(inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mName);
+ }
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbolCount = 0;
+ CLEANUP(inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols);
+ CLEANUP(inContainer->mObjects[objectLoop].mSections[sectionLoop].mType);
+ }
+ inContainer->mObjects[objectLoop].mSectionCount = 0;
+ CLEANUP(inContainer->mObjects[objectLoop].mSections);
+ }
+ CLEANUP(inContainer->mObjects);
+ inContainer->mObjectCount = 0;
+}
+
+
+int qsortSymOffset(const void* in1, const void* in2)
+/*
+** qsort callback to sort the symbols by their offset.
+*/
+{
+ MSDump_Symbol* sym1 = (MSDump_Symbol*)in1;
+ MSDump_Symbol* sym2 = (MSDump_Symbol*)in2;
+ int retval = 0;
+
+ if(sym1->mOffset < sym2->mOffset)
+ {
+ retval = 1;
+ }
+ else if(sym1->mOffset > sym2->mOffset)
+ {
+ retval = -1;
+ }
+
+ return retval;
+}
+
+
+int calcContainer(Options* inOptions, MSDump_Container* inContainer)
+/*
+** Resposible for doing any size calculations based on the offsets known.
+** After this calculation, each sections mUsed will match mSize.
+** After this calculation, all symbols should know how big they are.
+*/
+{
+ int retval = 0;
+ unsigned objectLoop = 0;
+ unsigned sectionLoop = 0;
+ unsigned symbolLoop = 0;
+
+
+ /*
+ ** Need to sort all symbols by their offsets.
+ */
+ for(objectLoop = 0; 0 == retval && objectLoop < inContainer->mObjectCount; objectLoop++)
+ {
+ for(sectionLoop = 0; 0 == retval && sectionLoop < inContainer->mObjects[objectLoop].mSectionCount; sectionLoop++)
+ {
+ qsort(
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols,
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbolCount,
+ sizeof(MSDump_Symbol),
+ qsortSymOffset
+ );
+ }
+ }
+
+
+ /*
+ ** Need to go through all symbols and calculate their size.
+ */
+ for(objectLoop = 0; 0 == retval && objectLoop < inContainer->mObjectCount; objectLoop++)
+ {
+ for(sectionLoop = 0; 0 == retval && sectionLoop < inContainer->mObjects[objectLoop].mSectionCount; sectionLoop++)
+ {
+ for(symbolLoop = 0; 0 == retval && symbolLoop < inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbolCount; symbolLoop++)
+ {
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mSize =
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mLength -
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mUsed -
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mOffset;
+
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mUsed +=
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mSize;
+ }
+ }
+ }
+
+
+ return retval;
+}
+
+
+int reportContainer(Options* inOptions, MSDump_Container* inContainer)
+/*
+** Display all symbols and their data.
+** We'll use a tsv format.
+*/
+{
+ int retval = 0;
+ unsigned objectLoop = 0;
+ unsigned sectionLoop = 0;
+ unsigned symbolLoop = 0;
+ int printRes = 0;
+
+ for(objectLoop = 0; 0 == retval && objectLoop < inContainer->mObjectCount; objectLoop++)
+ {
+ for(sectionLoop = 0; 0 == retval && sectionLoop < inContainer->mObjects[objectLoop].mSectionCount; sectionLoop++)
+ {
+ for(symbolLoop = 0; 0 == retval && symbolLoop < inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbolCount; symbolLoop++)
+ {
+ printRes = fprintf(inOptions->mOutput, "%s\t%s\t%.8X\t%s\n",
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mName,
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mType,
+ inContainer->mObjects[objectLoop].mSections[sectionLoop].mSymbols[symbolLoop].mSize,
+ inContainer->mObjects[objectLoop].mObject
+ );
+
+ if(0 > printRes)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mOutputName, "Unable to write to file.");
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+int dump2symdb(Options* inOptions)
+/*
+** Convert the input into the output, respecting the options.
+** Returns 0 on success.
+*/
+{
+ int retval = 0;
+ char lineBuffer[0x800];
+ MSDump_Container container;
+
+ memset(&container, 0, sizeof(container));
+
+ /*
+ ** Read the file line by line.
+ */
+ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput))
+ {
+ if(0 != container.mReadState.mSkipLines)
+ {
+ container.mReadState.mSkipLines--;
+ continue;
+ }
+ retval = processLine(inOptions, &container, lineBuffer);
+ }
+
+ /*
+ ** Perform whatever calculations desired.
+ */
+ if(0 == retval)
+ {
+ retval = calcContainer(inOptions, &container);
+ }
+
+ /*
+ ** Output what we know.
+ */
+ if(0 == retval)
+ {
+ retval = reportContainer(inOptions, &container);
+ }
+
+ /*
+ ** Cleanup what we've done.
+ */
+ dumpCleanup(&container);
+
+ return retval;
+}
+
+
+int initOptions(Options* outOptions, int inArgc, char** inArgv)
+/*
+** returns int 0 if successful.
+*/
+{
+ int retval = 0;
+ int loop = 0;
+ int switchLoop = 0;
+ int match = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ Switch* current = NULL;
+
+ /*
+ ** Set any defaults.
+ */
+ memset(outOptions, 0, sizeof(Options));
+ outOptions->mProgramName = inArgv[0];
+ outOptions->mInput = stdin;
+ outOptions->mInputName = strdup("stdin");
+ outOptions->mOutput = stdout;
+ outOptions->mOutputName = strdup("stdout");
+
+ if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup.");
+ }
+
+ /*
+ ** Go through and attempt to do the right thing.
+ */
+ for(loop = 1; loop < inArgc && 0 == retval; loop++)
+ {
+ match = 0;
+ current = NULL;
+
+ for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++)
+ {
+ if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+ else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+
+ if(match)
+ {
+ if(gSwitches[switchLoop]->mHasValue)
+ {
+ /*
+ ** Attempt to absorb next option to fullfill value.
+ */
+ if(loop + 1 < inArgc)
+ {
+ loop++;
+
+ current = gSwitches[switchLoop];
+ current->mValue = inArgv[loop];
+ }
+ }
+ else
+ {
+ current = gSwitches[switchLoop];
+ }
+
+ break;
+ }
+ }
+
+ if(0 == match)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch.");
+ }
+ else if(NULL == current)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value.");
+ }
+ else
+ {
+ /*
+ ** Do something based on address/swtich.
+ */
+ if(current == &gInputSwitch)
+ {
+ CLEANUP(outOptions->mInputName);
+ if(NULL != outOptions->mInput && stdin != outOptions->mInput)
+ {
+ fclose(outOptions->mInput);
+ outOptions->mInput = NULL;
+ }
+
+ outOptions->mInput = fopen(current->mValue, "r");
+ if(NULL == outOptions->mInput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open input file.");
+ }
+ else
+ {
+ outOptions->mInputName = strdup(current->mValue);
+ if(NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gOutputSwitch)
+ {
+ CLEANUP(outOptions->mOutputName);
+ if(NULL != outOptions->mOutput && stdout != outOptions->mOutput)
+ {
+ fclose(outOptions->mOutput);
+ outOptions->mOutput = NULL;
+ }
+
+ outOptions->mOutput = fopen(current->mValue, "a");
+ if(NULL == outOptions->mOutput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open output file.");
+ }
+ else
+ {
+ outOptions->mOutputName = strdup(current->mValue);
+ if(NULL == outOptions->mOutputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gHelpSwitch)
+ {
+ outOptions->mHelp = __LINE__;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "No handler for command line switch.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanOptions(Options* inOptions)
+/*
+** Clean up any open handles.
+*/
+{
+ CLEANUP(inOptions->mInputName);
+ if(NULL != inOptions->mInput && stdin != inOptions->mInput)
+ {
+ fclose(inOptions->mInput);
+ }
+ CLEANUP(inOptions->mOutputName);
+ if(NULL != inOptions->mOutput && stdout != inOptions->mOutput)
+ {
+ fclose(inOptions->mOutput);
+ }
+
+ memset(inOptions, 0, sizeof(Options));
+}
+
+
+void showHelp(Options* inOptions)
+/*
+** Show some simple help text on usage.
+*/
+{
+ int loop = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ const char* valueText = NULL;
+
+ printf("usage:\t%s [arguments]\n", inOptions->mProgramName);
+ printf("\n");
+ printf("arguments:\n");
+
+ for(loop = 0; loop < switchCount; loop++)
+ {
+ if(gSwitches[loop]->mHasValue)
+ {
+ valueText = " <value>";
+ }
+ else
+ {
+ valueText = "";
+ }
+
+ printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText);
+ printf("\t %s%s", gSwitches[loop]->mShortName, valueText);
+ printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription);
+ }
+
+ printf("This tool takes the output of \"dumpbin /symbols\" to produce a simple\n");
+ printf("tsv db file of symbols and their respective attributes, like size.\n");
+}
+
+
+int main(int inArgc, char** inArgv)
+{
+ int retval = 0;
+ Options options;
+
+ retval = initOptions(&options, inArgc, inArgv);
+ if(options.mHelp)
+ {
+ showHelp(&options);
+ }
+ else if(0 == retval)
+ {
+ retval = dump2symdb(&options);
+ }
+
+ cleanOptions(&options);
+ return retval;
+}
+
diff --git a/chromium/third_party/codesighs/msmap.h b/chromium/third_party/codesighs/msmap.h
new file mode 100644
index 00000000000..3c528de5cff
--- /dev/null
+++ b/chromium/third_party/codesighs/msmap.h
@@ -0,0 +1,149 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is msmap.h code, released
+ * Oct 3, 2002.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 03-October-2002
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#if !defined __msmap_H
+#define __msmap_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+
+/*
+** Used to numerically represent addresses.
+*/
+typedef unsigned long address;
+
+
+typedef enum __enum_MSMap_SymbolScope
+/*
+** Symbol scope.
+*/
+{
+ PUBLIC,
+ STATIC,
+ UNDEFINED
+}
+MSMap_SymbolScope;
+
+
+typedef enum __enum_MSMap_SegmentClass
+/*
+** Segment class.
+*/
+{
+ CODE,
+ DATA
+}
+MSMap_SegmentClass;
+
+
+typedef struct __struct_MSMap_Segment
+/*
+** Information about a segment.
+*/
+{
+ address mPrefix;
+ address mOffset;
+ address mLength;
+ address mUsed;
+ char* mSegment;
+ MSMap_SegmentClass mClass;
+}
+MSMap_Segment;
+
+
+typedef struct __struct_MSMap_Symbol
+/*
+** Information about a symbol.
+*/
+{
+ address mPrefix;
+ address mOffset;
+ char* mSymbol;
+ address mRVABase;
+ char* mObject;
+ MSMap_SymbolScope mScope;
+ unsigned mSymDBSize;
+ MSMap_Segment* mSection;
+}
+MSMap_Symbol;
+
+
+typedef struct __struct_MSMap_Module
+/*
+** Top level container of the map data.
+*/
+{
+ char* mModule;
+ time_t mTimestamp;
+ address mPreferredLoadAddress;
+ MSMap_Segment* mSegments;
+ unsigned mSegmentCount;
+ unsigned mSegmentCapacity;
+ address mEntryPrefix;
+ address mEntryOffset;
+ MSMap_Symbol* mSymbols;
+ unsigned mSymbolCount;
+ unsigned mSymbolCapacity;
+}
+MSMap_Module;
+
+
+/*
+** How much to grow our arrays by.
+*/
+#define MSMAP_SEGMENT_GROWBY 0x10
+#define MSMAP_SYMBOL_GROWBY 0x100
+
+
+#if 0
+{
+#endif
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+
+#endif /* __msmap_H */
diff --git a/chromium/third_party/codesighs/msmap2tsv.c b/chromium/third_party/codesighs/msmap2tsv.c
new file mode 100644
index 00000000000..91587029dcc
--- /dev/null
+++ b/chromium/third_party/codesighs/msmap2tsv.c
@@ -0,0 +1,2237 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is msmap2tsv.c code, released
+ * Oct 3, 2002.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 03-October-2002
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include "msmap.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <imagehlp.h>
+
+#define F_DEMANGLE 1
+#define DEMANGLE_STATE_NORMAL 0
+#define DEMANGLE_STATE_QDECODE 1
+#define DEMANGLE_STATE_PROLOGUE_1 2
+#define DEMANGLE_STATE_HAVE_TYPE 3
+#define DEMANGLE_STATE_DEC_LENGTH 4
+#define DEMANGLE_STATE_HEX_LENGTH 5
+#define DEMANGLE_STATE_PROLOGUE_SECONDARY 6
+#define DEMANGLE_STATE_DOLLAR_1 7
+#define DEMANGLE_STATE_DOLLAR_2 8
+#define DEMANGLE_STATE_START 9
+#define DEMANGLE_STATE_STOP 10
+#define DEMANGLE_SAFE_CHAR(eval) (isprint(eval) ? eval : ' ')
+
+#else
+#define F_DEMANGLE 0
+#endif /* WIN32 */
+
+
+#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg));
+#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0)
+
+
+typedef struct __struct_SymDB_Size
+/*
+** The size of the symbol.
+** The size is nested withing a symbols structures to produce a fast
+** lookup path.
+** The objects are listed in case the client of the symdb needs to
+** match the object name in the scenario where multiple symbol
+** sizes are present.
+**
+** mSize The size of the symbol in these objects.
+** mObjects A list of objects containing said symbol.
+** mObjectCount Number of objects.
+*/
+{
+ unsigned mSize;
+ char** mObjects;
+ unsigned mObjectCount;
+}
+SymDB_Size;
+
+
+typedef struct __struct_SymDB_Section
+/*
+** Each section for a symbol has a list of sizes.
+** Should there be exactly one size for the symbol, then that
+** is the size that should be accepted.
+** If there is more than one size, then a match on the object
+** should be attempted, held withing each size.
+**
+** mName The section name.
+** mSizes The varoius sizes of the symbol in this section.
+** mSizeCount The number of available sizes.
+*/
+{
+ char* mName;
+ SymDB_Size* mSizes;
+ unsigned mSizeCount;
+}
+SymDB_Section;
+
+
+typedef struct __struct_SymDB_Symbol
+/*
+** Each symbol has at least one section.
+** The section indicates what type of symbol a client may be looking for.
+** If there is no match on the section, then the client should not trust
+** the symbdb.
+**
+** mName The mangled name of the symbol.
+** mSections Various sections this symbol belongs to.
+** mSectionCount The number of sections.
+*/
+{
+ char* mName;
+ SymDB_Section* mSections;
+ unsigned mSectionCount;
+}
+SymDB_Symbol;
+
+
+#define SYMDB_SYMBOL_GROWBY 0x1000 /* how many sybols to allocate at a time */
+
+
+typedef struct __struct_SymDB_Container
+/*
+** The symbol DB container object.
+** The goal of the symbol DB is to have exactly one SymDB_Symbol for each
+** mangled name, no matter how ever many identical mangled names there
+** are in the input.
+** The input is already expected to be well sorted, futher this leads to
+** the ability to binary search for symbol name matches.
+**
+** mSymbols The symbols.
+** mSymbolCount The number of symbols in the DB.
+** mSymbolCapacity The number of symbols we can hold (before realloc).
+*/
+{
+ SymDB_Symbol* mSymbols;
+ unsigned mSymbolCount;
+ unsigned mSymbolCapacity;
+}
+SymDB_Container;
+
+
+typedef struct __struct_Options
+/*
+** Options to control how we perform.
+**
+** mProgramName Used in help text.
+** mInput File to read for input.
+** Default is stdin.
+** mInputName Name of the file.
+** mOutput Output file, append.
+** Default is stdout.
+** mOutputName Name of the file.
+** mHelp Whether or not help should be shown.
+** mMatchModules Array of strings which the module name should match.
+** mMatchModuleCount Number of items in array.
+** mSymDBName Symbol DB filename.
+** mBatchMode Batch mode.
+** When in batch mode, the input file contains a list of
+** map files to process.
+** Normally the input file is a single map file itself.
+*/
+{
+ const char* mProgramName;
+ FILE* mInput;
+ char* mInputName;
+ FILE* mOutput;
+ char* mOutputName;
+ int mHelp;
+ char** mMatchModules;
+ unsigned mMatchModuleCount;
+ char* mSymDBName;
+ SymDB_Container* mSymDB;
+ int mBatchMode;
+}
+Options;
+
+
+typedef struct __struct_Switch
+/*
+** Command line options.
+*/
+{
+ const char* mLongName;
+ const char* mShortName;
+ int mHasValue;
+ const char* mValue;
+ const char* mDescription;
+}
+Switch;
+
+#define DESC_NEWLINE "\n\t\t"
+
+static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."};
+static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."};
+static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."};
+static Switch gMatchModuleSwitch = {"--match-module", "-mm", 1, NULL, "Specify a valid module name." DESC_NEWLINE "Multiple specifications allowed." DESC_NEWLINE "If a module name does not match one of the names specified then no output will occur."};
+static Switch gSymDBSwitch = {"--symdb", "-sdb", 1, NULL, "Specify a symbol tsv db input file." DESC_NEWLINE "Such a symdb is produced using the tool msdump2symdb." DESC_NEWLINE "This allows better symbol size approximations." DESC_NEWLINE "The symdb file must be pre-sorted."};
+static Switch gBatchModeSwitch = {"--batch", "-b", 0, NULL, "Runs in batch mode." DESC_NEWLINE "The input file contains a list of map files." DESC_NEWLINE "Normally the input file is a map file itself." DESC_NEWLINE "This eliminates reprocessing the symdb for multiple map files."};
+
+static Switch* gSwitches[] = {
+ &gInputSwitch,
+ &gOutputSwitch,
+ &gMatchModuleSwitch,
+ &gSymDBSwitch,
+ &gBatchModeSwitch,
+ &gHelpSwitch
+};
+
+
+typedef struct __struct_MSMap_ReadState
+/*
+** Keep track of what state we are while reading input.
+** This gives the input context in which we absorb the datum.
+*/
+{
+ int mHasModule;
+
+ int mHasTimestamp;
+
+ int mHasPreferredLoadAddress;
+
+ int mHasSegmentData;
+ int mSegmentDataSkippedLine;
+
+ int mHasPublicSymbolData;
+ int mHasPublicSymbolDataSkippedLines;
+
+ int mHasEntryPoint;
+
+ int mFoundStaticSymbols;
+}
+MSMap_ReadState;
+
+
+char* skipWhite(char* inScan)
+/*
+** Skip whitespace.
+*/
+{
+ char* retval = inScan;
+
+ while(isspace(*retval))
+ {
+ retval++;
+ }
+
+ return retval;
+}
+
+void trimWhite(char* inString)
+/*
+** Remove any whitespace from the end of the string.
+*/
+{
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+
+ if(isspace(*(inString + len)))
+ {
+ *(inString + len) = '\0';
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+char* lastWord(char* inString)
+/*
+** Finds and returns the last word in a string.
+** It is assumed no whitespace is at the end of the string.
+*/
+{
+ int mod = 0;
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+ if(isspace(*(inString + len)))
+ {
+ mod = 1;
+ break;
+ }
+ }
+
+ return inString + len + mod;
+}
+
+
+MSMap_Segment* getSymbolSection(MSMap_Module* inModule, MSMap_Symbol* inoutSymbol)
+/*
+** Perform a lookup for the section of the symbol.
+** The function could cache the value.
+*/
+{
+ MSMap_Segment* retval = NULL;
+
+ if(NULL != inoutSymbol->mSection)
+ {
+ /*
+ ** Use cached value.
+ */
+ retval = inoutSymbol->mSection;
+ }
+ else
+ {
+ unsigned secLoop = 0;
+
+ /*
+ ** Go through sections in module to find the match for the symbol.
+ */
+ for(secLoop = 0; secLoop < inModule->mSegmentCount; secLoop++)
+ {
+ if(inoutSymbol->mPrefix == inModule->mSegments[secLoop].mPrefix)
+ {
+ if(inoutSymbol->mOffset >= inModule->mSegments[secLoop].mOffset)
+ {
+ if(inoutSymbol->mOffset < (inModule->mSegments[secLoop].mOffset + inModule->mSegments[secLoop].mLength))
+ {
+ /*
+ ** We have the section.
+ */
+ retval = &inModule->mSegments[secLoop];
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ ** Cache the value for next time.
+ */
+ inoutSymbol->mSection = retval;
+ }
+
+ return retval;
+}
+
+
+int readSymDB(const char* inDBName, SymDB_Container** outDB)
+/*
+** Intialize the symbol DB.
+** Only call if the symbol DB should be initialized.
+*/
+{
+ int retval = 0;
+
+ /*
+ ** Initialize out arguments.
+ */
+ if(NULL != outDB)
+ {
+ *outDB = NULL;
+ }
+
+ if(NULL != outDB && NULL != inDBName)
+ {
+ FILE* symDB = NULL;
+
+ symDB = fopen(inDBName, "r");
+ if(NULL != symDB)
+ {
+ *outDB = (SymDB_Container*)calloc(1, sizeof(SymDB_Container));
+ if(NULL != *outDB)
+ {
+ char lineBuf[0x400];
+ char* symbol = NULL;
+ char* section = NULL;
+ char* object = NULL;
+ char* length = NULL;
+ unsigned lengthNum = 0;
+ char* endLength = NULL;
+
+ /*
+ ** Read the file line by line.
+ */
+ while(0 == retval && NULL != fgets(lineBuf, sizeof(lineBuf), symDB))
+ {
+ trimWhite(lineBuf);
+
+ /*
+ ** Each line has four arguments. tab separated values (tsv).
+ ** Symbol
+ ** Section
+ ** Length
+ ** Object
+ */
+
+ symbol = skipWhite(lineBuf);
+ if(NULL == symbol)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "File does not appear to be a symbol DB.");
+ break;
+ }
+
+ section = strchr(symbol, '\t');
+ if(NULL == section)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "File does not appear to be a symbol DB.");
+ break;
+ }
+ *section = '\0';
+ section++;
+
+ length = strchr(section, '\t');
+ if(NULL == length)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "File does not appear to be a symbol DB.");
+ break;
+ }
+ *length = '\0';
+ length++;
+
+ object = strchr(length, '\t');
+ if(NULL == object)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "File does not appear to be a symbol DB.");
+ break;
+ }
+ *object = '\0';
+ object++;
+
+ /*
+ ** Convert the length into a number.
+ */
+ errno = 0;
+ lengthNum = strtoul(length, &endLength, 16);
+ if(0 == errno && endLength != length)
+ {
+ SymDB_Symbol* dbSymbol = NULL;
+ SymDB_Section* dbSection = NULL;
+ SymDB_Size* dbSize = NULL;
+ char* dbObject = NULL;
+ void* moved = NULL;
+
+ /*
+ ** Are we looking at the same symbol as last line?
+ ** This assumes the symdb is pre sorted!!!
+ */
+ if(0 != (*outDB)->mSymbolCount)
+ {
+ unsigned index = (*outDB)->mSymbolCount - 1;
+
+ if(0 == strcmp((*outDB)->mSymbols[index].mName, symbol))
+ {
+ dbSymbol = &(*outDB)->mSymbols[index];
+ }
+ }
+
+ /*
+ ** May need to create symbol.
+ */
+ if(NULL == dbSymbol)
+ {
+ /*
+ ** Could be time to grow the symbol pool.
+ */
+ if((*outDB)->mSymbolCount >= (*outDB)->mSymbolCapacity)
+ {
+ moved = realloc((*outDB)->mSymbols, sizeof(SymDB_Symbol) * ((*outDB)->mSymbolCapacity + SYMDB_SYMBOL_GROWBY));
+ if(NULL != moved)
+ {
+ (*outDB)->mSymbols = (SymDB_Symbol*)moved;
+ memset(&(*outDB)->mSymbols[(*outDB)->mSymbolCapacity], 0, sizeof(SymDB_Symbol) * SYMDB_SYMBOL_GROWBY);
+ (*outDB)->mSymbolCapacity += SYMDB_SYMBOL_GROWBY;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "Unable to grow symbol DB symbol array.");
+ break;
+ }
+ }
+
+ if((*outDB)->mSymbolCount < (*outDB)->mSymbolCapacity)
+ {
+ dbSymbol = &(*outDB)->mSymbols[(*outDB)->mSymbolCount];
+ (*outDB)->mSymbolCount++;
+
+ dbSymbol->mName = strdup(symbol);
+ if(NULL == dbSymbol->mName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, symbol, "Unable to duplicate string.");
+ break;
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, symbol, "Unable to grow symbol DB for symbol.");
+ break;
+ }
+ }
+
+ /*
+ ** Assume we have the symbol.
+ **
+ ** Is this the same section as the last section in the symbol?
+ ** This assumes the symdb was presorted!!!!
+ */
+ if(0 != dbSymbol->mSectionCount)
+ {
+ unsigned index = dbSymbol->mSectionCount - 1;
+
+ if(0 == strcmp(dbSymbol->mSections[index].mName, section))
+ {
+ dbSection = &dbSymbol->mSections[index];
+ }
+ }
+
+ /*
+ ** May need to create the section.
+ */
+ if(NULL == dbSection)
+ {
+ moved = realloc(dbSymbol->mSections, sizeof(SymDB_Section) * (dbSymbol->mSectionCount + 1));
+ if(NULL != moved)
+ {
+ dbSymbol->mSections = (SymDB_Section*)moved;
+ dbSection = &dbSymbol->mSections[dbSymbol->mSectionCount];
+ dbSymbol->mSectionCount++;
+
+ memset(dbSection, 0, sizeof(SymDB_Section));
+
+ dbSection->mName = strdup(section);
+ if(NULL == dbSection->mName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, section, "Unable to duplicate string.");
+ break;
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, section, "Unable to grow symbol sections for symbol DB.");
+ break;
+ }
+ }
+
+ /*
+ ** Assume we have the section.
+ **
+ ** Is this the same size as the last size?
+ ** This assumes the symdb was presorted!!!
+ */
+ if(0 != dbSection->mSizeCount)
+ {
+ unsigned index = dbSection->mSizeCount - 1;
+
+ if(dbSection->mSizes[index].mSize == lengthNum)
+ {
+ dbSize = &dbSection->mSizes[index];
+ }
+ }
+
+ /*
+ ** May need to create the size in question.
+ */
+ if(NULL == dbSize)
+ {
+ moved = realloc(dbSection->mSizes, sizeof(SymDB_Size) * (dbSection->mSizeCount + 1));
+ if(NULL != moved)
+ {
+ dbSection->mSizes = (SymDB_Size*)moved;
+ dbSize = &dbSection->mSizes[dbSection->mSizeCount];
+ dbSection->mSizeCount++;
+
+ memset(dbSize, 0, sizeof(SymDB_Size));
+
+ dbSize->mSize = lengthNum;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, length, "Unable to grow symbol section sizes for symbol DB.");
+ break;
+ }
+ }
+
+ /*
+ ** Assume we have the size.
+ **
+ ** We assume a one to one correllation between size and object.
+ ** Always try to add the new object name.
+ ** As the symdb is assumed to be sorted, the object names should also be in order.
+ */
+ moved = realloc(dbSize->mObjects, sizeof(char*) * (dbSize->mObjectCount + 1));
+ if(NULL != moved)
+ {
+ dbObject = strdup(object);
+
+ dbSize->mObjects = (char**)moved;
+ dbSize->mObjects[dbSize->mObjectCount] = dbObject;
+ dbSize->mObjectCount++;
+
+ if(NULL == dbObject)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, object, "Unable to duplicate string.");
+ break;
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, object, "Unable to grow symbol section size objects for symbol DB.");
+ break;
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, length, "Unable to convert symbol DB length into a number.");
+ break;
+ }
+ }
+
+ if(0 == retval && 0 != ferror(symDB))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "Unable to read file.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "Unable to allocate symbol DB.");
+ }
+
+ fclose(symDB);
+ symDB = NULL;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inDBName, "Unable to open symbol DB.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "(NULL)", "Invalid arguments.");
+ }
+
+ return retval;
+}
+
+
+void cleanSymDB(SymDB_Container** inDB)
+/*
+** Free it all up.
+*/
+{
+ if(NULL != inDB && NULL != *inDB)
+ {
+ unsigned symLoop = 0;
+ unsigned secLoop = 0;
+ unsigned sizLoop = 0;
+ unsigned objLoop = 0;
+
+ for(symLoop = 0; symLoop < (*inDB)->mSymbolCount; symLoop++)
+ {
+ for(secLoop = 0; secLoop < (*inDB)->mSymbols[symLoop].mSectionCount; secLoop++)
+ {
+ for(sizLoop = 0; sizLoop < (*inDB)->mSymbols[symLoop].mSections[secLoop].mSizeCount; sizLoop++)
+ {
+ for(objLoop = 0; objLoop < (*inDB)->mSymbols[symLoop].mSections[secLoop].mSizes[sizLoop].mObjectCount; objLoop++)
+ {
+ CLEANUP((*inDB)->mSymbols[symLoop].mSections[secLoop].mSizes[sizLoop].mObjects[objLoop]);
+ }
+ CLEANUP((*inDB)->mSymbols[symLoop].mSections[secLoop].mSizes[sizLoop].mObjects);
+ }
+ CLEANUP((*inDB)->mSymbols[symLoop].mSections[secLoop].mName);
+ CLEANUP((*inDB)->mSymbols[symLoop].mSections[secLoop].mSizes);
+ }
+ CLEANUP((*inDB)->mSymbols[symLoop].mName);
+ CLEANUP((*inDB)->mSymbols[symLoop].mSections);
+ }
+ CLEANUP((*inDB)->mSymbols);
+ CLEANUP(*inDB);
+ }
+}
+
+
+int symDBLookup(const void* inKey, const void* inItem)
+/*
+** bsearch utility routine to find the symbol in the symdb.
+*/
+{
+ int retval = 0;
+ const char* key = (const char*)inKey;
+ const SymDB_Symbol* symbol = (const SymDB_Symbol*)inItem;
+
+ retval = strcmp(key, symbol->mName);
+
+ return retval;
+}
+
+
+int fillSymbolSizeFromDB(Options* inOptions, MSMap_Module* inModule, MSMap_Symbol* inoutSymbol, const char* inMangledName)
+/*
+** If we have a symbol DB, attempt to determine the real size of the symbol
+** up front.
+** This helps us later in the game to avoid performing size guesses by
+** offset.
+*/
+{
+ int retval = 0;
+
+ /*
+ ** May need to initialize symdb.
+ */
+ if(NULL == inOptions->mSymDB && NULL != inOptions->mSymDBName)
+ {
+ retval = readSymDB(inOptions->mSymDBName, &inOptions->mSymDB);
+ }
+
+ /*
+ ** Optional
+ */
+ if(0 == retval && NULL != inOptions->mSymDB)
+ {
+ void* match = NULL;
+
+ /*
+ ** Find the symbol.
+ */
+ match = bsearch(inMangledName, inOptions->mSymDB->mSymbols, inOptions->mSymDB->mSymbolCount, sizeof(SymDB_Symbol), symDBLookup);
+ if(NULL != match)
+ {
+ SymDB_Symbol* symbol = (SymDB_Symbol*)match;
+ unsigned symDBSize = 0;
+ MSMap_Segment* mapSection = NULL;
+
+ /*
+ ** We found the symbol.
+ **
+ ** See if it has the section in question.
+ */
+ mapSection = getSymbolSection(inModule, inoutSymbol);
+ if(NULL != mapSection)
+ {
+ unsigned secLoop = 0;
+
+ for(secLoop = 0; secLoop < symbol->mSectionCount; secLoop++)
+ {
+ if(0 == strcmp(mapSection->mSegment, symbol->mSections[secLoop].mName))
+ {
+ SymDB_Section* section = &symbol->mSections[secLoop];
+
+ /*
+ ** We have a section match.
+ ** Should there be a single size for the symbol,
+ ** then we just default to that.
+ ** If more than one size, we have to do an
+ ** object match search.
+ ** Should there be no object match, we do nothign.
+ */
+ if(1 == section->mSizeCount)
+ {
+ symDBSize = section->mSizes[0].mSize;
+ }
+ else
+ {
+ char* mapObject = NULL;
+
+ /*
+ ** Figure out the map object file name.
+ ** Skip any colon.
+ ** If it doesn't have a .obj in it, not worth continuing.
+ */
+ mapObject = strrchr(inoutSymbol->mObject, ':');
+ if(NULL == mapObject)
+ {
+ mapObject = inoutSymbol->mObject;
+ }
+ else
+ {
+ mapObject++; /* colon */
+ }
+
+ if(NULL != strstr(mapObject, ".obj"))
+ {
+ unsigned sizLoop = 0;
+ unsigned objLoop = 0;
+ SymDB_Size* size = NULL;
+
+ for(sizLoop = 0; sizLoop < section->mSizeCount; sizLoop++)
+ {
+ size = &section->mSizes[sizLoop];
+
+ for(objLoop = 0; objLoop < size->mObjectCount; objLoop++)
+ {
+ if(NULL != strstr(size->mObjects[objLoop], mapObject))
+ {
+ /*
+ ** As we matched the object, in a particular section,
+ ** we'll go with this as the number.
+ */
+ symDBSize = size->mSize;
+ break;
+ }
+ }
+
+ /*
+ ** If the object loop broke early, we break too.
+ */
+ if(objLoop < size->mObjectCount)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ /*
+ ** Put the size in.
+ */
+ inoutSymbol->mSymDBSize = symDBSize;
+ }
+ }
+
+ return retval;
+}
+
+
+char* symdup(const char* inSymbol)
+/*
+** Attempts to demangle the symbol if appropriate.
+** Otherwise acts like strdup.
+*/
+{
+ char* retval = NULL;
+
+#if F_DEMANGLE
+ {
+ int isImport = 0;
+
+ if(0 == strncmp("__imp_", inSymbol, 6))
+ {
+ isImport = __LINE__;
+ inSymbol += 6;
+ }
+
+ if('?' == inSymbol[0])
+ {
+ char demangleBuf[0x200];
+ DWORD demangleRes = 0;
+
+ demangleRes = UnDecorateSymbolName(inSymbol, demangleBuf, sizeof(demangleBuf), UNDNAME_COMPLETE);
+ if(0 != demangleRes)
+ {
+ if (strcmp(demangleBuf, "`string'") == 0)
+ {
+
+ /* attempt manual demangling of string prefix.. */
+
+ /* first make sure we have enough space for the
+ updated string - the demangled string will
+ always be shorter than strlen(inSymbol) and the
+ prologue will always be longer than the
+ "string: " that we tack on the front of the string
+ */
+ char *curresult = retval = malloc(strlen(inSymbol) + 11);
+ const char *curchar = inSymbol;
+
+ int state = DEMANGLE_STATE_START;
+
+ /* the hex state is for stuff like ?$EA which
+ really means hex value 0x40 */
+ char hex_state = 0;
+ char string_is_unicode = 0;
+
+ /* sometimes we get a null-termination before the
+ final @ sign - in that case, remember that
+ we've seen the whole string */
+ int have_null_char = 0;
+
+ /* stick our user-readable prefix on */
+ strcpy(curresult, "string: \"");
+ curresult += 9;
+
+ while (*curchar) {
+
+ // process current state
+ switch (state) {
+
+ /* the Prologue states are divided up so
+ that someday we can try to decode
+ the random letters in between the '@'
+ signs. Also, some strings only have 2
+ prologue '@' signs, so we have to
+ figure out how to distinguish between
+ them at some point. */
+ case DEMANGLE_STATE_START:
+ if (*curchar == '@')
+ state = DEMANGLE_STATE_PROLOGUE_1;
+ /* ignore all other states */
+ break;
+
+ case DEMANGLE_STATE_PROLOGUE_1:
+ switch (*curchar) {
+ case '0':
+ string_is_unicode=0;
+ state = DEMANGLE_STATE_HAVE_TYPE;
+ break;
+ case '1':
+ string_is_unicode=1;
+ state = DEMANGLE_STATE_HAVE_TYPE;
+ break;
+
+ /* ignore all other characters */
+ }
+ break;
+
+ case DEMANGLE_STATE_HAVE_TYPE:
+ if (*curchar >= '0' && *curchar <= '9') {
+ state = DEMANGLE_STATE_DEC_LENGTH;
+ } else if (*curchar >= 'A' && *curchar <= 'Z') {
+ state = DEMANGLE_STATE_HEX_LENGTH;
+ }
+ case DEMANGLE_STATE_DEC_LENGTH:
+ /* decimal lengths don't have the 2nd
+ field
+ */
+ if (*curchar == '@')
+ state = DEMANGLE_STATE_NORMAL;
+ break;
+
+ case DEMANGLE_STATE_HEX_LENGTH:
+ /* hex lengths have a 2nd field
+ (though I have no idea what it is for)
+ */
+ if (*curchar == '@')
+ state = DEMANGLE_STATE_PROLOGUE_SECONDARY;
+ break;
+
+ case DEMANGLE_STATE_PROLOGUE_SECONDARY:
+ if (*curchar == '@')
+ state = DEMANGLE_STATE_NORMAL;
+ break;
+
+ case DEMANGLE_STATE_NORMAL:
+ switch (*curchar) {
+ case '?':
+ state = DEMANGLE_STATE_QDECODE;
+ break;
+ case '@':
+ state = DEMANGLE_STATE_STOP;
+ break;
+ default:
+ *curresult++ = DEMANGLE_SAFE_CHAR(*curchar);
+ state = DEMANGLE_STATE_NORMAL;
+ break;
+ }
+ break;
+
+ /* found a '?' */
+ case DEMANGLE_STATE_QDECODE:
+ state = DEMANGLE_STATE_NORMAL;
+
+ /* there are certain shortcuts, like
+ "?3" means ":"
+ */
+ switch (*curchar) {
+ case '1':
+ *curresult++ = '/';
+ break;
+ case '2':
+ *curresult++ = '\\';
+ break;
+ case '3':
+ *curresult++ = ':';
+ break;
+ case '4':
+ *curresult++ = '.';
+ break;
+ case '5':
+ *curresult++ = ' ';
+ break;
+ case '6':
+ *curresult++ = '\\';
+ *curresult++ = 'n';
+ break;
+ case '8':
+ *curresult++ = '\'';
+ break;
+ case '9':
+ *curresult++ = '-';
+ break;
+
+ /* any other arbitrary ASCII value can
+ be stored by prefixing it with ?$
+ */
+ case '$':
+ state = DEMANGLE_STATE_DOLLAR_1;
+ }
+ break;
+
+ case DEMANGLE_STATE_DOLLAR_1:
+ /* first digit of ?$ notation. All digits
+ are hex, represented starting with the
+ capital leter 'A' such that 'A' means 0x0,
+ 'B' means 0x1, 'K' means 0xA
+ */
+ hex_state = (*curchar - 'A') * 0x10;
+ state = DEMANGLE_STATE_DOLLAR_2;
+ break;
+
+ case DEMANGLE_STATE_DOLLAR_2:
+ /* same mechanism as above */
+ hex_state += (*curchar - 'A');
+ if (hex_state) {
+ *curresult++ = DEMANGLE_SAFE_CHAR(hex_state);
+ have_null_char = 0;
+ }
+ else {
+ have_null_char = 1;
+ }
+
+ state = DEMANGLE_STATE_NORMAL;
+ break;
+
+ case DEMANGLE_STATE_STOP:
+ break;
+ }
+
+ curchar++;
+ }
+
+ /* add the appropriate termination depending
+ if we completed the string or not */
+ if (!have_null_char)
+ strcpy(curresult, "...\"");
+ else
+ strcpy(curresult, "\"");
+ } else {
+ retval = strdup(demangleBuf);
+ }
+ }
+ else
+ {
+ /*
+ ** fall back to normal.
+ */
+ retval = strdup(inSymbol);
+ }
+ }
+ else if('_' == inSymbol[0])
+ {
+ retval = strdup(inSymbol + 1);
+ }
+ else
+ {
+ retval = strdup(inSymbol);
+ }
+
+ /*
+ ** May need to rewrite the symbol if an import.
+ */
+ if(NULL != retval && isImport)
+ {
+ const char importPrefix[] = "__declspec(dllimport) ";
+ char importBuf[0x200];
+ int printRes = 0;
+
+ printRes = _snprintf(importBuf, sizeof(importBuf), "%s%s", importPrefix, retval);
+ free(retval);
+ retval = NULL;
+
+ if(printRes > 0)
+ {
+ retval = strdup(importBuf);
+ }
+ }
+ }
+#else /* F_DEMANGLE */
+ retval = strdup(inSymbol);
+#endif /* F_DEMANGLE */
+
+ return retval;
+}
+
+
+int readmap(Options* inOptions, MSMap_Module* inModule)
+/*
+** Read the input line by line, adding it to the module.
+*/
+{
+ int retval = 0;
+ char lineBuffer[0x400];
+ char* current = NULL;
+ MSMap_ReadState fsm;
+ int len = 0;
+ int forceContinue = 0;
+
+ memset(&fsm, 0, sizeof(fsm));
+
+ /*
+ ** Read the map file line by line.
+ ** We keep a simple state machine to determine what we're looking at.
+ */
+ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput))
+ {
+ if(forceContinue)
+ {
+ /*
+ ** Used to skip anticipated blank lines.
+ */
+ forceContinue--;
+ continue;
+ }
+
+ current = skipWhite(lineBuffer);
+ trimWhite(current);
+
+ len = strlen(current);
+
+ if(fsm.mHasModule)
+ {
+ if(fsm.mHasTimestamp)
+ {
+ if(fsm.mHasPreferredLoadAddress)
+ {
+ if(fsm.mHasSegmentData)
+ {
+ if(fsm.mHasPublicSymbolData)
+ {
+ if(fsm.mHasEntryPoint)
+ {
+ if(fsm.mFoundStaticSymbols)
+ {
+ /*
+ ** A blank line means we've reached the end of all static symbols.
+ */
+ if(len)
+ {
+ /*
+ ** We're adding a new symbol.
+ ** Make sure we have room for it.
+ */
+ if(inModule->mSymbolCapacity == inModule->mSymbolCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(inModule->mSymbols, sizeof(MSMap_Symbol) * (inModule->mSymbolCapacity + MSMAP_SYMBOL_GROWBY));
+ if(NULL != moved)
+ {
+ inModule->mSymbolCapacity += MSMAP_SYMBOL_GROWBY;
+ inModule->mSymbols = (MSMap_Symbol*)moved;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to grow symbols.");
+ }
+ }
+
+ if(0 == retval && inModule->mSymbolCapacity > inModule->mSymbolCount)
+ {
+ MSMap_Symbol* theSymbol = NULL;
+ unsigned index = 0;
+ int scanRes = 0;
+ char symbolBuf[0x200];
+
+ index = inModule->mSymbolCount;
+ inModule->mSymbolCount++;
+ theSymbol = (inModule->mSymbols + index);
+
+ memset(theSymbol, 0, sizeof(MSMap_Symbol));
+ theSymbol->mScope = STATIC;
+
+ scanRes = sscanf(current, "%x:%x %s %x", (unsigned*)&(theSymbol->mPrefix), (unsigned*)&(theSymbol->mOffset), symbolBuf, (unsigned*)&(theSymbol->mRVABase));
+ if(4 == scanRes)
+ {
+ theSymbol->mSymbol = symdup(symbolBuf);
+
+ if(0 == retval)
+ {
+ if(NULL != theSymbol->mSymbol)
+ {
+ char *last = lastWord(current);
+
+ theSymbol->mObject = strdup(last);
+ if(NULL == theSymbol->mObject)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, last, "Unable to copy object name.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, symbolBuf, "Unable to copy symbol name.");
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to scan static symbols.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** All done.
+ */
+ break;
+ }
+ }
+ else
+ {
+ /*
+ ** Static symbols are optional.
+ ** If no static symbols we're done.
+ ** Otherwise, set the flag such that it will work more.
+ */
+ if(0 == strcmp(current, "Static symbols"))
+ {
+ fsm.mFoundStaticSymbols = __LINE__;
+ forceContinue = 1;
+ }
+ else
+ {
+ /*
+ ** All done.
+ */
+ break;
+ }
+ }
+ }
+ else
+ {
+ int scanRes = 0;
+
+ scanRes = sscanf(current, "entry point at %x:%x", (unsigned*)&(inModule->mEntryPrefix), (unsigned*)&(inModule->mEntryOffset));
+ if(2 == scanRes)
+ {
+ fsm.mHasEntryPoint = __LINE__;
+ forceContinue = 1;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current, "Unable to obtain entry point.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Skip the N lines of public symbol data (column headers).
+ */
+ if(2 <= fsm.mHasPublicSymbolDataSkippedLines)
+ {
+ /*
+ ** A blank line indicates end of public symbols.
+ */
+ if(len)
+ {
+ /*
+ ** We're adding a new symbol.
+ ** Make sure we have room for it.
+ */
+ if(inModule->mSymbolCapacity == inModule->mSymbolCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(inModule->mSymbols, sizeof(MSMap_Symbol) * (inModule->mSymbolCapacity + MSMAP_SYMBOL_GROWBY));
+ if(NULL != moved)
+ {
+ inModule->mSymbolCapacity += MSMAP_SYMBOL_GROWBY;
+ inModule->mSymbols = (MSMap_Symbol*)moved;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to grow symbols.");
+ }
+ }
+
+ if(0 == retval && inModule->mSymbolCapacity > inModule->mSymbolCount)
+ {
+ MSMap_Symbol* theSymbol = NULL;
+ unsigned index = 0;
+ int scanRes = 0;
+ char symbolBuf[0x200];
+
+ index = inModule->mSymbolCount;
+ inModule->mSymbolCount++;
+ theSymbol = (inModule->mSymbols + index);
+
+ memset(theSymbol, 0, sizeof(MSMap_Symbol));
+ theSymbol->mScope = PUBLIC;
+
+ scanRes = sscanf(current, "%x:%x %s %x", (unsigned*)&(theSymbol->mPrefix), (unsigned*)&(theSymbol->mOffset), symbolBuf, (unsigned *)&(theSymbol->mRVABase));
+ if(4 == scanRes)
+ {
+ theSymbol->mSymbol = symdup(symbolBuf);
+
+ if(NULL != theSymbol->mSymbol)
+ {
+ char *last = lastWord(current);
+
+ theSymbol->mObject = strdup(last);
+ if(NULL != theSymbol->mObject)
+ {
+ /*
+ ** Finally, attempt to lookup the actual size of the symbol
+ ** if there is a symbol DB available.
+ */
+ retval = fillSymbolSizeFromDB(inOptions, inModule, theSymbol, symbolBuf);
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, last, "Unable to copy object name.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, symbolBuf, "Unable to copy symbol name.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to scan public symbols.");
+ }
+ }
+ }
+ else
+ {
+ fsm.mHasPublicSymbolData = __LINE__;
+ }
+ }
+ else
+ {
+ fsm.mHasPublicSymbolDataSkippedLines++;
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Skip the first line of segment data (column headers).
+ ** Mark that we've begun grabbing segement data.
+ */
+ if(fsm.mSegmentDataSkippedLine)
+ {
+ /*
+ ** A blank line means end of the segment data.
+ */
+ if(len)
+ {
+ /*
+ ** We're adding a new segment.
+ ** Make sure we have room for it.
+ */
+ if(inModule->mSegmentCapacity == inModule->mSegmentCount)
+ {
+ void* moved = NULL;
+
+ moved = realloc(inModule->mSegments, sizeof(MSMap_Segment) * (inModule->mSegmentCapacity + MSMAP_SEGMENT_GROWBY));
+ if(NULL != moved)
+ {
+ inModule->mSegmentCapacity += MSMAP_SEGMENT_GROWBY;
+ inModule->mSegments = (MSMap_Segment*)moved;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to grow segments.");
+ }
+ }
+
+ if(0 == retval && inModule->mSegmentCapacity > inModule->mSegmentCount)
+ {
+ MSMap_Segment* theSegment = NULL;
+ unsigned index = 0;
+ char classBuf[0x10];
+ char nameBuf[0x20];
+ int scanRes = 0;
+
+ index = inModule->mSegmentCount;
+ inModule->mSegmentCount++;
+ theSegment = (inModule->mSegments + index);
+
+ memset(theSegment, 0, sizeof(MSMap_Segment));
+
+ scanRes = sscanf(current, "%x:%x %xH %s %s", (unsigned*)&(theSegment->mPrefix), (unsigned*)&(theSegment->mOffset), (unsigned*)&(theSegment->mLength), nameBuf, classBuf);
+ if(5 == scanRes)
+ {
+ if('.' == nameBuf[0])
+ {
+ theSegment->mSegment = strdup(&nameBuf[1]);
+ }
+ else
+ {
+ theSegment->mSegment = strdup(nameBuf);
+ }
+
+ if(NULL != theSegment->mSegment)
+ {
+ if(0 == strcmp("DATA", classBuf))
+ {
+ theSegment->mClass = DATA;
+ }
+ else if(0 == strcmp("CODE", classBuf))
+ {
+ theSegment->mClass = CODE;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, classBuf, "Unrecognized segment class.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, nameBuf, "Unable to copy segment name.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inModule->mModule, "Unable to scan segments.");
+ }
+ }
+ }
+ else
+ {
+ fsm.mHasSegmentData = __LINE__;
+ }
+ }
+ else
+ {
+ fsm.mSegmentDataSkippedLine = __LINE__;
+ }
+ }
+ }
+ else
+ {
+ int scanRes = 0;
+
+ /*
+ ** The PLA has a particular format.
+ */
+ scanRes = sscanf(current, "Preferred load address is %x", (unsigned*)&(inModule->mPreferredLoadAddress));
+ if(1 == scanRes)
+ {
+ fsm.mHasPreferredLoadAddress = __LINE__;
+ forceContinue = 1;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current, "Unable to obtain preferred load address.");
+ }
+ }
+ }
+ else
+ {
+ int scanRes = 0;
+
+ /*
+ ** The timestamp has a particular format.
+ */
+ scanRes = sscanf(current, "Timestamp is %x", (unsigned*)&(inModule->mTimestamp));
+ if(1 == scanRes)
+ {
+ fsm.mHasTimestamp = __LINE__;
+ forceContinue = 1;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current, "Unable to obtain timestamp.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** The module is on a line by itself.
+ */
+ inModule->mModule = strdup(current);
+ if(NULL != inModule->mModule)
+ {
+ fsm.mHasModule = __LINE__;
+ forceContinue = 1;
+
+ if(0 != inOptions->mMatchModuleCount)
+ {
+ unsigned matchLoop = 0;
+
+ /*
+ ** If this module name doesn't match, then bail.
+ ** Compare in a case sensitive manner, exact match only.
+ */
+ for(matchLoop = 0; matchLoop < inOptions->mMatchModuleCount; matchLoop++)
+ {
+ if(0 == strcmp(inModule->mModule, inOptions->mMatchModules[matchLoop]))
+ {
+ break;
+ }
+ }
+
+ if(matchLoop == inOptions->mMatchModuleCount)
+ {
+ /*
+ ** A match did not occur, bail out of read loop.
+ ** No error, however.
+ */
+ break;
+ }
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current, "Unable to obtain module.");
+ }
+ }
+ }
+
+ if(0 == retval && 0 != ferror(inOptions->mInput))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file.");
+ }
+
+ return retval;
+}
+
+
+static int qsortRVABase(const void* in1, const void* in2)
+/*
+** qsort callback to sort the symbols by their RVABase.
+*/
+{
+ MSMap_Symbol* sym1 = (MSMap_Symbol*)in1;
+ MSMap_Symbol* sym2 = (MSMap_Symbol*)in2;
+ int retval = 0;
+
+ if(sym1->mRVABase < sym2->mRVABase)
+ {
+ retval = -1;
+ }
+ else if(sym1->mRVABase > sym2->mRVABase)
+ {
+ retval = 1;
+ }
+
+ return retval;
+}
+
+
+static int tsvout(Options* inOptions, unsigned inSize, MSMap_SegmentClass inClass, MSMap_SymbolScope inScope, const char* inModule, const char* inSegment, const char* inObject, const char* inSymbol)
+/*
+** Output a line of map information separated by tabs.
+** Some items (const char*), if not present, will receive a default value.
+*/
+{
+ int retval = 0;
+
+ /*
+ ** No need to output on no size.
+ ** This can happen with zero sized segments,
+ ** or an imported symbol which has multiple names (one will count).
+ */
+ if(0 != inSize)
+ {
+ char objectBuf[0x100];
+ const char* symScope = NULL;
+ const char* segClass = NULL;
+ const char* undefined = "UNDEF";
+
+ /*
+ ** Fill in unspecified values.
+ */
+ if(NULL == inObject)
+ {
+ sprintf(objectBuf, "%s:%s:%s", undefined, inModule, inSegment);
+ inObject = objectBuf;
+ }
+ if(NULL == inSymbol)
+ {
+ inSymbol = inObject;
+ }
+
+ /*
+ ** Convert some enumerations to text.
+ */
+ switch(inClass)
+ {
+ case CODE:
+ segClass = "CODE";
+ break;
+ case DATA:
+ segClass = "DATA";
+ break;
+ default:
+ retval = __LINE__;
+ ERROR_REPORT(retval, "", "Unable to determine class for output.");
+ break;
+ }
+
+ switch(inScope)
+ {
+ case PUBLIC:
+ symScope = "PUBLIC";
+ break;
+ case STATIC:
+ symScope = "STATIC";
+ break;
+ case UNDEFINED:
+ symScope = undefined;
+ break;
+ default:
+ retval = __LINE__;
+ ERROR_REPORT(retval, "", "Unable to determine scope for symbol.");
+ break;
+ }
+
+ if(0 == retval)
+ {
+ int printRes = 0;
+
+ printRes = fprintf(inOptions->mOutput,
+ "%.8X\t%s\t%s\t%s\t%s\t%s\t%s\n",
+ inSize,
+ segClass,
+ symScope,
+ inModule,
+ inSegment,
+ inObject,
+ inSymbol
+ );
+
+ if(0 > printRes)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mOutputName, "Unable to output tsv data.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanModule(MSMap_Module* inModule)
+{
+ unsigned loop = 0;
+
+ for(loop = 0; loop < inModule->mSymbolCount; loop++)
+ {
+ CLEANUP(inModule->mSymbols[loop].mObject);
+ CLEANUP(inModule->mSymbols[loop].mSymbol);
+ }
+ CLEANUP(inModule->mSymbols);
+
+ for(loop = 0; loop < inModule->mSegmentCount; loop++)
+ {
+ CLEANUP(inModule->mSegments[loop].mSegment);
+ }
+ CLEANUP(inModule->mSegments);
+
+ CLEANUP(inModule->mModule);
+
+ memset(inModule, 0, sizeof(MSMap_Module));
+}
+
+
+int map2tsv(Options* inOptions)
+/*
+** Read all input.
+** Output tab separated value data.
+*/
+{
+ int retval = 0;
+ MSMap_Module module;
+
+ memset(&module, 0, sizeof(module));
+
+ /*
+ ** Read in the map file.
+ */
+ retval = readmap(inOptions, &module);
+ if(0 == retval)
+ {
+ unsigned symLoop = 0;
+ MSMap_Symbol* symbol = NULL;
+ unsigned secLoop = 0;
+ MSMap_Segment* section = NULL;
+ unsigned size = 0;
+ unsigned dbSize = 0;
+ unsigned offsetSize = 0;
+ unsigned endOffset = 0;
+
+ /*
+ ** Quick sort the symbols via RVABase.
+ */
+ qsort(module.mSymbols, module.mSymbolCount, sizeof(MSMap_Symbol), qsortRVABase);
+
+ /*
+ ** Go through all the symbols (in order by sort).
+ ** Output their sizes.
+ */
+ for(symLoop = 0; 0 == retval && symLoop < module.mSymbolCount; symLoop++)
+ {
+ symbol = &module.mSymbols[symLoop];
+ section = getSymbolSection(&module, symbol);
+ if (!section)
+ continue;
+
+ /*
+ ** Use the symbol DB size if available.
+ */
+ dbSize = symbol->mSymDBSize;
+
+ /*
+ ** Guess using offsets.
+ ** Is there a next symbol available? If so, its start offset is the end of this symbol.
+ ** Otherwise, our section offset + length is the end of this symbol.
+ **
+ ** The trick is, the DB size can not go beyond the offset size, for sanity.
+ */
+
+ /*
+ ** Try next symbol, but only if in same section.
+ ** If still not, use the end of the segment.
+ ** This implies we were the last symbol in the segment.
+ */
+ if((symLoop + 1) < module.mSymbolCount)
+ {
+ MSMap_Symbol* nextSymbol = NULL;
+ MSMap_Segment* nextSection = NULL;
+
+ nextSymbol = &module.mSymbols[symLoop + 1];
+ nextSection = getSymbolSection(&module, nextSymbol);
+
+ if(section == nextSection)
+ {
+ endOffset = nextSymbol->mOffset;
+ }
+ else
+ {
+ endOffset = section->mOffset + section->mLength;
+ }
+ }
+ else
+ {
+ endOffset = section->mOffset + section->mLength;
+ }
+
+ /*
+ ** Can now guess at size.
+ */
+ offsetSize = endOffset - symbol->mOffset;
+
+ /*
+ ** Now, determine which size to use.
+ ** This is really a sanity check as well.
+ */
+ size = offsetSize;
+ if(0 != dbSize)
+ {
+ if(dbSize < offsetSize)
+ {
+ size = dbSize;
+ }
+ }
+
+ /*
+ ** Output the symbol with the size.
+ */
+ retval = tsvout(inOptions,
+ size,
+ section->mClass,
+ symbol->mScope,
+ module.mModule,
+ section->mSegment,
+ symbol->mObject,
+ symbol->mSymbol
+ );
+
+ /*
+ ** Make sure we mark this amount of space as used in the section.
+ */
+ section->mUsed += size;
+ }
+
+ /*
+ ** Go through the sections, and those whose length is longer than the
+ ** amount of space used, output dummy filler values.
+ */
+ for(secLoop = 0; 0 == retval && secLoop < module.mSegmentCount; secLoop++)
+ {
+ section = &module.mSegments[secLoop];
+
+ if(section && section->mUsed < section->mLength)
+ {
+ retval = tsvout(inOptions,
+ section->mLength - section->mUsed,
+ section->mClass,
+ UNDEFINED,
+ module.mModule,
+ section->mSegment,
+ NULL,
+ NULL
+ );
+ }
+ }
+ }
+
+ /*
+ ** Cleanup.
+ */
+ cleanModule(&module);
+
+ return retval;
+}
+
+
+int initOptions(Options* outOptions, int inArgc, char** inArgv)
+/*
+** returns int 0 if successful.
+*/
+{
+ int retval = 0;
+ int loop = 0;
+ int switchLoop = 0;
+ int match = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ Switch* current = NULL;
+
+ /*
+ ** Set any defaults.
+ */
+ memset(outOptions, 0, sizeof(Options));
+ outOptions->mProgramName = inArgv[0];
+ outOptions->mInput = stdin;
+ outOptions->mInputName = strdup("stdin");
+ outOptions->mOutput = stdout;
+ outOptions->mOutputName = strdup("stdout");
+
+ if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup.");
+ }
+
+ /*
+ ** Go through and attempt to do the right thing.
+ */
+ for(loop = 1; loop < inArgc && 0 == retval; loop++)
+ {
+ match = 0;
+ current = NULL;
+
+ for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++)
+ {
+ if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+ else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+
+ if(match)
+ {
+ if(gSwitches[switchLoop]->mHasValue)
+ {
+ /*
+ ** Attempt to absorb next option to fullfill value.
+ */
+ if(loop + 1 < inArgc)
+ {
+ loop++;
+
+ current = gSwitches[switchLoop];
+ current->mValue = inArgv[loop];
+ }
+ }
+ else
+ {
+ current = gSwitches[switchLoop];
+ }
+
+ break;
+ }
+ }
+
+ if(0 == match)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch.");
+ }
+ else if(NULL == current)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value.");
+ }
+ else
+ {
+ /*
+ ** Do something based on address/swtich.
+ */
+ if(current == &gInputSwitch)
+ {
+ CLEANUP(outOptions->mInputName);
+ if(NULL != outOptions->mInput && stdin != outOptions->mInput)
+ {
+ fclose(outOptions->mInput);
+ outOptions->mInput = NULL;
+ }
+
+ outOptions->mInput = fopen(current->mValue, "r");
+ if(NULL == outOptions->mInput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open input file.");
+ }
+ else
+ {
+ outOptions->mInputName = strdup(current->mValue);
+ if(NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gOutputSwitch)
+ {
+ CLEANUP(outOptions->mOutputName);
+ if(NULL != outOptions->mOutput && stdout != outOptions->mOutput)
+ {
+ fclose(outOptions->mOutput);
+ outOptions->mOutput = NULL;
+ }
+
+ outOptions->mOutput = fopen(current->mValue, "a");
+ if(NULL == outOptions->mOutput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open output file.");
+ }
+ else
+ {
+ outOptions->mOutputName = strdup(current->mValue);
+ if(NULL == outOptions->mOutputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gHelpSwitch)
+ {
+ outOptions->mHelp = __LINE__;
+ }
+ else if(current == &gMatchModuleSwitch)
+ {
+ void* moved = NULL;
+
+ /*
+ ** Add the value to the list of allowed module names.
+ */
+ moved = realloc(outOptions->mMatchModules, sizeof(char*) * (outOptions->mMatchModuleCount + 1));
+ if(NULL != moved)
+ {
+ outOptions->mMatchModules = (char**)moved;
+ outOptions->mMatchModules[outOptions->mMatchModuleCount] = strdup(current->mValue);
+ if(NULL != outOptions->mMatchModules[outOptions->mMatchModuleCount])
+ {
+ outOptions->mMatchModuleCount++;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate string.");
+ }
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to allocate space for string.");
+ }
+ }
+ else if(current == &gSymDBSwitch)
+ {
+ CLEANUP(outOptions->mSymDBName);
+ outOptions->mSymDBName = strdup(current->mValue);
+ if(NULL == outOptions->mSymDBName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to duplicate symbol db name.");
+ }
+ }
+ else if(current == &gBatchModeSwitch)
+ {
+ outOptions->mBatchMode = __LINE__;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "No handler for command line switch.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanOptions(Options* inOptions)
+/*
+** Clean up any open handles, et. al.
+*/
+{
+ CLEANUP(inOptions->mInputName);
+ if(NULL != inOptions->mInput && stdin != inOptions->mInput)
+ {
+ fclose(inOptions->mInput);
+ }
+ CLEANUP(inOptions->mOutputName);
+ if(NULL != inOptions->mOutput && stdout != inOptions->mOutput)
+ {
+ fclose(inOptions->mOutput);
+ }
+ while(0 != inOptions->mMatchModuleCount)
+ {
+ inOptions->mMatchModuleCount--;
+ CLEANUP(inOptions->mMatchModules[inOptions->mMatchModuleCount]);
+ }
+ CLEANUP(inOptions->mMatchModules);
+
+ cleanSymDB(&inOptions->mSymDB);
+
+ memset(inOptions, 0, sizeof(Options));
+}
+
+
+void showHelp(Options* inOptions)
+/*
+** Show some simple help text on usage.
+*/
+{
+ int loop = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ const char* valueText = NULL;
+
+ printf("usage:\t%s [arguments]\n", inOptions->mProgramName);
+ printf("\n");
+ printf("arguments:\n");
+
+ for(loop = 0; loop < switchCount; loop++)
+ {
+ if(gSwitches[loop]->mHasValue)
+ {
+ valueText = " <value>";
+ }
+ else
+ {
+ valueText = "";
+ }
+
+ printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText);
+ printf("\t %s%s", gSwitches[loop]->mShortName, valueText);
+ printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription);
+ }
+
+ printf("This tool normalizes MS linker .map files for use by other tools.\n");
+}
+
+
+int batchMode(Options* inOptions)
+/*
+** Batch mode means that the input file is actually a list of map files.
+** We simply swap out our input file names while we do this.
+*/
+{
+ int retval = 0;
+ char lineBuf[0x400];
+ FILE* realInput = NULL;
+ char* realInputName = NULL;
+ FILE* mapFile = NULL;
+ int finalRes = 0;
+
+ realInput = inOptions->mInput;
+ realInputName = inOptions->mInputName;
+
+ while(0 == retval && NULL != fgets(lineBuf, sizeof(lineBuf), realInput))
+ {
+ trimWhite(lineBuf);
+
+ /*
+ ** Skip/allow blank lines.
+ */
+ if('\0' == lineBuf[0])
+ {
+ continue;
+ }
+
+ /*
+ ** Override what we believe to be the input for this line.
+ */
+ inOptions->mInputName = lineBuf;
+ inOptions->mInput = fopen(lineBuf, "r");
+ if(NULL != inOptions->mInput)
+ {
+ int mapRes = 0;
+
+ /*
+ ** Do it.
+ */
+ mapRes = map2tsv(inOptions);
+
+ /*
+ ** We report the first error that we encounter, but we continue.
+ ** This is batch mode after all.
+ */
+ if(0 == finalRes)
+ {
+ finalRes = mapRes;
+ }
+
+ /*
+ ** Close the input file.
+ */
+ fclose(inOptions->mInput);
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, lineBuf, "Unable to open map file.");
+ break;
+ }
+ }
+
+ if(0 == retval && 0 != ferror(realInput))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, realInputName, "Unable to read file.");
+ }
+
+ /*
+ ** Restore what we've swapped.
+ */
+ inOptions->mInput = realInput;
+ inOptions->mInputName = realInputName;
+
+ /*
+ ** Report first map file error if there were no other operational
+ ** problems.
+ */
+ if(0 == retval)
+ {
+ retval = finalRes;
+ }
+
+ return retval;
+}
+
+
+int main(int inArgc, char** inArgv)
+{
+ int retval = 0;
+ Options options;
+
+ retval = initOptions(&options, inArgc, inArgv);
+ if(options.mHelp)
+ {
+ showHelp(&options);
+ }
+ else if(0 == retval)
+ {
+ if(options.mBatchMode)
+ {
+ retval = batchMode(&options);
+ }
+ else
+ {
+ retval = map2tsv(&options);
+ }
+ }
+
+ cleanOptions(&options);
+ return retval;
+}
+
diff --git a/chromium/third_party/codesighs/nm2tsv.c b/chromium/third_party/codesighs/nm2tsv.c
new file mode 100644
index 00000000000..07b4563b07a
--- /dev/null
+++ b/chromium/third_party/codesighs/nm2tsv.c
@@ -0,0 +1,505 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nm2tsv.c code, released
+ * Oct 10, 2002.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 10-October-2002
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg));
+#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0)
+
+
+typedef struct __struct_Options
+/*
+** Options to control how we perform.
+**
+** mProgramName Used in help text.
+** mInput File to read for input.
+** Default is stdin.
+** mInputName Name of the file.
+** mOutput Output file, append.
+** Default is stdout.
+** mOutputName Name of the file.
+** mHelp Whether or not help should be shown.
+*/
+{
+ const char* mProgramName;
+ FILE* mInput;
+ char* mInputName;
+ FILE* mOutput;
+ char* mOutputName;
+ int mHelp;
+}
+Options;
+
+
+typedef struct __struct_Switch
+/*
+** Command line options.
+*/
+{
+ const char* mLongName;
+ const char* mShortName;
+ int mHasValue;
+ const char* mValue;
+ const char* mDescription;
+}
+Switch;
+
+#define DESC_NEWLINE "\n\t\t"
+
+static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."};
+static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."};
+static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."};
+
+static Switch* gSwitches[] = {
+ &gInputSwitch,
+ &gOutputSwitch,
+ &gHelpSwitch
+};
+
+
+char* scanWhite(char* inScan)
+/*
+** Scan for whitespace.
+*/
+{
+ char* retval = inScan;
+
+ while('\0' != *retval && 0 == isspace(*retval))
+ {
+ retval++;
+ }
+
+ return retval;
+}
+
+
+void trimWhite(char* inString)
+/*
+** Remove any whitespace from the end of the string.
+*/
+{
+ int len = strlen(inString);
+
+ while(len)
+ {
+ len--;
+
+ if(isspace(*(inString + len)))
+ {
+ *(inString + len) = '\0';
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+int nm2tsv(Options* inOptions)
+/*
+** Read all input.
+** Output tab separated value data.
+**
+** We expect our data to be in a particular format.
+** nm --format=bsd --size-sort --print-file-name --demangle
+*/
+{
+ int retval = 0;
+ char lineBuffer[4096]; /* yes, the are some very large symbols */
+ char* module = NULL;
+ char* size = NULL;
+ char* type = NULL;
+ char* symbol = NULL;
+
+ /*
+ ** Read in the nm file.
+ */
+ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput))
+ {
+ trimWhite(lineBuffer);
+
+ /*
+ ** Find the various pieces of information we'll be looking for.
+ */
+ size = strchr(lineBuffer, ':');
+ if(NULL != size)
+ {
+ *size = '\0';
+ size++;
+
+ module = strrchr(lineBuffer, '/');
+ if(NULL == module)
+ {
+ module = lineBuffer;
+ }
+ else
+ {
+ *module = '\0';
+ module++;
+ }
+
+ type = scanWhite(size);
+ *type = '\0';
+ type++;
+
+ symbol = type + 1;
+ *symbol = '\0';
+ symbol++;
+
+ /*
+ ** Skip certain types.
+ */
+ switch(*type)
+ {
+ case '-':
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ ** Simply output the data with a little more interpretation.
+ ** First is size.
+ */
+ fprintf(inOptions->mOutput, "%s\t", size);
+
+ /*
+ ** Type, CODE or DATA
+ */
+ switch(toupper(*type))
+ {
+ case 'T': /* text (code) */
+ case 'W': /* weak symbol ??? */
+ fprintf(inOptions->mOutput, "CODE\t");
+ break;
+ default:
+ fprintf(inOptions->mOutput, "DATA\t");
+ break;
+ }
+
+ /*
+ ** Scope, PUBLIC, STATIC, or UNDEF
+ */
+ if(islower(*type))
+ {
+ fprintf(inOptions->mOutput, "STATIC\t");
+ }
+ else
+ {
+ switch(*type)
+ {
+ case '?':
+ fprintf(inOptions->mOutput, "UNDEF\t");
+ break;
+ default:
+ fprintf(inOptions->mOutput, "PUBLIC\t");
+ break;
+ }
+ }
+
+ /*
+ ** Module name, segment.
+ */
+ fprintf(inOptions->mOutput, "%s\t", module);
+ fprintf(inOptions->mOutput, "%c\t", toupper(*type));
+
+ /*
+ ** Origin
+ */
+ fprintf(inOptions->mOutput, "UNDEF:%s:%c\t", module, toupper(*type));
+
+ /*
+ ** Symbol is last.
+ */
+ fprintf(inOptions->mOutput, "%s\n", symbol);
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, lineBuffer, "Malformed input line.");
+ }
+ }
+
+ if(0 == retval && 0 != ferror(inOptions->mInput))
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file.");
+ }
+
+ return retval;
+}
+
+
+int initOptions(Options* outOptions, int inArgc, char** inArgv)
+/*
+** returns int 0 if successful.
+*/
+{
+ int retval = 0;
+ int loop = 0;
+ int switchLoop = 0;
+ int match = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ Switch* current = NULL;
+
+ /*
+ ** Set any defaults.
+ */
+ memset(outOptions, 0, sizeof(Options));
+ outOptions->mProgramName = inArgv[0];
+ outOptions->mInput = stdin;
+ outOptions->mInputName = strdup("stdin");
+ outOptions->mOutput = stdout;
+ outOptions->mOutputName = strdup("stdout");
+
+ if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup.");
+ }
+
+ /*
+ ** Go through and attempt to do the right thing.
+ */
+ for(loop = 1; loop < inArgc && 0 == retval; loop++)
+ {
+ match = 0;
+ current = NULL;
+
+ for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++)
+ {
+ if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+ else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop]))
+ {
+ match = __LINE__;
+ }
+
+ if(match)
+ {
+ if(gSwitches[switchLoop]->mHasValue)
+ {
+ /*
+ ** Attempt to absorb next option to fullfill value.
+ */
+ if(loop + 1 < inArgc)
+ {
+ loop++;
+
+ current = gSwitches[switchLoop];
+ current->mValue = inArgv[loop];
+ }
+ }
+ else
+ {
+ current = gSwitches[switchLoop];
+ }
+
+ break;
+ }
+ }
+
+ if(0 == match)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch.");
+ }
+ else if(NULL == current)
+ {
+ outOptions->mHelp = __LINE__;
+ retval = __LINE__;
+ ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value.");
+ }
+ else
+ {
+ /*
+ ** Do something based on address/swtich.
+ */
+ if(current == &gInputSwitch)
+ {
+ CLEANUP(outOptions->mInputName);
+ if(NULL != outOptions->mInput && stdin != outOptions->mInput)
+ {
+ fclose(outOptions->mInput);
+ outOptions->mInput = NULL;
+ }
+
+ outOptions->mInput = fopen(current->mValue, "r");
+ if(NULL == outOptions->mInput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open input file.");
+ }
+ else
+ {
+ outOptions->mInputName = strdup(current->mValue);
+ if(NULL == outOptions->mInputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gOutputSwitch)
+ {
+ CLEANUP(outOptions->mOutputName);
+ if(NULL != outOptions->mOutput && stdout != outOptions->mOutput)
+ {
+ fclose(outOptions->mOutput);
+ outOptions->mOutput = NULL;
+ }
+
+ outOptions->mOutput = fopen(current->mValue, "a");
+ if(NULL == outOptions->mOutput)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to open output file.");
+ }
+ else
+ {
+ outOptions->mOutputName = strdup(current->mValue);
+ if(NULL == outOptions->mOutputName)
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mValue, "Unable to strdup.");
+ }
+ }
+ }
+ else if(current == &gHelpSwitch)
+ {
+ outOptions->mHelp = __LINE__;
+ }
+ else
+ {
+ retval = __LINE__;
+ ERROR_REPORT(retval, current->mLongName, "No handler for command line switch.");
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+void cleanOptions(Options* inOptions)
+/*
+** Clean up any open handles.
+*/
+{
+ CLEANUP(inOptions->mInputName);
+ if(NULL != inOptions->mInput && stdin != inOptions->mInput)
+ {
+ fclose(inOptions->mInput);
+ }
+ CLEANUP(inOptions->mOutputName);
+ if(NULL != inOptions->mOutput && stdout != inOptions->mOutput)
+ {
+ fclose(inOptions->mOutput);
+ }
+
+ memset(inOptions, 0, sizeof(Options));
+}
+
+
+void showHelp(Options* inOptions)
+/*
+** Show some simple help text on usage.
+*/
+{
+ int loop = 0;
+ const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]);
+ const char* valueText = NULL;
+
+ printf("usage:\t%s [arguments]\n", inOptions->mProgramName);
+ printf("\n");
+ printf("arguments:\n");
+
+ for(loop = 0; loop < switchCount; loop++)
+ {
+ if(gSwitches[loop]->mHasValue)
+ {
+ valueText = " <value>";
+ }
+ else
+ {
+ valueText = "";
+ }
+
+ printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText);
+ printf("\t %s%s", gSwitches[loop]->mShortName, valueText);
+ printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription);
+ }
+
+ printf("This tool normalizes nm output for use by other tools.\n");
+ printf("GNU nm is assumed for symbol type determination.\n");
+ printf("i.e. Use this tool to parse the output of:\n");
+ printf("\t/usr/bin/nm --format=bsd --size-sort --print-file-name --demangle <exefile>\n");
+}
+
+
+int main(int inArgc, char** inArgv)
+{
+ int retval = 0;
+ Options options;
+
+ retval = initOptions(&options, inArgc, inArgv);
+ if(options.mHelp)
+ {
+ showHelp(&options);
+ }
+ else if(0 == retval)
+ {
+ retval = nm2tsv(&options);
+ }
+
+ cleanOptions(&options);
+ return retval;
+}
+
diff --git a/chromium/third_party/codesighs/nm_wrap_osx.pl b/chromium/third_party/codesighs/nm_wrap_osx.pl
new file mode 100755
index 00000000000..cf1181fe0ad
--- /dev/null
+++ b/chromium/third_party/codesighs/nm_wrap_osx.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl -w
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is autosummary.linx.bash code, released
+# Oct 10, 2002.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Simon Fraser <sfraser@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use strict;
+
+#
+# A wrapper for nm that produces output listing symbol size.
+#
+my($prev_addr) = 0;
+my($prev_module) = "";
+my($prev_kind) = "";
+my($prev_symbol) = "";
+
+open(NM_OUTPUT, "nm -fnol $ARGV[0] | c++filt |") or die "nm failed to run on $ARGV[0]\n";
+while (<NM_OUTPUT>)
+{
+ my($line) = $_;
+ chomp($line);
+
+ if ($line =~ /^([^:]+):\s*([0-9a-f]{8}) (\w) (.+)$/)
+ {
+ my($module) = $1;
+ my($addr) = $2;
+ my($kind) = $3;
+ my($symbol) = $4;
+
+ #Skip absolute addresses, there should be only a few
+ if ('a' eq lc $kind) {
+ if ('trampoline_size' ne $symbol) {
+ warn "Encountered unknown absolutely addressed symbol '$symbol' in $module";
+ }
+ next;
+ }
+
+ # we expect the input to have been piped through c++filt to
+ # demangle symbols. For some reason, it doesn't always demangle
+ # all of them, so push still-mangled symbols back through c++filt again.
+ if ($symbol =~ /^(_[_Z].+)/)
+ {
+ # warn "Trying again to unmangle $1\n";
+ $symbol = `c++filt '$1'`;
+ chomp($symbol);
+ # warn "Unmangling again to $symbol\n";
+ }
+
+ my($prev_size) = hex($addr) - hex($prev_addr);
+ # print "Outputting line $line\n";
+
+ # always print one behind, because only now do we know its size
+ if ($prev_module ne "") {
+ printf "%s:%08x %s %s\n", $prev_module, $prev_size, $prev_kind, $prev_symbol;
+ }
+
+ $prev_addr = $addr;
+ $prev_module = $module;
+ $prev_kind = $kind;
+ $prev_symbol = $symbol;
+ }
+ else
+ {
+ # warn " Discaring line $line\n";
+ }
+}
+
+# we don't know how big the last symbol is, so always show 4.
+if ($prev_module ne "") {
+ printf "%s:%08x %s %s\n", $prev_module, 4, $prev_kind, $prev_symbol;
+}
diff --git a/chromium/third_party/codesighs/readelf_wrap.pl b/chromium/third_party/codesighs/readelf_wrap.pl
new file mode 100755
index 00000000000..7e2b15e1c78
--- /dev/null
+++ b/chromium/third_party/codesighs/readelf_wrap.pl
@@ -0,0 +1,192 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is readelf_wrap.pl.
+#
+# The Initial Developer of the Original Code is
+# IBM Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Brian Ryner <bryner@brianryner.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use strict;
+
+# Section fields (the full list of values is in <elf.h>)
+my $SECT_NUM = 0; # section index
+my $SECT_NAME = 1; # section name
+my $SECT_TYPE = 2; # section type
+my $SECT_ADDR = 3; # section virtual address
+my $SECT_OFF = 4; # section offset in file
+my $SECT_SIZE = 5; # size of section
+my $SECT_ES = 6; # section entry size
+my $SECT_FLG = 7; # section flags
+my $SECT_LK = 8; # link to another section
+my $SECT_INF = 9; # additional section info
+my $SECT_AL = 10; # section alignment
+
+
+# Symbol fields (note: the full list of possible values for each field
+# is given in <elf.h>)
+
+my $SYM_NUM = 0; # unique index of the symbol
+my $SYM_VALUE = 1; # value of the symbol
+my $SYM_SIZE = 2; # size of the symbol
+my $SYM_TYPE = 3; # type (NOTYPE, OBJECT, FUNC, SECTION, FILE, ...)
+my $SYM_BIND = 4; # binding/scope (LOCAL, GLOBAL, WEAK, ...)
+my $SYM_VIS = 5; # visibility (DEFAULT, INTERNAL, HIDDEN, PROTECTED)
+my $SYM_NDX = 6; # index of section the symbol is in
+my $SYM_NAME = 7; # name of the symbol
+my $SYM_FILE = 8; # (not part of readelf) file for symbol
+
+# Tell readelf to print out the list of sections and then the symbols
+die "Usage: $^X <binary>\n" unless ($#ARGV >= 0);
+my $readelf = $ENV{'READELF_PROG'};
+if (!$readelf) {
+ $readelf = 'readelf';
+}
+open(READELF_OUTPUT, "$readelf -Ss $ARGV[0] 2>/dev/null | c++filt |") or die "readelf failed to run on $ARGV[0]\n";
+
+my @section_list;
+my @symbol_list;
+my ($module) = ($ARGV[0] =~ /([^\/]+)$/);
+my $in_symbols = 0;
+
+while (<READELF_OUTPUT>) {
+
+ if (!$in_symbols) {
+ if (/^ *\[ *(\d+)\]/) {
+ my @section;
+
+ # note that we strip off the leading '.' of section names for
+ # readability
+ if (! (@section = (/^ *\[ *(\d+)\] \.([\w\.\-]+) *(\w+) *(.{8}) (.{6}[0-9a-fA-F]*) (.{6}[0-9a-fA-F]*) *(\d+) ([a-zA-Z]+ +| +[a-zA-Z]+|) *(\d+) *(\w+) *(\d+)/))) {
+ # capture the 'null' section which has no name, so that the
+ # array indices are the same as the section indices.
+
+ @section = ($1, '', 'NULL', '00000000', '000000', '000000',
+ '00', '', '0', '0', '0');
+ }
+
+ push (@section_list, \@section);
+ } elsif (/^Symbol table/) {
+ $in_symbols = 1;
+ }
+ } else {
+
+ my @sym;
+
+ if (@sym = /^\s*(\d+): (\w+)\s*(\d+)\s*(\w+)\s*(\w+)\s*(\w+)\s*(\w+) (.*)/)
+ {
+ # Filter out types of symbols that we don't care about:
+ # - anything that's not of type OBJECT or FUNC
+ # - any undefined symbols (ndx = UND[EF])
+ # - any 0-size symbols
+
+ if (($sym[$SYM_TYPE] !~ /^(OBJECT|FUNC)$/) ||
+ $sym[$SYM_NDX] eq 'UND' || $sym[$SYM_NDX] eq 'UNDEF'
+ || $sym[$SYM_SIZE] eq '0') {
+ next;
+ }
+ push (@symbol_list, \@sym);
+ }
+ elsif (/^Symbol table .*'\.symtab'/) {
+ # We've been using .dynsym up to this point, but if we have .symtab
+ # available, it will have everything in .dynsym and more.
+ # So, reset our symbol list.
+
+ @symbol_list = ();
+ }
+ }
+}
+
+close(READELF_OUTPUT);
+
+# spit them out in codesighs TSV format
+my $sym;
+my @section_sizes;
+$#section_sizes = $#section_list;
+foreach (@section_sizes) { $_ = 0; }
+
+foreach $sym (@symbol_list) {
+ # size
+ printf "%08x\t", $sym->[$SYM_SIZE];
+
+ # code or data
+ if ($sym->[$SYM_TYPE] eq 'FUNC') {
+ print "CODE\t";
+ } else { # OBJECT
+ print "DATA\t";
+ }
+
+ # scope
+ if ($sym->[$SYM_BIND] eq 'LOCAL') {
+ print "STATIC\t";
+ } elsif ($sym->[$SYM_BIND] =~ /(GLOBAL|WEAK)/) {
+ print "PUBLIC\t";
+ } else {
+ print "UNDEF\t";
+ }
+
+ # module name
+
+ print "$module\t";
+
+ # section
+ my $section = $section_list[$sym->[$SYM_NDX]]->[$SECT_NAME];
+ print "$section\t";
+
+ # should be the object file, but for now just module/section
+ print "UNDEF:$module:$section\t";
+
+ # now the symbol name
+ print $sym->[$SYM_NAME]."\n";
+
+ # update our cumulative section sizes
+ $section_sizes[$section_list[$sym->[$SYM_NDX]]->[$SECT_NUM]] += $sym->[$SYM_SIZE];
+}
+
+# Output extra entries to make the sum of the symbol sizes equal the
+# section size.
+
+my $section;
+foreach $section (@section_list) {
+
+ my $diff = hex($section->[$SECT_SIZE]) - $section_sizes[$section->[$SECT_NUM]];
+ if ($diff > 0) {
+ my $sectname = $section->[$SECT_NAME];
+ if ($section->[$SECT_NAME] =~ /^(rodata|data|text|bss)/) {
+ printf "%08x", $diff;
+ print "\tDATA\tSTATIC\t$module\t$sectname\tUNDEF:$module:$sectname\t.nosyms.$sectname\n";
+# } else {
+# print "ignoring $diff bytes of empty space in $sectname section\n";
+ }
+ }
+}