1 /*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
4 for INTEL64(R), AMD64(R)
6 Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY Koine Yuusuke(koinec) ``AS IS'' AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL Koine Yuusuke(koinec) OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 OF THE POSSIBILITY OF SUCH DAMAGE.
29 DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
31 /* File Info -----------------------------------------------------------
35 ----------------------------------------------------------------------*/
37 #define DRD64_SRC_LIBGOBLIN_DWARF_ABBREV
38 #include"drd64_libgoblin.h"
41 /*----------------------------------------------------------------------
42 ----------------------------------------------------------------------*/
44 LibGoblin_DwarfLine_Read_LineHeader_FileNameData(
45 LibGoblin_Dwarf_LineSection *pt_line,
55 pt_line->t_filename[ i_files ].pstr_srcfilename
56 = (char *)(pb_data - 1);
57 while( ( 0 < *pqw_remain) && ('\0' != b_byte) ) {
62 /* Read Directory Index */
63 pb_data = DWARF_Common_DecodeULEB128(
64 &qw_qword, pb_data, pqw_remain );
65 if( NULL == pb_data ) { return NULL; }
66 pt_line->t_filename[ i_files ].dw_dirindex = (DWord)qw_qword;
69 pb_data = DWARF_Common_DecodeULEB128(
70 &qw_qword, pb_data, pqw_remain );
71 if( NULL == pb_data ) { return NULL; }
72 pt_line->t_filename[ i_files ].qw_date = qw_qword;
75 pb_data = DWARF_Common_DecodeULEB128(
76 &qw_qword, pb_data, pqw_remain );
77 if( NULL == pb_data ) { return NULL; }
78 pt_line->t_filename[ i_files ].qw_filesize = qw_qword;
84 /*----------------------------------------------------------------------
85 ----------------------------------------------------------------------*/
87 LibGoblin_DwarfLine_Read_LineHeader_FileNames(
88 LibGoblin_Dwarf_LineSection *pt_line,
98 if( 1 > (*pqw_remain)-- ) { return NULL; }
101 while( '\0' != b_byte) {
102 pb_data = LibGoblin_DwarfLine_Read_LineHeader_FileNameData(
103 pt_line, pb_data, pqw_remain, i_files );
106 /* pt_line->t_filename[ i_files ].pstr_srcfilename
107 = (char *)(pb_data - 1);
108 while( ( 0 < *pqw_remain) && ('\0' != b_byte) ) {
113 /* Read Directory Index */
114 /*pb_data = DWARF_Common_DecodeULEB128(
115 &qw_qword, pb_data, pqw_remain );
116 if( NULL == pb_data ) { return NULL; }
117 pt_line->t_filename[ i_files ].dw_dirindex = (DWord)qw_qword;
120 /*pb_data = DWARF_Common_DecodeULEB128(
121 &qw_qword, pb_data, pqw_remain );
122 if( NULL == pb_data ) { return NULL; }
123 pt_line->t_filename[ i_files ].qw_date = qw_qword;
126 /*pb_data = DWARF_Common_DecodeULEB128(
127 &qw_qword, pb_data, pqw_remain );
128 if( NULL == pb_data ) { return NULL; }
129 pt_line->t_filename[ i_files ].qw_filesize = qw_qword;
131 if( 1 > (*pqw_remain)-- ) { return NULL; }
137 pt_line->i_num_filename = i_files;
143 /*----------------------------------------------------------------------
144 ----------------------------------------------------------------------*/
146 LibGoblin_DwarfLine_Read_LineHeader_IncludePath(
147 LibGoblin_Dwarf_LineSection *pt_line,
156 if( 1 > (*qw_remain)-- ) { return NULL; }
157 pt_line->pstr_includepath = (char *)pb_data;
160 while( '\0' != b_byte ) {
161 if( 1 > (*qw_remain)-- ) { return NULL; }
164 if( '\0' == b_byte ) {
165 if( 1 > (*qw_remain)-- ) { return NULL; }
170 pt_line->i_num_includepath = i_cnt;
176 /*----------------------------------------------------------------------
177 ----------------------------------------------------------------------*/
179 LibGoblin_DwarfLine_Read_LineHeader(
180 LibGoblin_Dwarf_LineSection *pt_line,
182 QWord *pqw_size_linesec )
192 assert( NULL != pt_line );
193 assert( NULL != pb_data );
198 pt_line->b_bits = 32;
199 qw_remain = *pqw_size_linesec;
202 /* Read unit_length (4Byte(32bit) or 8Byte(64bit)) */
203 pb_data = DWARF_Common_Read_DWord(
204 &dw_dword, pb_data, &qw_remain );
205 if( NULL == pb_data ) { return NULL; }
207 if( ((DWord)0xffffffff) == dw_dword ) {
208 pb_data = DWARF_Common_Read_QWord(
209 &qw_qword, pb_data, &qw_remain );
210 if( NULL == pb_data ) { return NULL; }
213 pt_line->b_bits = 64;
214 qw_remain = qw_qword;
217 qw_remain = (QWord)dw_dword;
220 /* Read version (2Byte) */
221 pb_data = DWARF_Common_Read_Word(
222 &(pt_line->w_version), pb_data, &qw_remain );
223 if( NULL == pb_data ) { return NULL; }
226 /* Read Header Length (4Byte(32bit), 8Byte(64bit)) */
227 if( 64 == i_bitflag ) {
228 pb_data = DWARF_Common_Read_QWord(
229 &qw_qword, pb_data, &qw_remain );
230 if( NULL == pb_data ) { return NULL; }
233 pt_line->qw_headerlength = qw_qword;
236 pb_data = DWARF_Common_Read_DWord(
237 &dw_dword, pb_data, &qw_remain );
238 if( NULL == pb_data ) { return NULL; }
241 pt_line->qw_headerlength = (QWord)dw_dword;
244 /* Read minimum Instruction Length (1Byte) */
245 pb_data = DWARF_Common_Read_Byte(
246 &(pt_line->b_minimum_inst_length), pb_data, &qw_remain );
247 if( NULL == pb_data ) { return NULL; }
250 /* Read default isStatement (1Byte) */
251 pb_data = DWARF_Common_Read_Byte(
252 &(pt_line->b_default_is_stmt), pb_data, &qw_remain );
253 if( NULL == pb_data ) { return NULL; }
256 /* Read LineBase (1Byte) */
257 pb_data = DWARF_Common_Read_Byte(
258 &b_byte, pb_data, &qw_remain );
259 if( NULL == pb_data ) { return NULL; }
261 pt_line->i_line_base = (INT)((char)b_byte);
263 /* Read LineRange (1Byte) */
264 pb_data = DWARF_Common_Read_Byte(
265 &b_byte, pb_data, &qw_remain );
266 if( NULL == pb_data ) { return NULL; }
268 pt_line->i_line_range = (INT)((DWord)b_byte);
270 /* Read Opcode Base (1Byte) */
271 pb_data = DWARF_Common_Read_Byte(
272 &(pt_line->b_opcode_base), pb_data, &qw_remain );
273 if( NULL == pb_data ) { return NULL; }
276 /* Read Operand length of the Standard Opecode */
277 for( i_cnt = 1; i_cnt < (pt_line->b_opcode_base); i_cnt++) {
278 pb_data = DWARF_Common_DecodeULEB128(
279 &qw_qword, pb_data, &qw_remain );
280 pt_line->dw_stdoperand_length[i_cnt] = (int)((DWord)qw_qword);
283 /* Read Include File-Path */
284 pb_data = LibGoblin_DwarfLine_Read_LineHeader_IncludePath(
285 pt_line, pb_data, &qw_remain );
286 if( NULL == pb_data ) { return NULL; }
289 pb_data = LibGoblin_DwarfLine_Read_LineHeader_FileNames(
290 pt_line, pb_data, &qw_remain );
291 if( NULL == pb_data ) { return NULL; }
294 printf(" version: %d \n", pt_line->w_version );
295 printf(" header length: %ld\n", pt_line->qw_headerlength );
296 printf(" min. Inst. length: %d\n", pt_line->b_minimum_inst_length );
297 printf(" default isStmt: %x\n", pt_line->b_default_is_stmt );
298 printf(" line_base: %d\n", pt_line->i_line_base );
299 printf(" line_range: %d\n", pt_line->i_line_range );
300 printf(" opcode_base: %d\n", pt_line->b_opcode_base );
301 for( i_cnt = 0; i_cnt < pt_line->b_opcode_base; i_cnt++ ) {
302 printf(" Std.Operand(%x) : %d \n", i_cnt,
303 pt_line->dw_stdoperand_length[i_cnt] );
305 printf(" include path nums: %d\n", pt_line->i_num_includepath );
306 printf(" include file nums: %d\n", pt_line->i_num_filename );
307 for( i_cnt = 0; i_cnt < pt_line->i_num_filename; i_cnt++ ) {
308 printf(" SrcFile[%d] filename: %s Dir.Index: %d Date: %ld Size: %ld \n",
310 pt_line->t_filename[i_cnt].pstr_srcfilename,
311 pt_line->t_filename[i_cnt].dw_dirindex,
312 pt_line->t_filename[i_cnt].qw_date,
313 pt_line->t_filename[i_cnt].qw_date );
316 //*pqw_size_linesec = qw_remain;
322 /*----------------------------------------------------------------------
323 ----------------------------------------------------------------------*/
325 LibGoblin_DwarfLine_CalcAddress(
327 LibGoblin_Dwarf_LineSection *pt_line )
331 assert( NULL != pt_line );
333 qw_value = ((INT)(b_opcode - pt_line->b_opcode_base)
334 / pt_line->i_line_range)
335 * (INT)pt_line->b_minimum_inst_length;
341 /*----------------------------------------------------------------------
342 ----------------------------------------------------------------------*/
344 LibGoblin_DwarfLine_CalcLine(
346 LibGoblin_Dwarf_LineSection *pt_line )
350 assert( NULL != pt_line );
352 ii_value = (Int64)(((INT)(b_opcode - pt_line->b_opcode_base)
353 % pt_line->i_line_range) + pt_line->i_line_base);
359 /*----------------------------------------------------------------------
360 ----------------------------------------------------------------------*/
362 LibGoblin_DwarfLine_DebugPrint_Register(
363 LibGoblin_Dwarf_Line_Register *pt_reg )
365 if( NULL == pt_reg ) {
366 puts(" Error: DebugRegister is NULL ");
370 printf(" [Line] File:%3d, PC:%08lx, Line:%5ld, Col:%2ld, ISA:%2ld, Option: %s%s%s%s\n",
371 pt_reg->dw_file, pt_reg->qw_address, pt_reg->qw_line,
372 pt_reg->qw_column,pt_reg->qw_isa,
373 ((pt_reg->b_is_stmt != 0x00 ) ? "Stmt : " : "" ),
374 ((pt_reg->b_basic_block != 0x00 ) ? "BasicBlk : " : "" ),
375 ((pt_reg->b_prologue_end != 0x00 ) ? "PrologueEnd : " : "" ),
376 ((pt_reg->b_epilogue_begin != 0x00 ) ? "EpilogueBegin" : "" ));
382 /*----------------------------------------------------------------------
383 ----------------------------------------------------------------------*/
385 LibGoblin_DwarfLine_InitRegister(
386 LibGoblin_Dwarf_Line_Register *pt_reg,
387 LibGoblin_Dwarf_LineSection *pt_line )
389 assert( NULL != pt_reg );
390 assert( NULL != pt_line );
392 pt_reg->qw_address = 0x0000000000000000;
396 = (pt_line->b_default_is_stmt == 0x00 ? 0x00 : 0x01 );
397 pt_reg->b_basic_block = 0x00;
398 pt_reg->b_prologue_end = 0x00;
399 pt_reg->b_epilogue_begin = 0x00;
400 pt_reg->qw_column = 0;
407 /*----------------------------------------------------------------------
408 ----------------------------------------------------------------------*/
410 LibGoblin_DwarfLine_Read_LineData(
411 LibGoblin_Dwarf_LineSection *pt_line,
420 LibGoblin_Dwarf_Line_Register t_reg;
422 assert( NULL != pt_line );
423 assert( NULL != pb_data );
425 LibGoblin_DwarfLine_InitRegister( &t_reg, pt_line );
429 pb_data = DWARF_Common_Read_Byte(
430 &b_opcode, pb_data, pqw_remain );
431 if( NULL == pb_data ) { return NULL; }
433 /* Read & Proc. by Opcode */
434 if( 0x00 == b_opcode ) {
435 /* Extended Opcode */
436 pb_data = DWARF_Common_DecodeULEB128(
437 &qw_qword, pb_data, pqw_remain );
438 pb_temp = pb_data + qw_qword;
440 /* XXX: unsupport user-more_than_2byte_opcode */
441 pb_data = DWARF_Common_Read_Byte(
442 &b_opcode, pb_data, pqw_remain );
443 if( NULL == pb_data ) { return NULL; }
445 /* dispatch for Extendee Opcode */
446 if( DW_LNE_end_sequence == b_opcode ) {
448 puts(" DW_LNE_end_sequence <NoOperand>");
451 else if( DW_LNE_set_address == b_opcode ) {
452 /* Operand: 4Byte(32bit) or 8Byte(64bit) */
453 pb_data = DWARF_Common_Read_QWord(
454 &qw_qword, pb_data, pqw_remain );
455 t_reg.qw_address = qw_qword;
456 /*if( 64 == pt_line->b_bits ) {
457 pb_data = DWARF_Common_Read_QWord(
458 &qw_qword, pb_data, pqw_remain );
459 t_reg.qw_address = qw_qword;
462 pb_data = DWARF_Common_Read_DWord(
463 &dw_value, pb_data, pqw_remain );
464 t_reg.qw_address = (QWord)dw_value;
466 printf(" DW_LNE_set_address %08lx\n", t_reg.qw_address );
468 else if( DW_LNE_define_file == b_opcode ) {
469 /* Operand: Filename Data Struct(Line Header) */
470 pb_data = LibGoblin_DwarfLine_Read_LineHeader_FileNameData(
471 pt_line, pb_data, pqw_remain,
472 pt_line->i_num_filename );
473 pt_line->i_num_filename++;
474 printf(" DW_LNE_define_file \n");
481 else if( pt_line->b_opcode_base > b_opcode ) {
482 /* Standard Opcode */
484 case DW_LNS_copy: /* 0x01 */
486 t_reg.b_basic_block = 0x00;
487 t_reg.b_prologue_end = 0x00;
488 t_reg.b_epilogue_begin = 0x00;
489 puts(" DW_LNS_copy <NoOperand>");
492 case DW_LNS_advance_pc: /* 0x02 */
493 /* Operand: uLEB128 */
494 pb_data = DWARF_Common_DecodeULEB128(
495 &qw_qword, pb_data, pqw_remain );
497 += pt_line->b_minimum_inst_length * qw_qword;
498 printf(" DW_LNS_advance_pc %08lx\n", qw_qword);
502 case DW_LNS_advance_line: /* 0x03 */
503 /* Operand: sLEB128 */
504 pb_data = DWARF_Common_DecodeLEB128(
505 &ii_value, pb_data, pqw_remain );
507 = (QWord)((Int64)(t_reg.qw_line) + ii_value);
508 printf(" DW_LNS_advance_line %8ld\n", ii_value);
511 case DW_LNS_set_file: /* 0x04 */
512 /* Operand: uLEB128 */
513 pb_data = DWARF_Common_DecodeULEB128(
514 &qw_qword, pb_data, pqw_remain );
515 t_reg.dw_file = (DWord)qw_qword;
516 printf(" DW_LNS_set_file %ld\n", qw_qword);
519 case DW_LNS_set_column: /* 0x05 */
520 /* Operand: uLEB128 */
521 pb_data = DWARF_Common_DecodeULEB128(
522 &qw_qword, pb_data, pqw_remain );
523 t_reg.qw_column = qw_qword;
524 printf(" DW_LNS_set_column %ld\n", qw_qword);
527 case DW_LNS_negate_stmt: /* 0x06 */
530 = ((t_reg.b_is_stmt == 0x00) ? 0x01 : 0x00 );
531 puts(" DW_LNS_negate_stmt");
534 case DW_LNS_set_basic_block: /* 0x07 */
536 t_reg.b_basic_block = 0x01;
537 puts(" DW_LNS_set_basic_block");
540 case DW_LNS_const_add_pc: /* 0x08 */
542 = LibGoblin_DwarfLine_CalcAddress( 0xff, pt_line);
543 t_reg.qw_address += qw_qword;
544 printf(" DW_LNS_const_add_pc %08lx\n", qw_qword);
547 case DW_LNS_fixed_advance_pc: /* 0x09 */
548 /* Operand: uhalf(short) */
549 pb_data = DWARF_Common_Read_Word(
550 &w_value, pb_data, pqw_remain );
551 t_reg.qw_address += (QWord)w_value;
552 printf(" DW_LNS_fixed_advance_pc %08lx\n", (QWord)w_value);
555 case DW_LNS_set_prologue_end: /* 0x0a */
556 t_reg.b_prologue_end = 0x01;
557 puts(" DW_LNS_set_prologue_end");
560 case DW_LNS_set_epilogue_begin: /* 0x0b */
561 t_reg.b_epilogue_begin = 0x01;
562 puts(" DW_LNS_set_epilogue_begin");
565 case DW_LNS_set_isa: /* 0x0c */
566 /* Operand: uLEB128 */
567 pb_data = DWARF_Common_DecodeULEB128(
568 &qw_qword, pb_data, pqw_remain );
569 t_reg.qw_isa += qw_qword;
570 printf(" DW_LNS_set_isa %08lx\n", qw_qword);
579 qw_qword = LibGoblin_DwarfLine_CalcAddress( b_opcode, pt_line);
580 ii_value = LibGoblin_DwarfLine_CalcLine( b_opcode, pt_line);
582 t_reg.qw_address += (qw_qword * pt_line->b_minimum_inst_length);
583 t_reg.qw_line = (QWord)((Int64)t_reg.qw_line + ii_value);
585 t_reg.b_basic_block = 0x00;
586 t_reg.b_prologue_end = 0x00;
587 t_reg.b_epilogue_begin = 0x00;
591 LibGoblin_DwarfLine_DebugPrint_Register( &t_reg );
593 }while( 0 != *pqw_remain );
599 /*----------------------------------------------------------------------
600 ----------------------------------------------------------------------*/
602 LibGoblin_DwarfLine_ReadCompileUnit(
603 LibGoblin_Dwarf_SourceFile *p_src,
607 LibGoblin_Dwarf_LineSection *pt_line;
609 assert( NULL != p_src );
610 assert( NULL != pb_data );
612 pt_line = &(p_src->t_linesec);
614 /* Read & SetInfo LineHeader (in CU) */
615 pt_line->pb_header = pb_data;
616 pb_data = LibGoblin_DwarfLine_Read_LineHeader(
617 pt_line, pb_data, pqw_remain );
618 if( NULL == pb_data ) {
622 /* Read & Check LineData */
623 pb_data = LibGoblin_DwarfLine_Read_LineData(
624 pt_line, pb_data, pqw_remain );
632 /*----------------------------------------------------------------------
633 ----------------------------------------------------------------------*/
634 LIBGOBLIN_DWARF_LINE_EXTERN
636 LibGoblin_DwarfLine_Analyze(
637 LibGoblin_BinaryInfo *p_bin )
642 LibGoblin_Dwarf_SourceFile *p_src;
643 LibGoblin_Debug_Dwarf *p_dwarf;
645 assert( NULL != p_bin );
647 p_dwarf = (LibGoblin_Debug_Dwarf *)p_bin->p_debug;
648 assert( NULL != p_dwarf );
650 i_srcfiles = p_dwarf->i_srcfilenum;
652 p_src = p_dwarf->p_src;
653 assert( NULL != p_src );
655 /* Get .debug_abbrev section Info */
656 pb_data = ELF_GetSection(
658 LIBGOBLIN_SECTION_ID_DEBUG_LINE );
659 if( NULL == pb_data ) { return 0x01; }
662 p_src->t_linesec.pb_header = pb_data;
664 /* Analyze .debug_info compile unit */
665 pb_data = LibGoblin_DwarfLine_ReadCompileUnit(
666 p_src, pb_data, &qw_size );
667 if( NULL == pb_data) { return 0x02; }
672 }while((qw_size > 0) && (i_srcfiles > 0));
679 /* EOF of drd64_.c ----------------------------------- */