OSDN Git Service

(LibGoblin)
[drdeamon64/drdeamon64.git] / libgoblin / drd64_libgoblin_debug_objinfo.c
1 /*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
2
3                          D r . D e a m o n  6 4
4                         for INTEL64(R), AMD64(R)
5         
6    Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10
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.
16
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.
28
29 DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
30
31 /* File Info -----------------------------------------------------------
32 File: drd64_.c
33 Function: 
34 Comment: 
35 ----------------------------------------------------------------------*/
36
37 #define DRD64_SRC_LIBGOBLIN_DEBUG_OBJINFO
38 #include"drd64_libgoblin.h"
39
40 static char     gstr_type[256][9]       = {
41         "NULL",
42         "PROGRAM",
43         "MASTER",
44         "PROGHDR",
45         "SECTION",
46         "FUNCTION",
47         "OBJECT",
48         "COMMON",
49         "TLS",
50         "REL",
51         "", "", "", "", "", "",
52         "", "", "", "", "", "", "", "",
53         "", "", "", "", "", "", "", "",
54         "", "", "", "", "", "", "", "",
55         "", "", "", "", "", "", "", "",
56         "", "", "", "", "", "", "", "",
57
58         "", "", "", "", "", "", "", "",
59         "", "", "", "", "", "", "", "",
60         "", "", "", "", "", "", "", "",
61         "", "", "", "", "", "", "", "",
62         "", "", "", "", "", "", "", "",
63         "", "", "", "", "", "", "", "",
64         "", "", "", "", "", "", "", "",
65
66         "", "", "", "", "", "", "", "",
67         "", "", "", "", "", "", "", "",
68         "", "", "", "", "", "", "", "",
69         "", "", "", "", "", "", "", "",
70         "", "", "", "", "", "", "", "",
71         "", "", "", "", "", "", "", "",
72         "", "", "", "", "", "", "", "",
73
74         "", "", "", "", "", "", "", "",
75         "", "", "", "", "", "", "", "",
76         "", "", "", "", "", "", "", "",
77         "", "", "", "", "", "", "", "",
78         "", "", "", "", "", "", "", "",
79         "", "", "", "", "", "", "", "",
80         "", "", "", "", "", "", "", ""
81 };
82
83 /*====================================================================*/
84 /*--------------------------------------------------------------------*/
85 void
86         Debug_ObjectInfo_Print_SymbolCommon(
87                         LibGoblin_ObjectInfo    *p_obj,
88                         char    *pstr_space,
89                         Byte    b_level )
90 {
91         char    str_type[64];
92         char    str_binding[32];
93         char    str_visibility[32];
94         LibGoblin_BinaryInfo    *p_binfo_origin;
95
96         printf(" %s\t\t[OBJINFO] Addr.Link(%3d <-> %3d)  File{ Offset=%8p, Size=%8ld, BinFileID=%d }\n",
97                                 pstr_space, 
98                                 p_obj->addrlink.i_prev_id, p_obj->addrlink.i_next_id,
99                                 p_obj->file.pv_offset, p_obj->file.qw_size, p_obj->file.i_binfile );
100
101         // Symbol type - ELFNN_ST_TYPE - st_info
102         switch( p_obj->info.symbol.b_type )     {
103                 case STT_NOTYPE:        // 0 - Unspecified type.
104                         strcpy( str_type, "NoType" );
105                         break;
106                 case STT_OBJECT:        // 1 - Data object.
107                         strcpy( str_type, "Data Object" );
108                         break;
109                 case STT_FUNC:          // 2 - Function.
110                         strcpy( str_type, "Function" );
111                         break;
112                 case STT_SECTION:       // 3 - Section.
113                         strcpy( str_type, "Section" );
114                         break;
115                 case STT_FILE:          // 4 - Source file.
116                         strcpy( str_type, "Source File" );
117                         break;
118                 case STT_COMMON:        // 5 - Uninitialized common block.
119                         strcpy( str_type, "UnInit. CommonBlock" );
120                         break;
121                 case STT_TLS:           // 6 - TLS object.
122                         strcpy( str_type, "TLS Object" );
123                         break;
124                 case STT_NUM:
125                         strcpy( str_type, "Num" );
126                         break;
127                 case STT_GNU_IFUNC:
128                         strcpy( str_type, "GNU IFunc" );
129                         break;
130                 default:
131                         snprintf( str_type, 31, "(%02xh)", p_obj->info.symbol.b_type );
132                         break;
133         }
134
135         // Symbol Binding - ELFNN_ST_BIND - st_info
136         switch( p_obj->info.symbol.b_binding )  {
137                 case STB_LOCAL:                 // 0 - Local symbol
138                         strcpy( str_binding, "Local" );
139                         break;
140                 case STB_GLOBAL:                // 1 - Global symbol
141                         strcpy( str_binding, "Global" );
142                         break;
143                 case STB_WEAK:                  // 2 - like global - lower precedence
144                         strcpy( str_binding, "WEAK" );
145                         break;
146                 case STB_GNU_UNIQUE:    // 10 - Unique symbol (GNU)
147                         strcpy( str_binding, "GNU Unique" );
148                         break;
149                 default:
150                         snprintf( str_binding, 31, "(%02xh)", p_obj->info.symbol.b_binding );
151                         break;
152         }
153
154
155         // Symbol visibility - ELFNN_ST_VISIBILITY - st_other
156         switch( p_obj->info.symbol.b_visibility )       {
157                 case STV_DEFAULT:       // 0x00 - Default visibility (see binding).
158                         strcpy( str_visibility, "Default" );
159                         break;
160                 case STV_INTERNAL:      // 0x01 - Special meaning in relocatable objects.
161                         strcpy( str_visibility, "INTERNAL" );
162                         break;
163                 case STV_HIDDEN:        // 0x02 - Not visible.
164                         strcpy( str_visibility, "HIDDEN" );
165                         break;
166                 case STV_PROTECTED:     // 0x03 - Visible but not preemptible.
167                         strcpy( str_visibility, "PROTECTED" );
168                         break;
169                 case STV_EXPORTED:
170                         strcpy( str_visibility, "EXPORTED" );
171                         break;
172                 case STV_SINGLETON:
173                         strcpy( str_visibility, "SINGLETON" );
174                         break;
175                 case STV_ELIMINATE:
176                         strcpy( str_visibility, "ELIMINATE" );
177                         break;
178                 default:
179                         snprintf( str_binding, 31, "(%02xh)", p_obj->info.symbol.b_binding );
180                         break;
181         }
182
183         printf(" %s\t\t[SYMBOL] Type: %s, Binding: %s, Visibility: %s\n",
184                                 pstr_space, str_type, str_binding, str_visibility );
185
186
187         if( OBJINFO_STATUS_DYNAMIC & p_obj->dw_status ) {
188                 p_binfo_origin  = BinaryInfo_GetBinInfo( p_obj->dynamic.i_binfo_origin );
189
190                 printf(" %s\t\t[DYNAMIC] Lib.Name: %s (binfo id= %d), .dynsym index= %d\n",
191                                 pstr_space,
192                                 ((NULL != p_binfo_origin) ? p_binfo_origin->str_filename : "--NULL--"),
193                                 p_obj->dynamic.i_binfo_origin, p_obj->dynamic.i_dynsym_index );
194         }
195
196
197         return;
198 }
199
200 /*--------------------------------------------------------------------*/
201 void
202         Debug_ObjectInfo_Print_Function(
203                         LibGoblin_ObjectInfo    *p_obj,
204                         char    *pstr_space,
205                         Byte    b_level )
206 {
207         Debug_ObjectInfo_Print_SymbolCommon( p_obj, pstr_space, b_level );
208         return;
209 }
210
211 /*--------------------------------------------------------------------*/
212 void
213         Debug_ObjectInfo_Print_Object(
214                         LibGoblin_ObjectInfo    *p_obj,
215                         char    *pstr_space,
216                         Byte    b_level )
217 {
218         Debug_ObjectInfo_Print_SymbolCommon( p_obj, pstr_space, b_level );
219         return;
220 }
221
222 /*--------------------------------------------------------------------*/
223 void
224         Debug_ObjectInfo_Print_Common(
225                         LibGoblin_ObjectInfo    *p_obj,
226                         char    *pstr_space,
227                         Byte    b_level )
228 {
229         Debug_ObjectInfo_Print_SymbolCommon( p_obj, pstr_space, b_level );
230         return;
231 }
232
233 /*--------------------------------------------------------------------*/
234 void
235         Debug_ObjectInfo_Print_TLS(
236                         LibGoblin_ObjectInfo    *p_obj,
237                         char    *pstr_space,
238                         Byte    b_level )
239 {
240         Debug_ObjectInfo_Print_SymbolCommon( p_obj, pstr_space, b_level );
241         return;
242 }
243
244 /*--------------------------------------------------------------------*/
245 void
246         Debug_ObjectInfo_Print_Rel(
247                         LibGoblin_ObjectInfo    *p_obj,
248                         char    *pstr_space,
249                         Byte    b_level )
250 {
251         //Debug_ObjectInfo_Print_SymbolCommon( p_obj, pstr_space, b_level );
252         return;
253 }
254
255 /*--------------------------------------------------------------------*/
256 void
257         Debug_ObjectInfo_Print_Section(
258                         LibGoblin_ObjectInfo    *p_obj,
259                         char    *pstr_space,
260                         Byte    b_level )
261 {
262         char    str_type[32];
263         char    str_flag[256];
264         DWord   qw_flag;
265
266         printf(" %s\t\t[OBJINFO] Addr.Link(%3d <-> %3d)  File{ Offset=%8p, Size=%8ld, BinFileID=%d }\n",
267                                 pstr_space, 
268                                 p_obj->addrlink.i_prev_id, p_obj->addrlink.i_next_id,
269                                 p_obj->file.pv_offset, p_obj->file.qw_size, p_obj->file.i_binfile );
270
271
272         switch( p_obj->info.section.dw_type )   {
273                 /* 0 - inactive */
274                 case SHT_NULL:
275                         strncpy( str_type, "NULL", 31 );
276                         break;
277                 /* 1 - program defined information */
278                 case SHT_PROGBITS:
279                         strncpy( str_type, "PROGBITS", 31 );
280                         break;
281                 /* 2 - symbol table section */
282                 case SHT_SYMTAB:
283                         strncpy( str_type, "SYMTAB", 31 );
284                         break;
285                 /* 3 - string table section */
286                 case SHT_STRTAB:
287                         strncpy( str_type, "STRTAB", 31 );
288                         break;
289                 /* 4 - relocation section with addends */
290                 case SHT_RELA:
291                         strncpy( str_type, "RELA", 31 );
292                         break;
293                 /* 5 - symbol hash table section */
294                 case SHT_HASH:
295                         strncpy( str_type, "HASH", 31 );
296                         break;
297                 /* 6 - dynamic section */
298                 case SHT_DYNAMIC:
299                         strncpy( str_type, "DYNAMIC", 31 );
300                         break;
301                 /* 7 - note section */
302                 case SHT_NOTE:
303                         strncpy( str_type, "NOTE", 31 );
304                         break;
305                 /* 8 - no space section */
306                 case SHT_NOBITS:
307                         strncpy( str_type, "NOBITS", 31 );
308                         break;
309                 /* 9 - relocation section - no addends */
310                 case SHT_REL:
311                         strncpy( str_type, "REL", 31 );
312                         break;
313                 /* 10 - reserved - purpose unknown */
314                 case SHT_SHLIB:
315                         strncpy( str_type, "SHLIB", 31 );
316                         break;
317                 /* 11 - dynamic symbol table section */
318                 case SHT_DYNSYM:
319                         strncpy( str_type, "DYNSYM", 31 );
320                         break;
321                 /* 14 - Initialization function pointers. */
322                 case  SHT_INIT_ARRAY:
323                         strncpy( str_type, "INIT_ARRAY", 31 );
324                         break;
325                 /* 15 - Termination function pointers. */
326                 case SHT_FINI_ARRAY:
327                         strncpy( str_type, "FINI_ARRAY", 31 );
328                         break;
329                 /* 16 - Pre-initialization function ptrs. */
330                 case SHT_PREINIT_ARRAY:
331                         strncpy( str_type, "PREINIT_ARRAY", 31 );
332                         break;
333                 /* 17 - Section group. */
334                 case SHT_GROUP:
335                         strncpy( str_type, "GROUP", 31 );
336                         break;
337                 /* 18 - Section indexes (see SHN_XINDEX). */
338                 case  SHT_SYMTAB_SHNDX:
339                         strncpy( str_type, "SYMTAB_SHNDX", 31 );
340                         break;
341
342                 default:
343                         snprintf( str_type, 31, "(%8x)", p_obj->info.section.dw_type );
344                         break;
345         }
346         
347         qw_flag = p_obj->info.section.qw_flag;
348         str_flag[0]     = '\0';
349         /* SHF_WRITE 0x1:       Section contains writable data. */
350         if( SHF_WRITE & qw_flag )       { strcat( str_flag, "Write " ); }
351         /* SHF_ALLOC 0x2: Section occupies memory. */
352         if( SHF_ALLOC & qw_flag )       { strcat( str_flag, "Alloc " ); }
353         /* SHF_EXECINSTR 0x4: Section contains instructions. */
354         if( SHF_EXECINSTR & qw_flag )   { strcat( str_flag, "Exec " ); }
355         /* SHF_MERGE 0x10: Section may be merged. */
356         if( SHF_MERGE & qw_flag )       { strcat( str_flag, "Merged " ); }
357         /* SHF_STRINGS 0x20: Section contains strings. */
358         if( SHF_STRINGS & qw_flag )     { strcat( str_flag, "Strings " ); }
359         /* SHF_INFO_LINK 0x40: sh_info holds section index. */
360         if( SHF_INFO_LINK & qw_flag )   { strcat( str_flag, "InfoLink " ); }
361         /* SHF_LINK_ORDER 0x80: Special ordering requirements. */
362         if( SHF_LINK_ORDER & qw_flag )  { strcat( str_flag, "LinkOrder " ); }
363         /* SHF_OS_NONCONFORMING 0x100: OS-specific processing required. */
364         if( SHF_OS_NONCONFORMING & qw_flag )    { strcat( str_flag, "OSspecific " ); }
365         /* SHF_GROUP 0x200: Member of section group. */
366         if( SHF_GROUP & qw_flag )       { strcat( str_flag, "Group " ); }
367         /* SHF_TLS 0x400: Section contains TLS data. */
368         if( SHF_TLS & qw_flag ) { strcat( str_flag, "TLS " ); }
369         /* SHF_COMPRESSED 0x800: Section contains compressed data. */
370         if( SHF_COMPRESSED & qw_flag )  { strcat( str_flag, "Compressed " ); }
371
372         printf(" %s\t\t[SECTION] Type: %s, Align= %ld, Flag[ %s]\n",
373                                 pstr_space, str_type, p_obj->info.section.qw_align, str_flag );
374         printf(" %s\t\t[SECTION] EntSize= %ld, Link(Related Section)= %d, Info(Depends Section Type)= %xh\n",
375                                 pstr_space, p_obj->info.section.qw_entsize,
376                                 p_obj->info.section.dw_link, p_obj->info.section.dw_info );
377
378         return;
379 }
380
381 /*--------------------------------------------------------------------*/
382 void
383         Debug_ObjectInfo_Print_ProgramHeader(
384                         LibGoblin_ObjectInfo    *p_obj,
385                         char    *pstr_space,
386                         Byte    b_level )
387 {
388         char    str_type[32];
389         char    str_flag[8];
390         DWord   dw_flag;
391
392         printf(" %s\t\t[OBJINFO] Addr.Link(%3d <-> %3d)  File{ Offset=%8p, Size=%8ld, BinFileID=%d }\n",
393                                 pstr_space, 
394                                 p_obj->addrlink.i_prev_id, p_obj->addrlink.i_next_id,
395                                 p_obj->file.pv_offset, p_obj->file.qw_size, p_obj->file.i_binfile );
396
397         switch( p_obj->info.proghdr.dw_type )   {
398                 case PT_NULL:
399                         strncpy( str_type, "NULL", 31 );
400                         break;
401                 case PT_LOAD:
402                         strncpy( str_type, "LOAD", 31 );
403                         break;
404                 case PT_DYNAMIC:
405                         strncpy( str_type, "DYNAMIC", 31 );
406                         break;
407                 case PT_INTERP:
408                         strncpy( str_type, "INTERP", 31 );
409                         break;
410                 case PT_NOTE:
411                         strncpy( str_type, "NOTE", 31 );
412                         break;
413                 case PT_SHLIB:
414                         strncpy( str_type, "SHLIB", 31 );
415                         break;
416                 case PT_PHDR:
417                         strncpy( str_type, "PHDR", 31 );
418                         break;
419                 case PT_TLS:
420                         strncpy( str_type, "TLS", 31 );
421                         break;
422                 default:
423                         snprintf( str_type, 31, "(%8x)", p_obj->info.proghdr.dw_type );
424                         break;
425         }
426         
427         dw_flag = p_obj->info.proghdr.dw_flags;
428         snprintf( str_flag, 7, "%c%c%c%c%c",
429                                         ((PF_R & dw_flag) ? 'R' : ' '),
430                                         ((PF_W & dw_flag) ? 'W' : ' '),
431                                         ((PF_X & dw_flag) ? 'X' : ' '),
432                                         ((PF_MASKOS & dw_flag) ? 'O': ' '),
433                                         ((PF_MASKPROC & dw_flag) ? 'P': ' ') );
434
435         printf(" %s\t\t[PROGHDR] Flag[%5s] Type: %s, align= %ld\n",
436                                 pstr_space, str_flag, str_type, p_obj->info.proghdr.qw_align );
437
438         return;
439 }
440
441 /*--------------------------------------------------------------------*/
442 void
443         Debug_ObjectInfo_Print_ProgramFile(
444                         LibGoblin_ObjectInfo    *p_obj,
445                         char    *pstr_space,
446                         Byte    b_level )
447 {
448         printf(" %s\t\t[OBJINFO] Addr.Link(%3d <-> %3d)\n",
449                                 pstr_space, p_obj->addrlink.i_prev_id, p_obj->addrlink.i_next_id );
450
451         printf(" %s\t\t[PROGRAM] BinaryInfo ID= %d\n",
452                                 pstr_space, p_obj->info.program.i_binfo_id );
453
454         return;
455 }
456
457
458 /*====================================================================*/
459 /*--------------------------------------------------------------------*/
460 void
461         Debug_ObjectInfo_PrintInfo(
462                         LibGoblin_ObjectInfo    *p_obj,
463                         int             i_depth,
464                         char    *pstr_space,
465                         int             i_len,
466                         Byte    b_level )
467 {
468
469         // Set Space String ---
470         if( 0 < i_depth )       {
471                 *(pstr_space + i_len - 2)       = '+';
472                 *(pstr_space + i_len - 1)       = '-';
473         }
474         printf(" %sOBJINFO[%4d] (%-8s)\t%16lxh - %16lxh (Size: %16lxh) : %s\n",
475                                 pstr_space, p_obj->i_id,
476                                 gstr_type[ p_obj->b_type ],
477                                 p_obj->addr.ptr_addr.value,
478                                 (( 0 < p_obj->addr.qw_size )
479                                         ? (p_obj->addr.ptr_addr.value + p_obj->addr.qw_size - 1)
480                                         : p_obj->addr.ptr_addr.value),
481                                 p_obj->addr.qw_size,
482                                 p_obj->pstr_name );
483
484         if( 0 < i_depth )       {
485                 if( NO_OBJINFO != p_obj->grplink.i_next_id )
486                                 { *(pstr_space + i_len - 2)     = '|'; }
487                 else    { *(pstr_space + i_len - 2)     = ' '; }
488                 *(pstr_space + i_len - 1)       = ' ';
489         }
490
491         if( NO_OBJINFO != p_obj->grplink.i_child_topid )
492                         { strcat( pstr_space, " | " ); }
493         else    { strcat( pstr_space, "   " ); }
494
495         switch( p_obj->b_type ) {
496                 case OBJINFO_TYPE_PROGRAM:
497                         Debug_ObjectInfo_Print_ProgramFile( p_obj, pstr_space, b_level );
498                         break;
499
500                 case OBJINFO_TYPE_PROGHDR:
501                         Debug_ObjectInfo_Print_ProgramHeader( p_obj, pstr_space, b_level );
502                         break;
503
504                 case OBJINFO_TYPE_SECTION:
505                         Debug_ObjectInfo_Print_Section( p_obj, pstr_space, b_level );
506                         break;
507
508                 case OBJINFO_TYPE_FUNCTION:
509                         Debug_ObjectInfo_Print_Function( p_obj, pstr_space, b_level );
510                         break;
511
512                 case OBJINFO_TYPE_OBJECT:
513                         Debug_ObjectInfo_Print_Object( p_obj, pstr_space, b_level );
514                         break;
515
516                 case OBJINFO_TYPE_COMMON:
517                         Debug_ObjectInfo_Print_Common( p_obj, pstr_space, b_level );
518                         break;
519
520                 case OBJINFO_TYPE_TLS:
521                         Debug_ObjectInfo_Print_TLS( p_obj, pstr_space, b_level );
522                         break;
523
524                 case OBJINFO_TYPE_REL:
525                         Debug_ObjectInfo_Print_Rel( p_obj, pstr_space, b_level );
526                         break;
527
528                 default:
529                         break;
530         }
531         printf(" %s\n", pstr_space );
532
533         *(pstr_space + i_len)   = '\0';
534
535         return;
536 }
537
538
539 /*====================================================================*/
540 /*--------------------------------------------------------------------*/
541 LIBGOBLIN_DEBUG_OBJINFO_EXTERN
542 int
543         Debug_ObjectInfo_Print_AllAddrLink(
544                         LibGoblin_ProgramInfo   *p_pginfo,
545                         Byte            b_level )
546 {
547         //LibGoblin_ObjectInfo  *p_objinfo;
548
549         if( 0x00 < b_level )
550                 { puts("[DEBUG] ObjectInfo - Addr.Link --------------------------------------"); }
551
552
553
554
555         if( 0x00 < b_level )    {
556                 puts("-----------------------------------------------------------------------");
557                 puts("");
558         }
559
560         return 0x00;
561 }
562
563 /*====================================================================*/
564 /*--------------------------------------------------------------------*/
565 void
566         Debug_ObjectInfo_Print_GroupLink(
567                         LibGoblin_ProgramInfo   *p_pginfo,
568                         LibGoblin_ObjectInfo    *p_objstart,
569                         int             i_depth,
570                         char    *pstr_space,
571                         Byte    b_level )
572 {
573         int     i_len;
574         LibGoblin_ObjectInfo    *p_objinfo;
575
576         i_len   = strnlen( pstr_space, 384 );
577         if( 0 < i_depth )       { strcat( pstr_space, " | " ); }
578
579         if( NULL == p_objstart )        { return; }
580         p_objinfo       = p_objstart;
581         do      {
582                 // Print ObjInfo ---
583                 Debug_ObjectInfo_PrintInfo( p_objinfo, i_depth, pstr_space,
584                                                 (i_len + ((0 < i_depth) ? 3 : 0)), b_level );
585
586                 // Child. ---
587                 if( NO_OBJINFO != p_objinfo->grplink.i_child_topid )    {
588                         Debug_ObjectInfo_Print_GroupLink(
589                                         p_pginfo,
590                                         OBJINFO( p_pginfo, p_objinfo->grplink.i_child_topid ),
591                                         (i_depth + 1), pstr_space, b_level );
592                 }
593
594                 // Set Next ObjectInfo ---
595                 p_objinfo       = ((NO_OBJINFO == p_objinfo->grplink.i_next_id)
596                                                         ? NULL : OBJINFO( p_pginfo, p_objinfo->grplink.i_next_id ));
597         } while( NULL != p_objinfo );
598
599         *(pstr_space + i_len)   = '\0';
600
601         return;
602 }
603
604
605 /*--------------------------------------------------------------------*/
606 LIBGOBLIN_DEBUG_OBJINFO_EXTERN
607 int
608         Debug_ObjectInfo_Print_AllGroupLink(
609                         LibGoblin_ProgramInfo   *p_pginfo,
610                         Byte            b_level )
611 {
612         char                                    str_space[384];
613         //LibGoblin_ObjectInfo  *p_objinfo;
614
615         str_space[0]    = '\0';
616
617         if( 0x00 < b_level )
618                 { puts("[DEBUG] ObjectInfo - GroupLink --------------------------------------"); }
619
620
621         Debug_ObjectInfo_Print_GroupLink( p_pginfo, p_pginfo->objinfo.p_objinfo, 0, str_space, b_level );
622
623         if( 0x00 < b_level )    {
624                 puts("-----------------------------------------------------------------------");
625                 puts("");
626         }
627
628         return 0x00;
629 }
630
631
632 /* EOF of drd64_.c ----------------------------------- */