gcunused.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* gcunused.c: Routines to remove unused sections
  2. Copyright (C) 2002-2004 Sebastian Reichelt
  3. Copyright (C) 2003-2005 Kevin Kofler
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software Foundation,
  14. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  15. #include "gcunused.h"
  16. #include "manip.h"
  17. #include "special.h"
  18. // Recursively mark the target section of the specified location, if any (i.e.
  19. // if the location is non-NULL), as referenced.
  20. #define MarkLocation(Location) \
  21. if ((Location) && (Location)->Symbol) \
  22. MarkSection ((Location)->Symbol->Parent)
  23. // Mark a section as referenced. If it was not already marked, follow all relocs
  24. // from this section and recursively mark the target sections of all the relocs.
  25. static void MarkSection (SECTION *Section)
  26. {
  27. RELOC *Reloc;
  28. // If the section is already marked, return immediately.
  29. if (Section->Referenced)
  30. return;
  31. // Mark the section right now to avoid infinite recursion.
  32. Section->Referenced = TRUE;
  33. // Recursively mark the target section and the relation section of all
  34. // relocs in this section
  35. for_each (Reloc, Section->Relocs)
  36. {
  37. MarkLocation (&(Reloc->Target));
  38. MarkLocation (Reloc->Relation);
  39. }
  40. }
  41. // Free a section if it is no longer referenced. Update the ReferencedLibCount
  42. // accordingly.
  43. static void RemoveSectionIfUnused (SECTION *Section)
  44. {
  45. PROGRAM *Program = Section->Parent;
  46. SECTION *OtherSection;
  47. LIB_CALL *LibCall, *OtherSecLibCall;
  48. // Don't free the section if it is still referenced.
  49. if (Section->Referenced)
  50. return;
  51. // If this section references any libraries, and if it was the last one to
  52. // reference them, we need to mark the library as no longer referenced.
  53. for_each (LibCall, Section->LibCalls)
  54. {
  55. LIBRARY *Library = LibCall->Library;
  56. if (Library->Referenced)
  57. {
  58. for_each (OtherSection, Program->Sections)
  59. {
  60. // Not this section!
  61. if (OtherSection == Section) continue;
  62. for_each (OtherSecLibCall, OtherSection->LibCalls)
  63. {
  64. // If this library is still referenced, forget it.
  65. if (OtherSecLibCall->Library == Library) goto NextLibCall;
  66. }
  67. }
  68. // The library is no longer referenced after this section is removed.
  69. Library->Referenced = FALSE;
  70. Program->Libraries.ReferencedCount--;
  71. }
  72. NextLibCall:;
  73. }
  74. // Now free the section.
  75. FreeSection (Section);
  76. }
  77. // Remove all unused sections.
  78. void RemoveUnusedSections (PROGRAM *Program)
  79. {
  80. SECTION *Section, *NextSection;
  81. for_each (Section, Program->Sections)
  82. {
  83. // If the section is an essential section, mark it (and all sections it
  84. // references) as referenced.
  85. if (Section->Essential)
  86. MarkSection (Section);
  87. }
  88. // For each section...
  89. for (Section = GetFirst (Program->Sections); Section; Section = NextSection)
  90. {
  91. // Get the next section now, since GetNext won't work once the section
  92. // has been freed.
  93. NextSection = GetNext (Section);
  94. // Remove the section if it is unused.
  95. RemoveSectionIfUnused (Section);
  96. }
  97. }
  98. // The following 2 functions are currently needed only for external data
  99. // variable support.
  100. #ifdef DATA_VAR_SUPPORT
  101. // Mark the section containing __main as Referenced. This is a kludge
  102. // compensating for the fact that the startup section referencing __main has not
  103. // been imported at that stage.
  104. void MarkMainSection (PROGRAM *Program)
  105. {
  106. SECTION *Section;
  107. // For each section...
  108. for_each (Section, Program->Sections)
  109. {
  110. SYMBOL *Symbol;
  111. // For each symbol...
  112. for_each (Symbol, Section->Symbols)
  113. {
  114. // If the name matches, we have found the right symbol.
  115. if (Symbol->Exported && (!(strcmp ("__main", Symbol->Name))))
  116. MarkSection (Section);
  117. }
  118. }
  119. }
  120. // Clear the Referenced flag of all sections, in order to be able to run a
  121. // second RemoveUnusedSections pass at a later point.
  122. void ResetReferencedFlags (PROGRAM *Program)
  123. {
  124. SECTION *Section;
  125. for_each (Section, Program->Sections)
  126. Section->Referenced = FALSE;
  127. }
  128. #endif /* DATA_VAR_SUPPORT */