lp_bld_debug.cpp revision 3469715a8a171512cf9b528702e70393f01c6041
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 */ 73extern "C" boolean 74lp_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 81class raw_debug_ostream : 82 public llvm::raw_ostream 83{ 84 uint64_t pos; 85 86 void write_impl(const char *Ptr, size_t Size); 87 88#if HAVE_LLVM >= 0x207 89 uint64_t current_pos() const { return pos; } 90 size_t preferred_buffer_size() const { return 512; } 91#else 92 uint64_t current_pos() { return pos; } 93 size_t preferred_buffer_size() { return 512; } 94#endif 95}; 96 97 98void 99raw_debug_ostream::write_impl(const char *Ptr, size_t Size) 100{ 101 if (Size > 0) { 102 char *lastPtr = (char *)&Ptr[Size]; 103 char last = *lastPtr; 104 *lastPtr = 0; 105 _debug_printf("%*s", Size, Ptr); 106 *lastPtr = last; 107 pos += Size; 108 } 109} 110 111 112/** 113 * Same as LLVMDumpValue, but through our debugging channels. 114 */ 115extern "C" void 116lp_debug_dump_value(LLVMValueRef value) 117{ 118#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED) 119 raw_debug_ostream os; 120 llvm::unwrap(value)->print(os); 121 os.flush(); 122#else 123 LLVMDumpValue(value); 124#endif 125} 126 127 128#if HAVE_LLVM >= 0x0207 129/* 130 * MemoryObject wrapper around a buffer of memory, to be used by MC 131 * disassembler. 132 */ 133class BufferMemoryObject: 134 public llvm::MemoryObject 135{ 136private: 137 const uint8_t *Bytes; 138 uint64_t Length; 139public: 140 BufferMemoryObject(const uint8_t *bytes, uint64_t length) : 141 Bytes(bytes), Length(length) 142 { 143 } 144 145 uint64_t getBase() const 146 { 147 return 0; 148 } 149 150 uint64_t getExtent() const 151 { 152 return Length; 153 } 154 155 int readByte(uint64_t addr, uint8_t *byte) const 156 { 157 if (addr > getExtent()) 158 return -1; 159 *byte = Bytes[addr]; 160 return 0; 161 } 162}; 163#endif /* HAVE_LLVM >= 0x0207 */ 164 165 166/* 167 * Disassemble a function, using the LLVM MC disassembler. 168 * 169 * See also: 170 * - http://blog.llvm.org/2010/01/x86-disassembler.html 171 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html 172 */ 173extern "C" void 174lp_disassemble(const void* func) 175{ 176#if HAVE_LLVM >= 0x0207 177 using namespace llvm; 178 179 const uint8_t *bytes = (const uint8_t *)func; 180 181 /* 182 * Limit disassembly to this extent 183 */ 184 const uint64_t extent = 96 * 1024; 185 186 uint64_t max_pc = 0; 187 188 /* 189 * Initialize all used objects. 190 */ 191 192#if HAVE_LLVM >= 0x0301 193 std::string Triple = sys::getDefaultTargetTriple(); 194#else 195 std::string Triple = sys::getHostTriple(); 196#endif 197 198 std::string Error; 199 const Target *T = TargetRegistry::lookupTarget(Triple, Error); 200 201#if HAVE_LLVM >= 0x0300 202 OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple)); 203#else 204 OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple)); 205#endif 206 207 if (!AsmInfo) { 208 debug_printf("error: no assembly info for target %s\n", Triple.c_str()); 209 return; 210 } 211 212#if HAVE_LLVM >= 0x0300 213 const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""); 214 OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI)); 215#else 216 OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler()); 217#endif 218 if (!DisAsm) { 219 debug_printf("error: no disassembler for target %s\n", Triple.c_str()); 220 return; 221 } 222 223 raw_debug_ostream Out; 224 225#if HAVE_LLVM >= 0x0300 226 unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 227#else 228 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 229#endif 230 231#if HAVE_LLVM >= 0x0301 232 OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); 233 if (!MRI) { 234 debug_printf("error: no register info for target %s\n", Triple.c_str()); 235 return; 236 } 237 238 OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo()); 239 if (!MII) { 240 debug_printf("error: no instruction info for target %s\n", Triple.c_str()); 241 return; 242 } 243#endif 244 245#if HAVE_LLVM >= 0x0301 246 OwningPtr<MCInstPrinter> Printer( 247 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); 248#elif HAVE_LLVM == 0x0300 249 OwningPtr<MCInstPrinter> Printer( 250 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI)); 251#elif HAVE_LLVM >= 0x0208 252 OwningPtr<MCInstPrinter> Printer( 253 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo)); 254#else 255 OwningPtr<MCInstPrinter> Printer( 256 T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out)); 257#endif 258 if (!Printer) { 259 debug_printf("error: no instruction printer for target %s\n", Triple.c_str()); 260 return; 261 } 262 263#if HAVE_LLVM >= 0x0301 264 TargetOptions options; 265#if defined(DEBUG) 266 options.JITEmitDebugInfo = true; 267#endif 268#if defined(PIPE_ARCH_X86) 269 options.StackAlignmentOverride = 4; 270#endif 271#if defined(DEBUG) || defined(PROFILE) 272 options.NoFramePointerElim = true; 273#endif 274 TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options); 275#elif HAVE_LLVM == 0x0300 276 TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), ""); 277#else 278 TargetMachine *TM = T->createTargetMachine(Triple, ""); 279#endif 280 281 const TargetInstrInfo *TII = TM->getInstrInfo(); 282 283 /* 284 * Wrap the data in a MemoryObject 285 */ 286 BufferMemoryObject memoryObject((const uint8_t *)bytes, extent); 287 288 uint64_t pc; 289 pc = 0; 290 while (true) { 291 MCInst Inst; 292 uint64_t Size; 293 294 /* 295 * Print address. We use addresses relative to the start of the function, 296 * so that between runs. 297 */ 298 299 debug_printf("%6lu:\t", (unsigned long)pc); 300 301 if (!DisAsm->getInstruction(Inst, Size, memoryObject, 302 pc, 303#if HAVE_LLVM >= 0x0300 304 nulls(), nulls())) { 305#else 306 nulls())) { 307#endif 308 debug_printf("invalid\n"); 309 pc += 1; 310 } 311 312 /* 313 * Output the bytes in hexidecimal format. 314 */ 315 316 if (0) { 317 unsigned i; 318 for (i = 0; i < Size; ++i) { 319 debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]); 320 } 321 for (; i < 16; ++i) { 322 debug_printf(" "); 323 } 324 } 325 326 /* 327 * Print the instruction. 328 */ 329 330#if HAVE_LLVM >= 0x0300 331 Printer->printInst(&Inst, Out, ""); 332#elif HAVE_LLVM >= 0x208 333 Printer->printInst(&Inst, Out); 334#else 335 Printer->printInst(&Inst); 336#endif 337 Out.flush(); 338 339 /* 340 * Advance. 341 */ 342 343 pc += Size; 344 345#if HAVE_LLVM >= 0x0300 346 const MCInstrDesc &TID = TII->get(Inst.getOpcode()); 347#else 348 const TargetInstrDesc &TID = TII->get(Inst.getOpcode()); 349#endif 350 351 /* 352 * Keep track of forward jumps to a nearby address. 353 */ 354 355 if (TID.isBranch()) { 356 for (unsigned i = 0; i < Inst.getNumOperands(); ++i) { 357 const MCOperand &operand = Inst.getOperand(i); 358 if (operand.isImm()) { 359 uint64_t jump; 360 361 /* 362 * FIXME: Handle both relative and absolute addresses correctly. 363 * EDInstInfo actually has this info, but operandTypes and 364 * operandFlags enums are not exposed in the public interface. 365 */ 366 367 if (1) { 368 /* 369 * PC relative addr. 370 */ 371 372 jump = pc + operand.getImm(); 373 } else { 374 /* 375 * Absolute addr. 376 */ 377 378 jump = (uint64_t)operand.getImm(); 379 } 380 381 /* 382 * Output the address relative to the function start, given 383 * that MC will print the addresses relative the current pc. 384 */ 385 debug_printf("\t\t; %lu", (unsigned long)jump); 386 387 /* 388 * Ignore far jumps given it could be actually a tail return to 389 * a random address. 390 */ 391 392 if (jump > max_pc && 393 jump < extent) { 394 max_pc = jump; 395 } 396 } 397 } 398 } 399 400 debug_printf("\n"); 401 402 /* 403 * Stop disassembling on return statements, if there is no record of a 404 * jump to a successive address. 405 */ 406 407 if (TID.isReturn()) { 408 if (pc > max_pc) { 409 break; 410 } 411 } 412 } 413 414 /* 415 * Print GDB command, useful to verify output. 416 */ 417 418 if (0) { 419 debug_printf("disassemble %p %p\n", bytes, bytes + pc); 420 } 421 422 debug_printf("\n"); 423#else /* HAVE_LLVM < 0x0207 */ 424 (void)func; 425#endif /* HAVE_LLVM < 0x0207 */ 426} 427 428