xref: /llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp (revision a6deaeec370ec5e34f9e5aa3fad3bc73770d4895)
1 //===---- llvm-jitlink-elf.cpp -- ELF parsing support for llvm-jitlink ----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ELF parsing support for llvm-jitlink.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm-jitlink.h"
14 
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/Path.h"
17 
18 #define DEBUG_TYPE "llvm_jitlink"
19 
20 using namespace llvm;
21 using namespace llvm::jitlink;
22 
23 namespace llvm {
24 
25 Error registerELFGraphInfo(Session &S, LinkGraph &G) {
26   auto FileName = sys::path::filename(G.getName());
27   if (S.FileInfos.count(FileName)) {
28     return make_error<StringError>("When -check is passed, file names must be "
29                                    "distinct (duplicate: \"" +
30                                        FileName + "\")",
31                                    inconvertibleErrorCode());
32   }
33 
34   auto &FileInfo = S.FileInfos[FileName];
35   LLVM_DEBUG({
36     dbgs() << "Registering ELF file info for \"" << FileName << "\"\n";
37   });
38   for (auto &Sec : G.sections()) {
39     LLVM_DEBUG({
40       dbgs() << "  Section \"" << Sec.getName() << "\": "
41              << (llvm::empty(Sec.symbols()) ? "empty. skipping."
42                                             : "processing...")
43              << "\n";
44     });
45 
46     // Skip empty sections.
47     if (llvm::empty(Sec.symbols()))
48       continue;
49 
50     if (FileInfo.SectionInfos.count(Sec.getName()))
51       return make_error<StringError>("Encountered duplicate section name \"" +
52                                          Sec.getName() + "\" in \"" + FileName +
53                                          "\"",
54                                      inconvertibleErrorCode());
55 
56     bool SectionContainsContent = false;
57     bool SectionContainsZeroFill = false;
58 
59     auto *FirstSym = *Sec.symbols().begin();
60     auto *LastSym = FirstSym;
61     for (auto *Sym : Sec.symbols()) {
62       if (Sym->getAddress() < FirstSym->getAddress())
63         FirstSym = Sym;
64       if (Sym->getAddress() > LastSym->getAddress())
65         LastSym = Sym;
66 
67       if (Sym->hasName()) {
68         dbgs() << "Symbol: " << Sym->getName() << "\n";
69         if (Sym->isSymbolZeroFill()) {
70           S.SymbolInfos[Sym->getName()] = {Sym->getSize(), Sym->getAddress()};
71           SectionContainsZeroFill = true;
72         } else {
73           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
74                                            Sym->getAddress()};
75           SectionContainsContent = true;
76         }
77       }
78     }
79 
80     JITTargetAddress SecAddr = FirstSym->getAddress();
81     uint64_t SecSize =
82         (LastSym->getBlock().getAddress() + LastSym->getBlock().getSize()) -
83         SecAddr;
84 
85     if (SectionContainsZeroFill && SectionContainsContent)
86       return make_error<StringError>("Mixed zero-fill and content sections not "
87                                      "supported yet",
88                                      inconvertibleErrorCode());
89     if (SectionContainsZeroFill)
90       FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr};
91     else
92       FileInfo.SectionInfos[Sec.getName()] = {
93           StringRef(FirstSym->getBlock().getContent().data(), SecSize),
94           SecAddr};
95   }
96 
97   return Error::success();
98 }
99 
100 } // end namespace llvm
101