llvm-objcopy-2.patch 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. From 2ccafacb7ddd740054dbee06655749ebc55a4d86 Mon Sep 17 00:00:00 2001
  2. From: Martin Storsjo <martin@martin.st>
  3. Date: Sat, 19 Jan 2019 19:42:35 +0000
  4. Subject: [PATCH] [llvm-objcopy] [COFF] Add support for removing sections
  5. Differential Revision: https://reviews.llvm.org/D56683
  6. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351660 91177308-0d34-0410-b5e6-96231b3b80d8
  7. ---
  8. .../llvm-objcopy/COFF/remove-section.test | 210 ++++++++++++++++++
  9. tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 10 +-
  10. tools/llvm-objcopy/COFF/Object.cpp | 63 ++++++
  11. tools/llvm-objcopy/COFF/Object.h | 27 ++-
  12. tools/llvm-objcopy/COFF/Reader.cpp | 31 ++-
  13. tools/llvm-objcopy/COFF/Writer.cpp | 68 ++++--
  14. tools/llvm-objcopy/COFF/Writer.h | 1 +
  15. 7 files changed, 391 insertions(+), 19 deletions(-)
  16. create mode 100644 test/tools/llvm-objcopy/COFF/remove-section.test
  17. diff --git a/llvm/test/tools/llvm-objcopy/COFF/remove-section.test b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
  18. new file mode 100644
  19. index 00000000000..b3dfb0b98cb
  20. --- /dev/null
  21. +++ b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
  22. @@ -0,0 +1,210 @@
  23. +# RUN: yaml2obj %s > %t.in.o
  24. +#
  25. +# RUN: llvm-objdump -section-headers %t.in.o | FileCheck %s --check-prefixes=SECTIONS-PRE
  26. +# RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS-PRE
  27. +#
  28. +# RUN: llvm-objcopy -R .bss %t.in.o %t.remove-bss.o
  29. +# RUN: llvm-objdump -section-headers %t.remove-bss.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-BSS
  30. +# RUN: llvm-objdump -t %t.remove-bss.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-BSS
  31. +#
  32. +# RUN: llvm-objcopy --remove-section .bss %t.in.o %t.cmp.o
  33. +# RUN: cmp %t.remove-bss.o %t.cmp.o
  34. +#
  35. +# RUN: llvm-objcopy -R .text %t.in.o %t.remove-text.o
  36. +# RUN: llvm-objdump -section-headers %t.remove-text.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-TEXT
  37. +# RUN: llvm-objdump -t %t.remove-text.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-TEXT
  38. +#
  39. +# RUN: not llvm-objcopy -R .comdat %t.in.o %t.remove-comdat.o 2>&1 | FileCheck %s --check-prefix=ERROR-RELOC
  40. +#
  41. +# RUN: llvm-objcopy -R .text -R .comdat %t.in.o %t.remove-text-comdat.o
  42. +# RUN: llvm-objdump -section-headers %t.remove-text-comdat.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-TEXT-COMDAT
  43. +# RUN: llvm-objdump -t %t.remove-text-comdat.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-TEXT-COMDAT
  44. +#
  45. +#
  46. +# SECTIONS-PRE: Sections:
  47. +# SECTIONS-PRE-NEXT: Idx Name
  48. +# SECTIONS-PRE-NEXT: 0 .text
  49. +# SECTIONS-PRE-NEXT: 1 .bss
  50. +# SECTIONS-PRE-NEXT: 2 .comdat
  51. +# SECTIONS-PRE-NEXT: 3 .associative
  52. +# SECTIONS-PRE-EMPTY:
  53. +#
  54. +# SYMBOLS-PRE: SYMBOL TABLE:
  55. +# SYMBOLS-PRE-NEXT: {{.*}}(sec -1){{.*}} @feat.00
  56. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 1){{.*}} .text
  57. +# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
  58. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 2){{.*}} .bss
  59. +# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 2 comdat 0
  60. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 4){{.*}} .associative
  61. +# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 3 comdat 5
  62. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 3){{.*}} .comdat
  63. +# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 3 comdat 2
  64. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 3){{.*}} foo
  65. +# SYMBOLS-PRE-NEXT: {{.*}}(sec 1){{.*}} main
  66. +# SYMBOLS-PRE-EMPTY:
  67. +#
  68. +#
  69. +# Removing the .bss section removes one symbol and its aux symbol,
  70. +# and updates the section indices in symbols pointing to later
  71. +# symbols, including the aux section defintitions.
  72. +#
  73. +# Testing that the absolute symbol @feat.00 survives the section number
  74. +# mangling.
  75. +#
  76. +# SECTIONS-REMOVE-BSS: Sections:
  77. +# SECTIONS-REMOVE-BSS-NEXT: Idx Name
  78. +# SECTIONS-REMOVE-BSS-NEXT: 0 .text
  79. +# SECTIONS-REMOVE-BSS-NEXT: 1 .comdat
  80. +# SECTIONS-REMOVE-BSS-NEXT: 2 .associative
  81. +# SECTIONS-REMOVE-BSS-EMPTY:
  82. +#
  83. +# SYMBOLS-REMOVE-BSS: SYMBOL TABLE:
  84. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec -1){{.*}} @feat.00
  85. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 1){{.*}} .text
  86. +# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
  87. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 3){{.*}} .associative
  88. +# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 2 comdat 5
  89. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 2){{.*}} .comdat
  90. +# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 2 comdat 2
  91. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 2){{.*}} foo
  92. +# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 1){{.*}} main
  93. +# SYMBOLS-REMOVE-BSS-EMPTY:
  94. +#
  95. +#
  96. +# Removing the .text section is ok and just removes the external symbol
  97. +# referring to it.
  98. +#
  99. +# SECTIONS-REMOVE-TEXT: Sections:
  100. +# SECTIONS-REMOVE-TEXT-NEXT: Idx Name
  101. +# SECTIONS-REMOVE-TEXT-NEXT: 0 .bss
  102. +# SECTIONS-REMOVE-TEXT-NEXT: 1 .comdat
  103. +# SECTIONS-REMOVE-TEXT-NEXT: 2 .associative
  104. +# SECTIONS-REMOVE-TEXT-EMPTY:
  105. +#
  106. +# SYMBOLS-REMOVE-TEXT: SYMBOL TABLE:
  107. +# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec -1){{.*}} @feat.00
  108. +# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 1){{.*}} .bss
  109. +# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
  110. +# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 3){{.*}} .associative
  111. +# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 2 comdat 5
  112. +# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 2){{.*}} .comdat
  113. +# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 2 comdat 2
  114. +# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 2){{.*}} foo
  115. +# SYMBOLS-REMOVE-TEXT-EMPTY:
  116. +#
  117. +#
  118. +# Removing the .comdat section fails, since the .text section has relocations
  119. +# against it.
  120. +#
  121. +# ERROR-RELOC: Relocation target foo ({{.*}}) not found
  122. +#
  123. +#
  124. +# Removing the .comdat section and .text (with a relocation against .comdat)
  125. +# works, as it also removes the .associative section transitively.
  126. +#
  127. +# SECTIONS-REMOVE-TEXT-COMDAT: Sections:
  128. +# SECTIONS-REMOVE-TEXT-COMDAT-NEXT: Idx Name
  129. +# SECTIONS-REMOVE-TEXT-COMDAT-NEXT: 0 .bss
  130. +# SECTIONS-REMOVE-TEXT-COMDAT-EMPTY:
  131. +#
  132. +# SYMBOLS-REMOVE-TEXT-COMDAT: SYMBOL TABLE:
  133. +# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: {{.*}}(sec -1){{.*}} @feat.00
  134. +# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: {{.*}}(sec 1){{.*}} .bss
  135. +# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
  136. +# SYMBOLS-REMOVE-TEXT-COMDAT-EMPTY:
  137. +
  138. +--- !COFF
  139. +header:
  140. + Machine: IMAGE_FILE_MACHINE_AMD64
  141. + Characteristics: [ ]
  142. +sections:
  143. + - Name: .text
  144. + Characteristics: [ ]
  145. + Alignment: 4
  146. + SectionData: 488B0500000000C3
  147. + Relocations:
  148. + - VirtualAddress: 3
  149. + SymbolName: foo
  150. + Type: IMAGE_REL_AMD64_REL32
  151. + - Name: .bss
  152. + Characteristics: [ ]
  153. + Alignment: 4
  154. + SectionData: ''
  155. + - Name: .comdat
  156. + Characteristics: [ IMAGE_SCN_LNK_COMDAT ]
  157. + Alignment: 1
  158. + SectionData: '2A000000'
  159. + - Name: .associative
  160. + Characteristics: [ IMAGE_SCN_LNK_COMDAT ]
  161. + Alignment: 1
  162. + SectionData: '0000000000000000'
  163. +symbols:
  164. + - Name: '@feat.00'
  165. + Value: 0
  166. + SectionNumber: -1
  167. + SimpleType: IMAGE_SYM_TYPE_NULL
  168. + ComplexType: IMAGE_SYM_DTYPE_NULL
  169. + StorageClass: IMAGE_SYM_CLASS_STATIC
  170. + - Name: .text
  171. + Value: 0
  172. + SectionNumber: 1
  173. + SimpleType: IMAGE_SYM_TYPE_NULL
  174. + ComplexType: IMAGE_SYM_DTYPE_NULL
  175. + StorageClass: IMAGE_SYM_CLASS_STATIC
  176. + SectionDefinition:
  177. + Length: 8
  178. + NumberOfRelocations: 1
  179. + NumberOfLinenumbers: 0
  180. + CheckSum: 583624169
  181. + Number: 1
  182. + - Name: .bss
  183. + Value: 0
  184. + SectionNumber: 2
  185. + SimpleType: IMAGE_SYM_TYPE_NULL
  186. + ComplexType: IMAGE_SYM_DTYPE_NULL
  187. + StorageClass: IMAGE_SYM_CLASS_STATIC
  188. + SectionDefinition:
  189. + Length: 0
  190. + NumberOfRelocations: 0
  191. + NumberOfLinenumbers: 0
  192. + CheckSum: 0
  193. + Number: 2
  194. + - Name: .associative
  195. + Value: 0
  196. + SectionNumber: 4
  197. + SimpleType: IMAGE_SYM_TYPE_NULL
  198. + ComplexType: IMAGE_SYM_DTYPE_NULL
  199. + StorageClass: IMAGE_SYM_CLASS_STATIC
  200. + SectionDefinition:
  201. + Length: 8
  202. + NumberOfRelocations: 0
  203. + NumberOfLinenumbers: 0
  204. + CheckSum: 0
  205. + Number: 3
  206. + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
  207. + - Name: .comdat
  208. + Value: 0
  209. + SectionNumber: 3
  210. + SimpleType: IMAGE_SYM_TYPE_NULL
  211. + ComplexType: IMAGE_SYM_DTYPE_NULL
  212. + StorageClass: IMAGE_SYM_CLASS_STATIC
  213. + SectionDefinition:
  214. + Length: 4
  215. + NumberOfRelocations: 0
  216. + NumberOfLinenumbers: 0
  217. + CheckSum: 3482275674
  218. + Number: 3
  219. + Selection: IMAGE_COMDAT_SELECT_ANY
  220. + - Name: foo
  221. + Value: 0
  222. + SectionNumber: 3
  223. + SimpleType: IMAGE_SYM_TYPE_NULL
  224. + ComplexType: IMAGE_SYM_DTYPE_NULL
  225. + StorageClass: IMAGE_SYM_CLASS_EXTERNAL
  226. + - Name: main
  227. + Value: 0
  228. + SectionNumber: 1
  229. + SimpleType: IMAGE_SYM_TYPE_NULL
  230. + ComplexType: IMAGE_SYM_DTYPE_NULL
  231. + StorageClass: IMAGE_SYM_CLASS_EXTERNAL
  232. +...
  233. diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
  234. index 437dccbd3d5..dd2e4829218 100644
  235. --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
  236. +++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
  237. @@ -27,9 +27,17 @@ using namespace object;
  238. using namespace COFF;
  239. static Error handleArgs(const CopyConfig &Config, Object &Obj) {
  240. + // Perform the actual section removals.
  241. + Obj.removeSections([&Config](const Section &Sec) {
  242. + if (is_contained(Config.ToRemove, Sec.Name))
  243. + return true;
  244. +
  245. + return false;
  246. + });
  247. +
  248. // StripAll removes all symbols and thus also removes all relocations.
  249. if (Config.StripAll || Config.StripAllGNU)
  250. - for (Section &Sec : Obj.Sections)
  251. + for (Section &Sec : Obj.getMutableSections())
  252. Sec.Relocs.clear();
  253. // If we need to do per-symbol removals, initialize the Referenced field.
  254. diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
  255. index e58e161e7d2..e19cea6aa9d 100644
  256. --- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
  257. +++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
  258. @@ -7,6 +7,7 @@
  259. //===----------------------------------------------------------------------===//
  260. #include "Object.h"
  261. +#include "llvm/ADT/DenseSet.h"
  262. #include <algorithm>
  263. namespace llvm {
  264. @@ -64,6 +65,68 @@ Error Object::markSymbols() {
  265. return Error::success();
  266. }
  267. +void Object::addSections(ArrayRef<Section> NewSections) {
  268. + for (Section S : NewSections) {
  269. + S.UniqueId = NextSectionUniqueId++;
  270. + Sections.emplace_back(S);
  271. + }
  272. + updateSections();
  273. +}
  274. +
  275. +void Object::updateSections() {
  276. + SectionMap = DenseMap<ssize_t, Section *>(Sections.size());
  277. + size_t Index = 1;
  278. + for (Section &S : Sections) {
  279. + SectionMap[S.UniqueId] = &S;
  280. + S.Index = Index++;
  281. + }
  282. +}
  283. +
  284. +const Section *Object::findSection(ssize_t UniqueId) const {
  285. + auto It = SectionMap.find(UniqueId);
  286. + if (It == SectionMap.end())
  287. + return nullptr;
  288. + return It->second;
  289. +}
  290. +
  291. +void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
  292. + DenseSet<ssize_t> AssociatedSections;
  293. + auto RemoveAssociated = [&AssociatedSections](const Section &Sec) {
  294. + return AssociatedSections.count(Sec.UniqueId) == 1;
  295. + };
  296. + do {
  297. + DenseSet<ssize_t> RemovedSections;
  298. + Sections.erase(
  299. + std::remove_if(std::begin(Sections), std::end(Sections),
  300. + [ToRemove, &RemovedSections](const Section &Sec) {
  301. + bool Remove = ToRemove(Sec);
  302. + if (Remove)
  303. + RemovedSections.insert(Sec.UniqueId);
  304. + return Remove;
  305. + }),
  306. + std::end(Sections));
  307. + // Remove all symbols referring to the removed sections.
  308. + AssociatedSections.clear();
  309. + Symbols.erase(
  310. + std::remove_if(
  311. + std::begin(Symbols), std::end(Symbols),
  312. + [&RemovedSections, &AssociatedSections](const Symbol &Sym) {
  313. + // If there are sections that are associative to a removed
  314. + // section,
  315. + // remove those as well as nothing will include them (and we can't
  316. + // leave them dangling).
  317. + if (RemovedSections.count(Sym.AssociativeComdatTargetSectionId) ==
  318. + 1)
  319. + AssociatedSections.insert(Sym.TargetSectionId);
  320. + return RemovedSections.count(Sym.TargetSectionId) == 1;
  321. + }),
  322. + std::end(Symbols));
  323. + ToRemove = RemoveAssociated;
  324. + } while (!AssociatedSections.empty());
  325. + updateSections();
  326. + updateSymbols();
  327. +}
  328. +
  329. } // end namespace coff
  330. } // end namespace objcopy
  331. } // end namespace llvm
  332. diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
  333. index e6147c40b7c..a73e93620d3 100644
  334. --- a/llvm/tools/llvm-objcopy/COFF/Object.h
  335. +++ b/llvm/tools/llvm-objcopy/COFF/Object.h
  336. @@ -37,12 +37,16 @@ struct Section {
  337. ArrayRef<uint8_t> Contents;
  338. std::vector<Relocation> Relocs;
  339. StringRef Name;
  340. + ssize_t UniqueId;
  341. + size_t Index;
  342. };
  343. struct Symbol {
  344. object::coff_symbol32 Sym;
  345. StringRef Name;
  346. - ArrayRef<uint8_t> AuxData;
  347. + std::vector<uint8_t> AuxData;
  348. + ssize_t TargetSectionId;
  349. + ssize_t AssociativeComdatTargetSectionId = 0;
  350. size_t UniqueId;
  351. size_t RawIndex;
  352. bool Referenced;
  353. @@ -61,7 +65,6 @@ struct Object {
  354. uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
  355. std::vector<object::data_directory> DataDirectories;
  356. - std::vector<Section> Sections;
  357. ArrayRef<Symbol> getSymbols() const { return Symbols; }
  358. // This allows mutating individual Symbols, but not mutating the list
  359. @@ -79,14 +82,34 @@ struct Object {
  360. // all sections.
  361. Error markSymbols();
  362. + ArrayRef<Section> getSections() const { return Sections; }
  363. + // This allows mutating individual Sections, but not mutating the list
  364. + // of symbols itself.
  365. + iterator_range<std::vector<Section>::iterator> getMutableSections() {
  366. + return make_range(Sections.begin(), Sections.end());
  367. + }
  368. +
  369. + const Section *findSection(ssize_t UniqueId) const;
  370. +
  371. + void addSections(ArrayRef<Section> NewSections);
  372. + void removeSections(function_ref<bool(const Section &)> ToRemove);
  373. +
  374. private:
  375. std::vector<Symbol> Symbols;
  376. DenseMap<size_t, Symbol *> SymbolMap;
  377. size_t NextSymbolUniqueId = 0;
  378. + std::vector<Section> Sections;
  379. + DenseMap<ssize_t, Section *> SectionMap;
  380. +
  381. + ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
  382. +
  383. // Update SymbolMap and RawIndex in each Symbol.
  384. void updateSymbols();
  385. +
  386. + // Update SectionMap and Index in each Section.
  387. + void updateSections();
  388. };
  389. // Copy between coff_symbol16 and coff_symbol32.
  390. diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
  391. index d794042ae24..c8abe2913a2 100644
  392. --- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
  393. +++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
  394. @@ -11,6 +11,7 @@
  395. #include "llvm-objcopy.h"
  396. #include "llvm/ADT/ArrayRef.h"
  397. #include "llvm/ADT/StringRef.h"
  398. +#include "llvm/BinaryFormat/COFF.h"
  399. #include "llvm/Object/COFF.h"
  400. #include "llvm/Support/ErrorHandling.h"
  401. #include <cstddef>
  402. @@ -21,6 +22,7 @@ namespace objcopy {
  403. namespace coff {
  404. using namespace object;
  405. +using namespace COFF;
  406. Error COFFReader::readExecutableHeaders(Object &Obj) const {
  407. const dos_header *DH = COFFObj.getDOSHeader();
  408. @@ -58,13 +60,14 @@ Error COFFReader::readExecutableHeaders(Object &Obj) const {
  409. }
  410. Error COFFReader::readSections(Object &Obj) const {
  411. + std::vector<Section> Sections;
  412. // Section indexing starts from 1.
  413. for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
  414. const coff_section *Sec;
  415. if (auto EC = COFFObj.getSection(I, Sec))
  416. return errorCodeToError(EC);
  417. - Obj.Sections.push_back(Section());
  418. - Section &S = Obj.Sections.back();
  419. + Sections.push_back(Section());
  420. + Section &S = Sections.back();
  421. S.Header = *Sec;
  422. if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
  423. return errorCodeToError(EC);
  424. @@ -77,12 +80,14 @@ Error COFFReader::readSections(Object &Obj) const {
  425. return make_error<StringError>("Extended relocations not supported yet",
  426. object_error::parse_failed);
  427. }
  428. + Obj.addSections(Sections);
  429. return Error::success();
  430. }
  431. Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
  432. std::vector<Symbol> Symbols;
  433. Symbols.reserve(COFFObj.getRawNumberOfSymbols());
  434. + ArrayRef<Section> Sections = Obj.getSections();
  435. for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
  436. Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
  437. if (!SymOrErr)
  438. @@ -103,6 +108,26 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
  439. Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
  440. assert((Sym.AuxData.size() %
  441. (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
  442. + // Find the unique id of the section
  443. + if (SymRef.getSectionNumber() <=
  444. + 0) // Special symbol (undefined/absolute/debug)
  445. + Sym.TargetSectionId = SymRef.getSectionNumber();
  446. + else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) <
  447. + Sections.size())
  448. + Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId;
  449. + else
  450. + return make_error<StringError>("Section number out of range",
  451. + object_error::parse_failed);
  452. + // For section definitions, check if it is comdat associative, and if
  453. + // it is, find the target section unique id.
  454. + const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
  455. + if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
  456. + int32_t Index = SD->getNumber(IsBigObj);
  457. + if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
  458. + return make_error<StringError>("Unexpected associative section index",
  459. + object_error::parse_failed);
  460. + Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
  461. + }
  462. I += 1 + SymRef.getNumberOfAuxSymbols();
  463. }
  464. Obj.addSymbols(Symbols);
  465. @@ -116,7 +141,7 @@ Error COFFReader::setRelocTargets(Object &Obj) const {
  466. for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
  467. RawSymbolTable.push_back(nullptr);
  468. }
  469. - for (Section &Sec : Obj.Sections) {
  470. + for (Section &Sec : Obj.getMutableSections()) {
  471. for (Relocation &R : Sec.Relocs) {
  472. if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
  473. return make_error<StringError>("SymbolTableIndex out of range",
  474. diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  475. index c347810dd24..9fb7812672b 100644
  476. --- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  477. +++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  478. @@ -25,7 +25,7 @@ using namespace object;
  479. using namespace COFF;
  480. Error COFFWriter::finalizeRelocTargets() {
  481. - for (Section &Sec : Obj.Sections) {
  482. + for (Section &Sec : Obj.getMutableSections()) {
  483. for (Relocation &R : Sec.Relocs) {
  484. const Symbol *Sym = Obj.findSymbol(R.Target);
  485. if (Sym == nullptr)
  486. @@ -39,8 +39,48 @@ Error COFFWriter::finalizeRelocTargets() {
  487. return Error::success();
  488. }
  489. +Error COFFWriter::finalizeSectionNumbers() {
  490. + for (Symbol &Sym : Obj.getMutableSymbols()) {
  491. + if (Sym.TargetSectionId <= 0) {
  492. + // Undefined, or a special kind of symbol. These negative values
  493. + // are stored in the SectionNumber field which is unsigned.
  494. + Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId);
  495. + } else {
  496. + const Section *Sec = Obj.findSection(Sym.TargetSectionId);
  497. + if (Sec == nullptr)
  498. + return make_error<StringError>("Symbol " + Sym.Name +
  499. + " points to a removed section",
  500. + object_error::invalid_symbol_index);
  501. + Sym.Sym.SectionNumber = Sec->Index;
  502. +
  503. + if (Sym.Sym.NumberOfAuxSymbols == 1 &&
  504. + Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) {
  505. + coff_aux_section_definition *SD =
  506. + reinterpret_cast<coff_aux_section_definition *>(Sym.AuxData.data());
  507. + uint32_t SDSectionNumber;
  508. + if (Sym.AssociativeComdatTargetSectionId == 0) {
  509. + // Not a comdat associative section; just set the Number field to
  510. + // the number of the section itself.
  511. + SDSectionNumber = Sec->Index;
  512. + } else {
  513. + Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
  514. + if (Sec == nullptr)
  515. + return make_error<StringError>(
  516. + "Symbol " + Sym.Name + " is associative to a removed section",
  517. + object_error::invalid_symbol_index);
  518. + SDSectionNumber = Sec->Index;
  519. + }
  520. + // Update the section definition with the new section number.
  521. + SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber);
  522. + SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16);
  523. + }
  524. + }
  525. + }
  526. + return Error::success();
  527. +}
  528. +
  529. void COFFWriter::layoutSections() {
  530. - for (auto &S : Obj.Sections) {
  531. + for (auto &S : Obj.getMutableSections()) {
  532. if (S.Header.SizeOfRawData > 0)
  533. S.Header.PointerToRawData = FileSize;
  534. FileSize += S.Header.SizeOfRawData; // For executables, this is already
  535. @@ -57,7 +97,7 @@ void COFFWriter::layoutSections() {
  536. }
  537. size_t COFFWriter::finalizeStringTable() {
  538. - for (auto &S : Obj.Sections)
  539. + for (const auto &S : Obj.getSections())
  540. if (S.Name.size() > COFF::NameSize)
  541. StrTabBuilder.add(S.Name);
  542. @@ -67,7 +107,7 @@ size_t COFFWriter::finalizeStringTable() {
  543. StrTabBuilder.finalize();
  544. - for (auto &S : Obj.Sections) {
  545. + for (auto &S : Obj.getMutableSections()) {
  546. if (S.Name.size() > COFF::NameSize) {
  547. snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d",
  548. (int)StrTabBuilder.getOffset(S.Name));
  549. @@ -97,6 +137,8 @@ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
  550. Error COFFWriter::finalize(bool IsBigObj) {
  551. if (Error E = finalizeRelocTargets())
  552. return E;
  553. + if (Error E = finalizeSectionNumbers())
  554. + return E;
  555. size_t SizeOfHeaders = 0;
  556. FileAlignment = 1;
  557. @@ -113,10 +155,10 @@ Error COFFWriter::finalize(bool IsBigObj) {
  558. SizeOfHeaders +=
  559. PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size();
  560. }
  561. - Obj.CoffFileHeader.NumberOfSections = Obj.Sections.size();
  562. + Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size();
  563. SizeOfHeaders +=
  564. IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header);
  565. - SizeOfHeaders += sizeof(coff_section) * Obj.Sections.size();
  566. + SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size();
  567. SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment);
  568. Obj.CoffFileHeader.SizeOfOptionalHeader =
  569. @@ -131,8 +173,8 @@ Error COFFWriter::finalize(bool IsBigObj) {
  570. Obj.PeHeader.SizeOfHeaders = SizeOfHeaders;
  571. Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData;
  572. - if (!Obj.Sections.empty()) {
  573. - const Section &S = Obj.Sections.back();
  574. + if (!Obj.getSections().empty()) {
  575. + const Section &S = Obj.getSections().back();
  576. Obj.PeHeader.SizeOfImage =
  577. alignTo(S.Header.VirtualAddress + S.Header.VirtualSize,
  578. Obj.PeHeader.SectionAlignment);
  579. @@ -198,7 +240,7 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
  580. BigObjHeader.unused4 = 0;
  581. // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus
  582. // get the original one instead.
  583. - BigObjHeader.NumberOfSections = Obj.Sections.size();
  584. + BigObjHeader.NumberOfSections = Obj.getSections().size();
  585. BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable;
  586. BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols;
  587. @@ -223,14 +265,14 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
  588. Ptr += sizeof(DD);
  589. }
  590. }
  591. - for (const auto &S : Obj.Sections) {
  592. + for (const auto &S : Obj.getSections()) {
  593. memcpy(Ptr, &S.Header, sizeof(S.Header));
  594. Ptr += sizeof(S.Header);
  595. }
  596. }
  597. void COFFWriter::writeSections() {
  598. - for (const auto &S : Obj.Sections) {
  599. + for (const auto &S : Obj.getSections()) {
  600. uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData;
  601. std::copy(S.Contents.begin(), S.Contents.end(), Ptr);
  602. @@ -295,7 +337,7 @@ Error COFFWriter::patchDebugDirectory() {
  603. const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY];
  604. if (Dir->Size <= 0)
  605. return Error::success();
  606. - for (const auto &S : Obj.Sections) {
  607. + for (const auto &S : Obj.getSections()) {
  608. if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress &&
  609. Dir->RelativeVirtualAddress <
  610. S.Header.VirtualAddress + S.Header.SizeOfRawData) {
  611. @@ -324,7 +366,7 @@ Error COFFWriter::patchDebugDirectory() {
  612. }
  613. Error COFFWriter::write() {
  614. - bool IsBigObj = Obj.Sections.size() > MaxNumberOfSections16;
  615. + bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16;
  616. if (IsBigObj && Obj.IsPE)
  617. return make_error<StringError>("Too many sections for executable",
  618. object_error::parse_failed);
  619. diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h
  620. index 52fef385926..a967a103df9 100644
  621. --- a/llvm/tools/llvm-objcopy/COFF/Writer.h
  622. +++ b/llvm/tools/llvm-objcopy/COFF/Writer.h
  623. @@ -31,6 +31,7 @@ class COFFWriter {
  624. StringTableBuilder StrTabBuilder;
  625. Error finalizeRelocTargets();
  626. + Error finalizeSectionNumbers();
  627. void layoutSections();
  628. size_t finalizeStringTable();
  629. template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
  630. --
  631. 2.17.1