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