]>
Commit | Line | Data |
---|---|---|
d71449a3 DL |
1 | // This is free and unencumbered software released into the public domain. |
2 | // | |
3 | // Anyone is free to copy, modify, publish, use, compile, sell, or | |
4 | // distribute this software, either in source code form or as a compiled | |
5 | // binary, for any purpose, commercial or non-commercial, and by any | |
6 | // means. | |
7 | // | |
8 | // In jurisdictions that recognize copyright laws, the author or authors | |
9 | // of this software dedicate any and all copyright interest in the | |
10 | // software to the public domain. We make this dedication for the benefit | |
11 | // of the public at large and to the detriment of our heirs and | |
12 | // successors. We intend this dedication to be an overt act of | |
13 | // relinquishment in perpetuity of all present and future rights to this | |
14 | // software under copyright law. | |
15 | // | |
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
20 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
21 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
22 | // OTHER DEALINGS IN THE SOFTWARE. | |
23 | // | |
24 | // For more information, please refer to <http://unlicense.org/> | |
25 | ||
26 | #include <llvm-c/BitReader.h> | |
27 | #include <llvm-c/BitWriter.h> | |
28 | #include <llvm-c/Core.h> | |
29 | #include <llvm-c/DebugInfo.h> | |
30 | ||
31 | #include <llvm/IR/Module.h> | |
32 | #include <llvm/IR/Value.h> | |
33 | #include <llvm/IR/Type.h> | |
34 | #include <llvm/IR/DebugInfo.h> | |
35 | #include <llvm/IR/DebugInfoMetadata.h> | |
36 | #include <llvm/Support/raw_ostream.h> | |
37 | ||
38 | #include <map> | |
39 | ||
40 | #include "frr-llvm-debuginfo.h" | |
41 | ||
42 | /* llvm::DebugInfoFinder is unfortunately not exposed in the llvm-c API... */ | |
43 | ||
44 | struct dbginfo { | |
45 | llvm::DebugInfoFinder finder; | |
46 | std::map<std::string, llvm::DICompositeType *> tab; | |
47 | }; | |
48 | ||
49 | struct dbginfo *dbginfo_load(LLVMModuleRef _mod) | |
50 | { | |
51 | llvm::Module *mod = llvm::unwrap(_mod); | |
52 | struct dbginfo *info = new dbginfo(); | |
53 | ||
54 | info->finder.processModule(*mod); | |
55 | ||
56 | for (auto ty : info->finder.types()) { | |
57 | if (ty->getMetadataID() != llvm::Metadata::DICompositeTypeKind) | |
58 | continue; | |
59 | ||
60 | llvm::DICompositeType *cty = (llvm::DICompositeType *)ty; | |
61 | /* empty forward declarations aka "struct foobar;" */ | |
62 | if (cty->getElements().size() == 0) | |
63 | continue; | |
64 | ||
65 | info->tab.emplace(std::move(ty->getName().str()), cty); | |
66 | } | |
67 | ||
68 | return info; | |
69 | } | |
70 | ||
71 | bool dbginfo_struct_member(struct dbginfo *info, LLVMTypeRef _typ, | |
72 | unsigned long long idx, char **struct_name, | |
73 | char **member_name) | |
74 | { | |
75 | *struct_name = NULL; | |
76 | *member_name = NULL; | |
77 | ||
78 | llvm::Type *typ = llvm::unwrap(_typ); | |
79 | ||
80 | if (!typ->isStructTy()) | |
81 | return false; | |
82 | ||
83 | llvm::StructType *styp = (llvm::StructType *)typ; | |
84 | auto sname = styp->getStructName(); | |
85 | ||
86 | if (!sname.startswith("struct.")) | |
87 | return false; | |
88 | sname = sname.drop_front(7); | |
89 | ||
90 | size_t dot = sname.find_last_of("."); | |
91 | if (dot != sname.npos) | |
92 | sname = sname.take_front(dot); | |
93 | ||
94 | auto item = info->tab.find(sname.str()); | |
95 | if (item == info->tab.end()) | |
96 | return false; | |
97 | ||
98 | auto elements = item->second->getElements(); | |
99 | if (idx >= elements.size()) | |
100 | return false; | |
101 | ||
102 | auto elem = elements[idx]; | |
103 | ||
104 | if (elem->getMetadataID() != llvm::Metadata::DIDerivedTypeKind) | |
105 | return false; | |
106 | ||
107 | llvm::DIDerivedType *dtyp = (llvm::DIDerivedType *)elem; | |
108 | ||
109 | *struct_name = strdup(sname.str().c_str()); | |
110 | *member_name = strdup(dtyp->getName().str().c_str()); | |
111 | return true; | |
112 | } |