1 /************************************************************************** 2 * 3 * Copyright 2009-2011 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include <stddef.h> 29 30 #include <llvm-c/Core.h> 31 #include <llvm/Target/TargetMachine.h> 32 #include <llvm/Target/TargetInstrInfo.h> 33 #include <llvm/Support/raw_ostream.h> 34 #include <llvm/Support/MemoryObject.h> 35 36 #if HAVE_LLVM >= 0x0300 37 #include <llvm/Support/TargetRegistry.h> 38 #else /* HAVE_LLVM < 0x0300 */ 39 #include <llvm/Target/TargetRegistry.h> 40 #endif /* HAVE_LLVM < 0x0300 */ 41 42 #if HAVE_LLVM >= 0x0209 43 #include <llvm/Support/Host.h> 44 #else /* HAVE_LLVM < 0x0209 */ 45 #include <llvm/System/Host.h> 46 #endif /* HAVE_LLVM < 0x0209 */ 47 48 #if HAVE_LLVM >= 0x0207 49 #include <llvm/MC/MCDisassembler.h> 50 #include <llvm/MC/MCAsmInfo.h> 51 #include <llvm/MC/MCInst.h> 52 #include <llvm/MC/MCInstPrinter.h> 53 #endif /* HAVE_LLVM >= 0x0207 */ 54 #if HAVE_LLVM >= 0x0301 55 #include <llvm/MC/MCRegisterInfo.h> 56 #endif /* HAVE_LLVM >= 0x0301 */ 57 58 #include "util/u_math.h" 59 #include "util/u_debug.h" 60 61 #include "lp_bld_debug.h" 62 63 64 65 /** 66 * Check alignment. 67 * 68 * It is important that this check is not implemented as a macro or inlined 69 * function, as the compiler assumptions in respect to alignment of global 70 * and stack variables would often make the check a no op, defeating the 71 * whole purpose of the exercise. 72 */ 73 extern "C" boolean 74 lp_check_alignment(const void *ptr, unsigned alignment) 75 { 76 assert(util_is_power_of_two(alignment)); 77 return ((uintptr_t)ptr & (alignment - 1)) == 0; 78 } 79 80 81 class raw_debug_ostream : 82 public llvm::raw_ostream 83 { 84 private: 85 uint64_t pos; 86 87 public: 88 raw_debug_ostream() : pos(0) { } 89 90 void write_impl(const char *Ptr, size_t Size); 91 92 #if HAVE_LLVM >= 0x207 93 uint64_t current_pos() const { return pos; } 94 size_t preferred_buffer_size() const { return 512; } 95 #else 96 uint64_t current_pos() { return pos; } 97 size_t preferred_buffer_size() { return 512; } 98 #endif 99 }; 100 101 102 void 103 raw_debug_ostream::write_impl(const char *Ptr, size_t Size) 104 { 105 if (Size > 0) { 106 char *lastPtr = (char *)&Ptr[Size]; 107 char last = *lastPtr; 108 *lastPtr = 0; 109 _debug_printf("%*s", Size, Ptr); 110 *lastPtr = last; 111 pos += Size; 112 } 113 } 114 115 116 /** 117 * Same as LLVMDumpValue, but through our debugging channels. 118 */ 119 extern "C" void 120 lp_debug_dump_value(LLVMValueRef value) 121 { 122 #if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED) 123 raw_debug_ostream os; 124 llvm::unwrap(value)->print(os); 125 os.flush(); 126 #else 127 LLVMDumpValue(value); 128 #endif 129 } 130 131 132 #if HAVE_LLVM >= 0x0207 133 /* 134 * MemoryObject wrapper around a buffer of memory, to be used by MC 135 * disassembler. 136 */ 137 class BufferMemoryObject: 138 public llvm::MemoryObject 139 { 140 private: 141 const uint8_t *Bytes; 142 uint64_t Length; 143 public: 144 BufferMemoryObject(const uint8_t *bytes, uint64_t length) : 145 Bytes(bytes), Length(length) 146 { 147 } 148 149 uint64_t getBase() const 150 { 151 return 0; 152 } 153 154 uint64_t getExtent() const 155 { 156 return Length; 157 } 158 159 int readByte(uint64_t addr, uint8_t *byte) const 160 { 161 if (addr > getExtent()) 162 return -1; 163 *byte = Bytes[addr]; 164 return 0; 165 } 166 }; 167 #endif /* HAVE_LLVM >= 0x0207 */ 168 169 170 /* 171 * Disassemble a function, using the LLVM MC disassembler. 172 * 173 * See also: 174 * - http://blog.llvm.org/2010/01/x86-disassembler.html 175 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html 176 */ 177 extern "C" void 178 lp_disassemble(const void* func) 179 { 180 #if HAVE_LLVM >= 0x0207 181 using namespace llvm; 182 183 const uint8_t *bytes = (const uint8_t *)func; 184 185 /* 186 * Limit disassembly to this extent 187 */ 188 const uint64_t extent = 96 * 1024; 189 190 uint64_t max_pc = 0; 191 192 /* 193 * Initialize all used objects. 194 */ 195 196 #if HAVE_LLVM >= 0x0301 197 std::string Triple = sys::getDefaultTargetTriple(); 198 #else 199 std::string Triple = sys::getHostTriple(); 200 #endif 201 202 std::string Error; 203 const Target *T = TargetRegistry::lookupTarget(Triple, Error); 204 205 #if HAVE_LLVM >= 0x0300 206 OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple)); 207 #else 208 OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple)); 209 #endif 210 211 if (!AsmInfo) { 212 debug_printf("error: no assembly info for target %s\n", Triple.c_str()); 213 return; 214 } 215 216 #if HAVE_LLVM >= 0x0300 217 const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""); 218 OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI)); 219 #else 220 OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler()); 221 #endif 222 if (!DisAsm) { 223 debug_printf("error: no disassembler for target %s\n", Triple.c_str()); 224 return; 225 } 226 227 raw_debug_ostream Out; 228 229 #if HAVE_LLVM >= 0x0300 230 unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 231 #else 232 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 233 #endif 234 235 #if HAVE_LLVM >= 0x0301 236 OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); 237 if (!MRI) { 238 debug_printf("error: no register info for target %s\n", Triple.c_str()); 239 return; 240 } 241 242 OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo()); 243 if (!MII) { 244 debug_printf("error: no instruction info for target %s\n", Triple.c_str()); 245 return; 246 } 247 #endif 248 249 #if HAVE_LLVM >= 0x0301 250 OwningPtr<MCInstPrinter> Printer( 251 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); 252 #elif HAVE_LLVM == 0x0300 253 OwningPtr<MCInstPrinter> Printer( 254 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI)); 255 #elif HAVE_LLVM >= 0x0208 256 OwningPtr<MCInstPrinter> Printer( 257 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo)); 258 #else 259 OwningPtr<MCInstPrinter> Printer( 260 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out)); 261 #endif 262 if (!Printer) { 263 debug_printf("error: no instruction printer for target %s\n", Triple.c_str()); 264 return; 265 } 266 267 #if HAVE_LLVM >= 0x0301 268 TargetOptions options; 269 #if defined(DEBUG) 270 options.JITEmitDebugInfo = true; 271 #endif 272 #if defined(PIPE_ARCH_X86) 273 options.StackAlignmentOverride = 4; 274 #endif 275 #if defined(DEBUG) || defined(PROFILE) 276 options.NoFramePointerElim = true; 277 #endif 278 TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options); 279 #elif HAVE_LLVM == 0x0300 280 TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), ""); 281 #else 282 TargetMachine *TM = T->createTargetMachine(Triple, ""); 283 #endif 284 285 const TargetInstrInfo *TII = TM->getInstrInfo(); 286 287 /* 288 * Wrap the data in a MemoryObject 289 */ 290 BufferMemoryObject memoryObject((const uint8_t *)bytes, extent); 291 292 uint64_t pc; 293 pc = 0; 294 while (true) { 295 MCInst Inst; 296 uint64_t Size; 297 298 /* 299 * Print address. We use addresses relative to the start of the function, 300 * so that between runs. 301 */ 302 303 debug_printf("%6lu:\t", (unsigned long)pc); 304 305 if (!DisAsm->getInstruction(Inst, Size, memoryObject, 306 pc, 307 #if HAVE_LLVM >= 0x0300 308 nulls(), nulls())) { 309 #else 310 nulls())) { 311 #endif 312 debug_printf("invalid\n"); 313 pc += 1; 314 } 315 316 /* 317 * Output the bytes in hexidecimal format. 318 */ 319 320 if (0) { 321 unsigned i; 322 for (i = 0; i < Size; ++i) { 323 debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]); 324 } 325 for (; i < 16; ++i) { 326 debug_printf(" "); 327 } 328 } 329 330 /* 331 * Print the instruction. 332 */ 333 334 #if HAVE_LLVM >= 0x0300 335 Printer->printInst(&Inst, Out, ""); 336 #elif HAVE_LLVM >= 0x208 337 Printer->printInst(&Inst, Out); 338 #else 339 Printer->printInst(&Inst); 340 #endif 341 Out.flush(); 342 343 /* 344 * Advance. 345 */ 346 347 pc += Size; 348 349 #if HAVE_LLVM >= 0x0300 350 const MCInstrDesc &TID = TII->get(Inst.getOpcode()); 351 #else 352 const TargetInstrDesc &TID = TII->get(Inst.getOpcode()); 353 #endif 354 355 /* 356 * Keep track of forward jumps to a nearby address. 357 */ 358 359 if (TID.isBranch()) { 360 for (unsigned i = 0; i < Inst.getNumOperands(); ++i) { 361 const MCOperand &operand = Inst.getOperand(i); 362 if (operand.isImm()) { 363 uint64_t jump; 364 365 /* 366 * FIXME: Handle both relative and absolute addresses correctly. 367 * EDInstInfo actually has this info, but operandTypes and 368 * operandFlags enums are not exposed in the public interface. 369 */ 370 371 if (1) { 372 /* 373 * PC relative addr. 374 */ 375 376 jump = pc + operand.getImm(); 377 } else { 378 /* 379 * Absolute addr. 380 */ 381 382 jump = (uint64_t)operand.getImm(); 383 } 384 385 /* 386 * Output the address relative to the function start, given 387 * that MC will print the addresses relative the current pc. 388 */ 389 debug_printf("\t\t; %lu", (unsigned long)jump); 390 391 /* 392 * Ignore far jumps given it could be actually a tail return to 393 * a random address. 394 */ 395 396 if (jump > max_pc && 397 jump < extent) { 398 max_pc = jump; 399 } 400 } 401 } 402 } 403 404 debug_printf("\n"); 405 406 /* 407 * Stop disassembling on return statements, if there is no record of a 408 * jump to a successive address. 409 */ 410 411 if (TID.isReturn()) { 412 if (pc > max_pc) { 413 break; 414 } 415 } 416 } 417 418 /* 419 * Print GDB command, useful to verify output. 420 */ 421 422 if (0) { 423 debug_printf("disassemble %p %p\n", bytes, bytes + pc); 424 } 425 426 debug_printf("\n"); 427 #else /* HAVE_LLVM < 0x0207 */ 428 (void)func; 429 #endif /* HAVE_LLVM < 0x0207 */ 430 } 431 432