bfc8dc5cb11b75539a9d04edaadab6ecedfecd0a
1 /* Do various things to symbol tables (other than lookup), for GDB.
2 Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "breakpoint.h"
34 #define DEV_TTY "/dev/tty"
37 /* Unfortunately for debugging, stderr is usually a macro. This is painful
38 when calling functions that take FILE *'s from the debugger.
39 So we make a variable which has the same value and which is accessible when
40 debugging GDB with itself. Because stdin et al need not be constants,
41 we initialize them in the _initialize_symmisc function at the bottom
47 /* Prototypes for local functions */
50 dump_symtab
PARAMS ((struct objfile
*, struct symtab
*, GDB_FILE
*));
53 dump_psymtab
PARAMS ((struct objfile
*, struct partial_symtab
*, GDB_FILE
*));
56 dump_msymbols
PARAMS ((struct objfile
*, GDB_FILE
*));
59 dump_objfile
PARAMS ((struct objfile
*));
62 block_depth
PARAMS ((struct block
*));
65 print_partial_symbol
PARAMS ((struct partial_symbol
*, int, char *, GDB_FILE
*));
67 struct print_symbol_args
{
68 struct symbol
*symbol
;
73 static int print_symbol
PARAMS ((char *));
76 free_symtab_block
PARAMS ((struct objfile
*, struct block
*));
79 /* Free a struct block <- B and all the symbols defined in that block. */
82 free_symtab_block (objfile
, b
)
83 struct objfile
*objfile
;
88 for (i
= 0; i
< n
; i
++)
90 mfree (objfile
-> md
, SYMBOL_NAME (BLOCK_SYM (b
, i
)));
91 mfree (objfile
-> md
, (PTR
) BLOCK_SYM (b
, i
));
93 mfree (objfile
-> md
, (PTR
) b
);
96 /* Free all the storage associated with the struct symtab <- S.
97 Note that some symtabs have contents malloc'ed structure by structure,
98 while some have contents that all live inside one big block of memory,
99 and some share the contents of another symbol table and so you should
100 not free the contents on their behalf (except sometimes the linetable,
101 which maybe per symtab even when the rest is not).
102 It is s->free_code that says which alternative to use. */
106 register struct symtab
*s
;
109 register struct blockvector
*bv
;
111 switch (s
->free_code
)
114 /* All the contents are part of a big block of memory (an obstack),
115 and some other symtab is in charge of freeing that block.
116 Therefore, do nothing. */
120 /* Here all the contents were malloc'ed structure by structure
121 and must be freed that way. */
122 /* First free the blocks (and their symbols. */
123 bv
= BLOCKVECTOR (s
);
124 n
= BLOCKVECTOR_NBLOCKS (bv
);
125 for (i
= 0; i
< n
; i
++)
126 free_symtab_block (s
-> objfile
, BLOCKVECTOR_BLOCK (bv
, i
));
127 /* Free the blockvector itself. */
128 mfree (s
-> objfile
-> md
, (PTR
) bv
);
129 /* Also free the linetable. */
132 /* Everything will be freed either by our `free_ptr'
133 or by some other symtab, except for our linetable.
136 mfree (s
-> objfile
-> md
, (PTR
) LINETABLE (s
));
140 /* If there is a single block of memory to free, free it. */
141 if (s
-> free_ptr
!= NULL
)
142 mfree (s
-> objfile
-> md
, s
-> free_ptr
);
144 /* Free source-related stuff */
145 if (s
-> line_charpos
!= NULL
)
146 mfree (s
-> objfile
-> md
, (PTR
) s
-> line_charpos
);
147 if (s
-> fullname
!= NULL
)
148 mfree (s
-> objfile
-> md
, s
-> fullname
);
149 mfree (s
-> objfile
-> md
, (PTR
) s
);
155 dump_objfile (objfile
)
156 struct objfile
*objfile
;
158 struct symtab
*symtab
;
159 struct partial_symtab
*psymtab
;
161 printf_filtered ("\nObject file %s: ", objfile
-> name
);
162 printf_filtered ("Objfile at ");
163 gdb_print_address (objfile
, gdb_stdout
);
164 printf_filtered (", bfd at ");
165 gdb_print_address (objfile
->obfd
, gdb_stdout
);
166 printf_filtered (", %d minsyms\n\n",
167 objfile
->minimal_symbol_count
);
169 if (objfile
-> psymtabs
)
171 printf_filtered ("Psymtabs:\n");
172 for (psymtab
= objfile
-> psymtabs
;
174 psymtab
= psymtab
-> next
)
176 printf_filtered ("%s at ",
177 psymtab
-> filename
);
178 gdb_print_address (psymtab
);
179 printf_filtered (", ");
180 if (psymtab
-> objfile
!= objfile
)
182 printf_filtered ("NOT ON CHAIN! ");
186 printf_filtered ("\n\n");
189 if (objfile
-> symtabs
)
191 printf_filtered ("Symtabs:\n");
192 for (symtab
= objfile
-> symtabs
;
194 symtab
= symtab
->next
)
196 printf_filtered ("%s at ", symtab
-> filename
);
197 gdb_print_address (symtab
);
198 printf_filtered (", ");
199 if (symtab
-> objfile
!= objfile
)
201 printf_filtered ("NOT ON CHAIN! ");
205 printf_filtered ("\n\n");
209 /* Print minimal symbols from this objfile. */
212 dump_msymbols (objfile
, outfile
)
213 struct objfile
*objfile
;
216 struct minimal_symbol
*msymbol
;
220 fprintf_filtered (outfile
, "\nObject file %s:\n\n", objfile
-> name
);
221 if (objfile
-> minimal_symbol_count
== 0)
223 fprintf_filtered (outfile
, "No minimal symbols found.\n");
226 for (index
= 0, msymbol
= objfile
-> msymbols
;
227 SYMBOL_NAME (msymbol
) != NULL
; msymbol
++, index
++)
229 switch (msymbol
-> type
)
259 fprintf_filtered (outfile
, "[%2d] %c %#10lx %s", index
, ms_type
,
260 SYMBOL_VALUE_ADDRESS (msymbol
), SYMBOL_NAME (msymbol
));
261 if (SYMBOL_DEMANGLED_NAME (msymbol
) != NULL
)
263 fprintf_filtered (outfile
, " %s", SYMBOL_DEMANGLED_NAME (msymbol
));
265 fputs_filtered ("\n", outfile
);
267 if (objfile
-> minimal_symbol_count
!= index
)
269 warning ("internal error: minimal symbol count %d != %d",
270 objfile
-> minimal_symbol_count
, index
);
272 fprintf_filtered (outfile
, "\n");
276 dump_psymtab (objfile
, psymtab
, outfile
)
277 struct objfile
*objfile
;
278 struct partial_symtab
*psymtab
;
283 fprintf_filtered (outfile
, "\nPartial symtab for source file %s ",
284 psymtab
-> filename
);
285 fprintf_filtered (outfile
, "(object )");
286 gdb_print_address (psymtab
, outfile
);
287 fprintf_filtered (outfile
, ")\n\n");
288 fprintf_unfiltered (outfile
, " Read from object file %s (",
290 gdb_print_address (objfile
, outfile
);
291 fprintf_unfiltered (outfile
, ")\n");
293 if (psymtab
-> readin
)
295 fprintf_filtered (outfile
,
296 " Full symtab was read (at ");
297 gdb_print_address (psymtab
->symtab
, outfile
);
298 fprintf_filtered (outfile
, " by function at ");
299 gdb_print_address (psymtab
->read_symtab
, outfile
);
300 fprintf_filtered (outfile
, ")\n");
303 fprintf_filtered (outfile
, " Relocate symbols by ");
304 for (i
= 0; i
< psymtab
->objfile
->num_sections
; ++i
)
307 print_address_numeric (ANOFFSET (psymtab
->section_offsets
, i
), outfile
);
308 fprintf_filtered (outfile
, ", ");
311 fprintf_filtered (outfile
, " Symbols cover text addresses ");
312 print_address_numeric (psymtab
->textlow
, outfile
);
313 fprintf_filtered (outfile
, "-");
314 print_address_numeric (psymtab
->texthigh
, outfile
);
315 fprintf_filtered (outfile
, "\n");
316 fprintf_filtered (outfile
, " Depends on %d other partial symtabs.\n",
317 psymtab
-> number_of_dependencies
);
318 for (i
= 0; i
< psymtab
-> number_of_dependencies
; i
++)
320 fprintf_filtered (outfile
, " %d ", i
);
321 gdb_print_address (psymtab
-> dependencies
[i
], outfile
);
322 fprintf_filtered (outfile
, " %s\n",
323 psymtab
-> dependencies
[i
] -> filename
);
325 if (psymtab
-> n_global_syms
> 0)
327 print_partial_symbol (objfile
-> global_psymbols
.list
328 + psymtab
-> globals_offset
,
329 psymtab
-> n_global_syms
, "Global", outfile
);
331 if (psymtab
-> n_static_syms
> 0)
333 print_partial_symbol (objfile
-> static_psymbols
.list
334 + psymtab
-> statics_offset
,
335 psymtab
-> n_static_syms
, "Static", outfile
);
337 fprintf_filtered (outfile
, "\n");
341 dump_symtab (objfile
, symtab
, outfile
)
342 struct objfile
*objfile
;
343 struct symtab
*symtab
;
348 register struct linetable
*l
;
349 struct blockvector
*bv
;
350 register struct block
*b
;
353 fprintf_filtered (outfile
, "\nSymtab for file %s\n", symtab
->filename
);
354 fprintf_filtered (outfile
, "Read from object file %s (", objfile
->name
);
355 gdb_print_address (objfile
, outfile
);
356 fprintf_filtered (outfile
, ")\n");
357 fprintf_filtered (outfile
, "Language: %s\n", language_str (symtab
-> language
));
359 /* First print the line table. */
360 l
= LINETABLE (symtab
);
363 fprintf_filtered (outfile
, "\nLine table:\n\n");
365 for (i
= 0; i
< len
; i
++)
367 fprintf_filtered (outfile
, " line %d at ", l
->item
[i
].line
);
368 print_address_numeric (l
->item
[i
].pc
, outfile
);
369 fprintf_filtered (outfile
, "\n");
372 /* Now print the block info. */
373 fprintf_filtered (outfile
, "\nBlockvector:\n\n");
374 bv
= BLOCKVECTOR (symtab
);
375 len
= BLOCKVECTOR_NBLOCKS (bv
);
376 for (i
= 0; i
< len
; i
++)
378 b
= BLOCKVECTOR_BLOCK (bv
, i
);
379 depth
= block_depth (b
) * 2;
380 print_spaces (depth
, outfile
);
381 fprintf_filtered (outfile
, "block #%03d (object ", i
);
382 gdb_print_address (b
, outfile
);
383 fprintf_filtered (outfile
, ") ");
384 fprintf_filtered (outfile
, "[");
385 print_address_numeric (BLOCK_START (b
), outfile
);
386 fprintf_filtered (outfile
, "..");
387 print_address_numeric (BLOCK_END (b
), outfile
);
388 fprintf_filtered (outfile
, "]");
389 if (BLOCK_SUPERBLOCK (b
))
391 fprintf_filtered (outfile
, " (under ");
392 gdb_print_address (BLOCK_SUPERBLOCK (b
), outfile
);
393 fprintf_filtered (outfile
, ")");
395 if (BLOCK_FUNCTION (b
))
397 fprintf_filtered (outfile
, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b
)));
398 if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b
)) != NULL
)
400 fprintf_filtered (outfile
, " %s",
401 SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b
)));
404 if (BLOCK_GCC_COMPILED(b
))
405 fprintf_filtered (outfile
, " gcc%d compiled", BLOCK_GCC_COMPILED(b
));
406 fputc_filtered ('\n', outfile
);
407 blen
= BLOCK_NSYMS (b
);
408 for (j
= 0; j
< blen
; j
++)
410 struct print_symbol_args s
;
411 s
.symbol
= BLOCK_SYM (b
, j
);
414 catch_errors (print_symbol
, &s
, "Error printing symbol:\n",
418 fprintf_filtered (outfile
, "\n");
422 maintenance_print_symbols (args
, from_tty
)
428 struct cleanup
*cleanups
;
429 char *symname
= NULL
;
430 char *filename
= DEV_TTY
;
431 struct objfile
*objfile
;
438 error ("print-symbols takes an output file name and optional symbol file name");
440 else if ((argv
= buildargv (args
)) == NULL
)
444 cleanups
= make_cleanup (freeargv
, (char *) argv
);
449 /* If a second arg is supplied, it is a source file name to match on */
456 filename
= tilde_expand (filename
);
457 make_cleanup (free
, filename
);
459 outfile
= gdb_fopen (filename
, FOPEN_WT
);
461 perror_with_name (filename
);
462 make_cleanup (fclose
, (char *) outfile
);
465 ALL_SYMTABS (objfile
, s
)
466 if (symname
== NULL
|| (STREQ (symname
, s
-> filename
)))
467 dump_symtab (objfile
, s
, outfile
);
469 do_cleanups (cleanups
);
472 /* Print symbol ARGS->SYMBOL on ARGS->OUTFILE. ARGS->DEPTH says how
473 far to indent. ARGS is really a struct print_symbol_args *, but is
474 declared as char * to get it past catch_errors. Returns 0 for error,
481 struct symbol
*symbol
= ((struct print_symbol_args
*)args
)->symbol
;
482 int depth
= ((struct print_symbol_args
*)args
)->depth
;
483 GDB_FILE
*outfile
= ((struct print_symbol_args
*)args
)->outfile
;
485 print_spaces (depth
, outfile
);
486 if (SYMBOL_NAMESPACE (symbol
) == LABEL_NAMESPACE
)
488 fprintf_filtered (outfile
, "label %s at ", SYMBOL_SOURCE_NAME (symbol
));
489 print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol
), outfile
);
490 fprintf_filtered (outfile
, "\n");
493 if (SYMBOL_NAMESPACE (symbol
) == STRUCT_NAMESPACE
)
495 if (TYPE_TAG_NAME (SYMBOL_TYPE (symbol
)))
497 LA_PRINT_TYPE (SYMBOL_TYPE (symbol
), "", outfile
, 1, depth
);
501 fprintf_filtered (outfile
, "%s %s = ",
502 (TYPE_CODE (SYMBOL_TYPE (symbol
)) == TYPE_CODE_ENUM
504 : (TYPE_CODE (SYMBOL_TYPE (symbol
)) == TYPE_CODE_STRUCT
505 ? "struct" : "union")),
506 SYMBOL_NAME (symbol
));
507 LA_PRINT_TYPE (SYMBOL_TYPE (symbol
), "", outfile
, 1, depth
);
509 fprintf_filtered (outfile
, ";\n");
513 if (SYMBOL_CLASS (symbol
) == LOC_TYPEDEF
)
514 fprintf_filtered (outfile
, "typedef ");
515 if (SYMBOL_TYPE (symbol
))
517 /* Print details of types, except for enums where it's clutter. */
518 LA_PRINT_TYPE (SYMBOL_TYPE (symbol
), SYMBOL_SOURCE_NAME (symbol
),
520 TYPE_CODE (SYMBOL_TYPE (symbol
)) != TYPE_CODE_ENUM
,
522 fprintf_filtered (outfile
, "; ");
525 fprintf_filtered (outfile
, "%s ", SYMBOL_SOURCE_NAME (symbol
));
527 switch (SYMBOL_CLASS (symbol
))
530 fprintf_filtered (outfile
, "const %ld (0x%lx),",
531 SYMBOL_VALUE (symbol
),
532 SYMBOL_VALUE (symbol
));
535 case LOC_CONST_BYTES
:
536 fprintf_filtered (outfile
, "const %u hex bytes:",
537 TYPE_LENGTH (SYMBOL_TYPE (symbol
)));
540 for (i
= 0; i
< TYPE_LENGTH (SYMBOL_TYPE (symbol
)); i
++)
541 fprintf_filtered (outfile
, " %02x",
542 (unsigned)SYMBOL_VALUE_BYTES (symbol
) [i
]);
543 fprintf_filtered (outfile
, ",");
548 fprintf_filtered (outfile
, "static at ");
549 print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol
), outfile
);
550 fprintf_filtered (outfile
, ",");
554 fprintf_filtered (outfile
, "register %ld,", SYMBOL_VALUE (symbol
));
558 fprintf_filtered (outfile
, "arg at offset 0x%lx,",
559 SYMBOL_VALUE (symbol
));
563 fprintf_filtered (outfile
, "arg at offset 0x%lx from fp,",
564 SYMBOL_VALUE (symbol
));
568 fprintf_filtered (outfile
, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol
));
572 fprintf_filtered (outfile
, "parameter register %ld,", SYMBOL_VALUE (symbol
));
575 case LOC_REGPARM_ADDR
:
576 fprintf_filtered (outfile
, "address parameter register %ld,", SYMBOL_VALUE (symbol
));
580 fprintf_filtered (outfile
, "local at offset 0x%lx,",
581 SYMBOL_VALUE (symbol
));
585 fprintf_filtered (outfile
, "local at 0x%lx from register %d",
586 SYMBOL_VALUE (symbol
), SYMBOL_BASEREG (symbol
));
589 case LOC_BASEREG_ARG
:
590 fprintf_filtered (outfile
, "arg at 0x%lx from register %d,",
591 SYMBOL_VALUE (symbol
), SYMBOL_BASEREG (symbol
));
598 fprintf_filtered (outfile
, "label at ");
599 print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol
), outfile
);
603 fprintf_filtered (outfile
, "block (object ");
604 gdb_print_address (SYMBOL_BLOCK_VALUE (symbol
), outfile
);
605 fprintf_filtered (outfile
, ") starting at ");
606 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (symbol
)),
608 fprintf_filtered (outfile
, ",");
611 case LOC_OPTIMIZED_OUT
:
612 fprintf_filtered (outfile
, "optimized out");
616 fprintf_filtered (outfile
, "botched symbol class %x",
617 SYMBOL_CLASS (symbol
));
621 fprintf_filtered (outfile
, "\n");
626 maintenance_print_psymbols (args
, from_tty
)
632 struct cleanup
*cleanups
;
633 char *symname
= NULL
;
634 char *filename
= DEV_TTY
;
635 struct objfile
*objfile
;
636 struct partial_symtab
*ps
;
642 error ("print-psymbols takes an output file name and optional symbol file name");
644 else if ((argv
= buildargv (args
)) == NULL
)
648 cleanups
= make_cleanup (freeargv
, (char *) argv
);
653 /* If a second arg is supplied, it is a source file name to match on */
660 filename
= tilde_expand (filename
);
661 make_cleanup (free
, filename
);
663 outfile
= gdb_fopen (filename
, FOPEN_WT
);
665 perror_with_name (filename
);
666 make_cleanup (fclose
, outfile
);
669 ALL_PSYMTABS (objfile
, ps
)
670 if (symname
== NULL
|| (STREQ (symname
, ps
-> filename
)))
671 dump_psymtab (objfile
, ps
, outfile
);
673 do_cleanups (cleanups
);
677 print_partial_symbol (p
, count
, what
, outfile
)
678 struct partial_symbol
*p
;
684 fprintf_filtered (outfile
, " %s partial symbols:\n", what
);
687 fprintf_filtered (outfile
, " `%s'", SYMBOL_NAME(p
));
688 if (SYMBOL_DEMANGLED_NAME (p
) != NULL
)
690 fprintf_filtered (outfile
, " `%s'", SYMBOL_DEMANGLED_NAME (p
));
692 fputs_filtered (", ", outfile
);
693 switch (SYMBOL_NAMESPACE (p
))
695 case UNDEF_NAMESPACE
:
696 fputs_filtered ("undefined namespace, ", outfile
);
699 /* This is the usual thing -- don't print it */
701 case STRUCT_NAMESPACE
:
702 fputs_filtered ("struct namespace, ", outfile
);
704 case LABEL_NAMESPACE
:
705 fputs_filtered ("label namespace, ", outfile
);
708 fputs_filtered ("<invalid namespace>, ", outfile
);
711 switch (SYMBOL_CLASS (p
))
714 fputs_filtered ("undefined", outfile
);
717 fputs_filtered ("constant int", outfile
);
720 fputs_filtered ("static", outfile
);
723 fputs_filtered ("register", outfile
);
726 fputs_filtered ("pass by value", outfile
);
729 fputs_filtered ("pass by reference", outfile
);
732 fputs_filtered ("register parameter", outfile
);
734 case LOC_REGPARM_ADDR
:
735 fputs_filtered ("register address parameter", outfile
);
738 fputs_filtered ("stack parameter", outfile
);
741 fputs_filtered ("type", outfile
);
744 fputs_filtered ("label", outfile
);
747 fputs_filtered ("function", outfile
);
749 case LOC_CONST_BYTES
:
750 fputs_filtered ("constant bytes", outfile
);
753 fputs_filtered ("shuffled arg", outfile
);
755 case LOC_OPTIMIZED_OUT
:
756 fputs_filtered ("optimized out", outfile
);
759 fputs_filtered ("<invalid location>", outfile
);
762 fputs_filtered (", ", outfile
);
763 /* FIXME-32x64: Need to use SYMBOL_VALUE_ADDRESS, etc.; this
764 could be 32 bits when some of the other fields in the union
766 fprintf_filtered (outfile
, "0x%lx\n", SYMBOL_VALUE (p
));
772 maintenance_print_msymbols (args
, from_tty
)
778 struct cleanup
*cleanups
;
779 char *filename
= DEV_TTY
;
780 char *symname
= NULL
;
781 struct objfile
*objfile
;
787 error ("print-msymbols takes an output file name and optional symbol file name");
789 else if ((argv
= buildargv (args
)) == NULL
)
793 cleanups
= make_cleanup (freeargv
, argv
);
798 /* If a second arg is supplied, it is a source file name to match on */
805 filename
= tilde_expand (filename
);
806 make_cleanup (free
, filename
);
808 outfile
= gdb_fopen (filename
, FOPEN_WT
);
810 perror_with_name (filename
);
811 make_cleanup (fclose
, outfile
);
814 ALL_OBJFILES (objfile
)
815 if (symname
== NULL
|| (STREQ (symname
, objfile
-> name
)))
816 dump_msymbols (objfile
, outfile
);
818 fprintf_filtered (outfile
, "\n\n");
819 do_cleanups (cleanups
);
823 maintenance_print_objfiles (ignore
, from_tty
)
827 struct objfile
*objfile
;
832 ALL_OBJFILES (objfile
)
833 dump_objfile (objfile
);
838 /* Return the nexting depth of a block within other blocks in its symtab. */
845 while ((block
= BLOCK_SUPERBLOCK (block
)) != NULL
)
852 #endif /* MAINTENANCE_CMDS */
855 /* Increase the space allocated for LISTP, which is probably
856 global_psymbol_list or static_psymbol_list. This space will eventually
857 be freed in free_objfile(). */
860 extend_psymbol_list (listp
, objfile
)
861 register struct psymbol_allocation_list
*listp
;
862 struct objfile
*objfile
;
865 if (listp
->size
== 0)
868 listp
->list
= (struct partial_symbol
*)
869 xmmalloc (objfile
-> md
, new_size
* sizeof (struct partial_symbol
));
873 new_size
= listp
->size
* 2;
874 listp
->list
= (struct partial_symbol
*)
875 xmrealloc (objfile
-> md
, (char *) listp
->list
,
876 new_size
* sizeof (struct partial_symbol
));
878 /* Next assumes we only went one over. Should be good if
879 program works correctly */
880 listp
->next
= listp
->list
+ listp
->size
;
881 listp
->size
= new_size
;
885 /* Do early runtime initializations. */
887 _initialize_symmisc ()
This page took 0.049441 seconds and 4 git commands to generate.