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