Mercurial > hg > CbC > CbC_llvm
comparison lib/XRay/InstrumentationMap.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===- InstrumentationMap.cpp - XRay Instrumentation Map ------------------===// | 1 //===- InstrumentationMap.cpp - XRay Instrumentation Map ------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 // | 8 // |
10 // Implementation of the InstrumentationMap type for XRay sleds. | 9 // Implementation of the InstrumentationMap type for XRay sleds. |
11 // | 10 // |
12 //===----------------------------------------------------------------------===// | 11 //===----------------------------------------------------------------------===// |
13 | 12 |
14 #include "llvm/XRay/InstrumentationMap.h" | 13 #include "llvm/XRay/InstrumentationMap.h" |
14 #include "llvm/ADT/DenseMap.h" | |
15 #include "llvm/ADT/None.h" | 15 #include "llvm/ADT/None.h" |
16 #include "llvm/ADT/STLExtras.h" | 16 #include "llvm/ADT/STLExtras.h" |
17 #include "llvm/ADT/StringRef.h" | 17 #include "llvm/ADT/StringRef.h" |
18 #include "llvm/ADT/Triple.h" | 18 #include "llvm/ADT/Triple.h" |
19 #include "llvm/ADT/Twine.h" | 19 #include "llvm/ADT/Twine.h" |
20 #include "llvm/Object/Binary.h" | 20 #include "llvm/Object/Binary.h" |
21 #include "llvm/Object/ELFObjectFile.h" | |
21 #include "llvm/Object/ObjectFile.h" | 22 #include "llvm/Object/ObjectFile.h" |
22 #include "llvm/Support/DataExtractor.h" | 23 #include "llvm/Support/DataExtractor.h" |
23 #include "llvm/Support/Error.h" | 24 #include "llvm/Support/Error.h" |
24 #include "llvm/Support/FileSystem.h" | 25 #include "llvm/Support/FileSystem.h" |
25 #include "llvm/Support/YAMLTraits.h" | 26 #include "llvm/Support/YAMLTraits.h" |
44 if (I != FunctionAddresses.end()) | 45 if (I != FunctionAddresses.end()) |
45 return I->second; | 46 return I->second; |
46 return None; | 47 return None; |
47 } | 48 } |
48 | 49 |
50 using RelocMap = DenseMap<uint64_t, uint64_t>; | |
51 | |
49 static Error | 52 static Error |
50 loadELF64(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, | 53 loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, |
51 InstrumentationMap::SledContainer &Sleds, | 54 InstrumentationMap::SledContainer &Sleds, |
52 InstrumentationMap::FunctionAddressMap &FunctionAddresses, | 55 InstrumentationMap::FunctionAddressMap &FunctionAddresses, |
53 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) { | 56 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) { |
54 InstrumentationMap Map; | 57 InstrumentationMap Map; |
55 | 58 |
56 // Find the section named "xray_instr_map". | 59 // Find the section named "xray_instr_map". |
57 if (!ObjFile.getBinary()->isELF() || | 60 if ((!ObjFile.getBinary()->isELF() && !ObjFile.getBinary()->isMachO()) || |
58 !(ObjFile.getBinary()->getArch() == Triple::x86_64 || | 61 !(ObjFile.getBinary()->getArch() == Triple::x86_64 || |
59 ObjFile.getBinary()->getArch() == Triple::ppc64le)) | 62 ObjFile.getBinary()->getArch() == Triple::ppc64le)) |
60 return make_error<StringError>( | 63 return make_error<StringError>( |
61 "File format not supported (only does ELF little endian 64-bit).", | 64 "File format not supported (only does ELF and Mach-O little endian 64-bit).", |
62 std::make_error_code(std::errc::not_supported)); | 65 std::make_error_code(std::errc::not_supported)); |
63 | 66 |
64 StringRef Contents = ""; | 67 StringRef Contents = ""; |
65 const auto &Sections = ObjFile.getBinary()->sections(); | 68 const auto &Sections = ObjFile.getBinary()->sections(); |
66 auto I = llvm::find_if(Sections, [&](object::SectionRef Section) { | 69 auto I = llvm::find_if(Sections, [&](object::SectionRef Section) { |
73 if (I == Sections.end()) | 76 if (I == Sections.end()) |
74 return make_error<StringError>( | 77 return make_error<StringError>( |
75 "Failed to find XRay instrumentation map.", | 78 "Failed to find XRay instrumentation map.", |
76 std::make_error_code(std::errc::executable_format_error)); | 79 std::make_error_code(std::errc::executable_format_error)); |
77 | 80 |
78 if (I->getContents(Contents)) | 81 if (Expected<StringRef> E = I->getContents()) |
79 return errorCodeToError( | 82 Contents = *E; |
80 std::make_error_code(std::errc::executable_format_error)); | 83 else |
84 return E.takeError(); | |
85 | |
86 RelocMap Relocs; | |
87 if (ObjFile.getBinary()->isELF()) { | |
88 uint32_t RelativeRelocation = [](object::ObjectFile *ObjFile) { | |
89 if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(ObjFile)) | |
90 return ELFObj->getELFFile()->getRelativeRelocationType(); | |
91 else if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(ObjFile)) | |
92 return ELFObj->getELFFile()->getRelativeRelocationType(); | |
93 else if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(ObjFile)) | |
94 return ELFObj->getELFFile()->getRelativeRelocationType(); | |
95 else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(ObjFile)) | |
96 return ELFObj->getELFFile()->getRelativeRelocationType(); | |
97 else | |
98 return static_cast<uint32_t>(0); | |
99 }(ObjFile.getBinary()); | |
100 | |
101 for (const object::SectionRef &Section : Sections) { | |
102 for (const object::RelocationRef &Reloc : Section.relocations()) { | |
103 if (Reloc.getType() != RelativeRelocation) | |
104 continue; | |
105 if (auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend()) | |
106 Relocs.insert({Reloc.getOffset(), *AddendOrErr}); | |
107 } | |
108 } | |
109 } | |
81 | 110 |
82 // Copy the instrumentation map data into the Sleds data structure. | 111 // Copy the instrumentation map data into the Sleds data structure. |
83 auto C = Contents.bytes_begin(); | 112 auto C = Contents.bytes_begin(); |
84 static constexpr size_t ELF64SledEntrySize = 32; | 113 static constexpr size_t ELF64SledEntrySize = 32; |
85 | 114 |
86 if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0) | 115 if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0) |
87 return make_error<StringError>( | 116 return make_error<StringError>( |
88 Twine("Instrumentation map entries not evenly divisible by size of " | 117 Twine("Instrumentation map entries not evenly divisible by size of " |
89 "an XRay sled entry in ELF64."), | 118 "an XRay sled entry in ELF64."), |
90 std::make_error_code(std::errc::executable_format_error)); | 119 std::make_error_code(std::errc::executable_format_error)); |
120 | |
121 auto RelocateOrElse = [&](uint64_t Offset, uint64_t Address) { | |
122 if (!Address) { | |
123 uint64_t A = I->getAddress() + C - Contents.bytes_begin() + Offset; | |
124 RelocMap::const_iterator R = Relocs.find(A); | |
125 if (R != Relocs.end()) | |
126 return R->second; | |
127 } | |
128 return Address; | |
129 }; | |
91 | 130 |
92 int32_t FuncId = 1; | 131 int32_t FuncId = 1; |
93 uint64_t CurFn = 0; | 132 uint64_t CurFn = 0; |
94 for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) { | 133 for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) { |
95 DataExtractor Extractor( | 134 DataExtractor Extractor( |
96 StringRef(reinterpret_cast<const char *>(C), ELF64SledEntrySize), true, | 135 StringRef(reinterpret_cast<const char *>(C), ELF64SledEntrySize), true, |
97 8); | 136 8); |
98 Sleds.push_back({}); | 137 Sleds.push_back({}); |
99 auto &Entry = Sleds.back(); | 138 auto &Entry = Sleds.back(); |
100 uint32_t OffsetPtr = 0; | 139 uint64_t OffsetPtr = 0; |
101 Entry.Address = Extractor.getU64(&OffsetPtr); | 140 uint64_t AddrOff = OffsetPtr; |
102 Entry.Function = Extractor.getU64(&OffsetPtr); | 141 Entry.Address = RelocateOrElse(AddrOff, Extractor.getU64(&OffsetPtr)); |
142 uint64_t FuncOff = OffsetPtr; | |
143 Entry.Function = RelocateOrElse(FuncOff, Extractor.getU64(&OffsetPtr)); | |
103 auto Kind = Extractor.getU8(&OffsetPtr); | 144 auto Kind = Extractor.getU8(&OffsetPtr); |
104 static constexpr SledEntry::FunctionKinds Kinds[] = { | 145 static constexpr SledEntry::FunctionKinds Kinds[] = { |
105 SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT, | 146 SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT, |
106 SledEntry::FunctionKinds::TAIL, | 147 SledEntry::FunctionKinds::TAIL, |
107 SledEntry::FunctionKinds::LOG_ARGS_ENTER, | 148 SledEntry::FunctionKinds::LOG_ARGS_ENTER, |
129 } | 170 } |
130 return Error::success(); | 171 return Error::success(); |
131 } | 172 } |
132 | 173 |
133 static Error | 174 static Error |
134 loadYAML(int Fd, size_t FileSize, StringRef Filename, | 175 loadYAML(sys::fs::file_t Fd, size_t FileSize, StringRef Filename, |
135 InstrumentationMap::SledContainer &Sleds, | 176 InstrumentationMap::SledContainer &Sleds, |
136 InstrumentationMap::FunctionAddressMap &FunctionAddresses, | 177 InstrumentationMap::FunctionAddressMap &FunctionAddresses, |
137 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) { | 178 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) { |
138 std::error_code EC; | 179 std::error_code EC; |
139 sys::fs::mapped_file_region MappedFile( | 180 sys::fs::mapped_file_region MappedFile( |
140 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC); | 181 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC); |
182 sys::fs::closeFile(Fd); | |
141 if (EC) | 183 if (EC) |
142 return make_error<StringError>( | 184 return make_error<StringError>( |
143 Twine("Failed memory-mapping file '") + Filename + "'.", EC); | 185 Twine("Failed memory-mapping file '") + Filename + "'.", EC); |
144 | 186 |
145 std::vector<YAMLXRaySledEntry> YAMLSleds; | 187 std::vector<YAMLXRaySledEntry> YAMLSleds; |
171 InstrumentationMap Map; | 213 InstrumentationMap Map; |
172 auto ObjectFileOrError = object::ObjectFile::createObjectFile(Filename); | 214 auto ObjectFileOrError = object::ObjectFile::createObjectFile(Filename); |
173 if (!ObjectFileOrError) { | 215 if (!ObjectFileOrError) { |
174 auto E = ObjectFileOrError.takeError(); | 216 auto E = ObjectFileOrError.takeError(); |
175 // We try to load it as YAML if the ELF load didn't work. | 217 // We try to load it as YAML if the ELF load didn't work. |
176 int Fd; | 218 Expected<sys::fs::file_t> FdOrErr = sys::fs::openNativeFileForRead(Filename); |
177 if (sys::fs::openFileForRead(Filename, Fd)) | 219 if (!FdOrErr) { |
178 return std::move(E); | 220 // Report the ELF load error if YAML failed. |
221 consumeError(FdOrErr.takeError()); | |
222 return std::move(E); | |
223 } | |
179 | 224 |
180 uint64_t FileSize; | 225 uint64_t FileSize; |
181 if (sys::fs::file_size(Filename, FileSize)) | 226 if (sys::fs::file_size(Filename, FileSize)) |
182 return std::move(E); | 227 return std::move(E); |
183 | 228 |
186 return std::move(E); | 231 return std::move(E); |
187 | 232 |
188 // From this point on the errors will be only for the YAML parts, so we | 233 // From this point on the errors will be only for the YAML parts, so we |
189 // consume the errors at this point. | 234 // consume the errors at this point. |
190 consumeError(std::move(E)); | 235 consumeError(std::move(E)); |
191 if (auto E = loadYAML(Fd, FileSize, Filename, Map.Sleds, | 236 if (auto E = loadYAML(*FdOrErr, FileSize, Filename, Map.Sleds, |
192 Map.FunctionAddresses, Map.FunctionIds)) | 237 Map.FunctionAddresses, Map.FunctionIds)) |
193 return std::move(E); | 238 return std::move(E); |
194 } else if (auto E = loadELF64(Filename, *ObjectFileOrError, Map.Sleds, | 239 } else if (auto E = loadObj(Filename, *ObjectFileOrError, Map.Sleds, |
195 Map.FunctionAddresses, Map.FunctionIds)) { | 240 Map.FunctionAddresses, Map.FunctionIds)) { |
196 return std::move(E); | 241 return std::move(E); |
197 } | 242 } |
198 return Map; | 243 return Map; |
199 } | 244 } |