ia64/xen-unstable
changeset 13250:60f91c9f1a24
[XEN] Make labels _start,_end,_stext,_etext,_sinittext,_einittext generic.
Also sync the tools/symbol.c symbol table generator with Linux.
Make section names generic (e.e.g, .init.text, .init.data, ...).
Signed-off-by: Keir Fraser <keir@xensource.com>
Also sync the tools/symbol.c symbol table generator with Linux.
Make section names generic (e.e.g, .init.text, .init.data, ...).
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@localhost.localdomain |
---|---|
date | Wed Jan 03 23:53:27 2007 +0000 (2007-01-03) |
parents | bf25488db8eb |
children | bdbfbfdfbd64 |
files | xen/arch/ia64/xen/xenmisc.c xen/arch/powerpc/setup.c xen/arch/powerpc/xen.lds.S xen/arch/x86/boot/x86_32.S xen/arch/x86/boot/x86_64.S xen/arch/x86/traps.c xen/arch/x86/x86_32/xen.lds.S xen/arch/x86/x86_64/xen.lds.S xen/common/kexec.c xen/common/symbols.c xen/include/asm-ia64/init.h xen/include/asm-powerpc/init.h xen/include/asm-x86/config.h xen/include/asm-x86/init.h xen/include/xen/init.h xen/include/xen/kernel.h xen/include/xen/symbols.h xen/tools/symbols.c |
line diff
1.1 --- a/xen/arch/ia64/xen/xenmisc.c Wed Jan 03 14:08:42 2007 +0000 1.2 +++ b/xen/arch/ia64/xen/xenmisc.c Wed Jan 03 23:53:27 2007 +0000 1.3 @@ -57,26 +57,6 @@ is_platform_hp_ski(void) 1.4 struct pt_regs *guest_cpu_user_regs(void) { return vcpu_regs(current); } 1.5 1.6 /////////////////////////////// 1.7 -// from arch/ia64/traps.c 1.8 -/////////////////////////////// 1.9 - 1.10 -int is_kernel_text(unsigned long addr) 1.11 -{ 1.12 - extern char _stext[], _etext[]; 1.13 - if (addr >= (unsigned long) _stext && 1.14 - addr <= (unsigned long) _etext) 1.15 - return 1; 1.16 - 1.17 - return 0; 1.18 -} 1.19 - 1.20 -unsigned long kernel_text_end(void) 1.21 -{ 1.22 - extern char _etext[]; 1.23 - return (unsigned long) _etext; 1.24 -} 1.25 - 1.26 -/////////////////////////////// 1.27 // from common/keyhandler.c 1.28 /////////////////////////////// 1.29 void dump_pageframe_info(struct domain *d)
2.1 --- a/xen/arch/powerpc/setup.c Wed Jan 03 14:08:42 2007 +0000 2.2 +++ b/xen/arch/powerpc/setup.c Wed Jan 03 23:53:27 2007 +0000 2.3 @@ -91,19 +91,6 @@ static struct domain *idle_domain; 2.4 2.5 volatile struct processor_area * volatile global_cpu_table[NR_CPUS]; 2.6 2.7 -int is_kernel_text(unsigned long addr) 2.8 -{ 2.9 - if (addr >= (unsigned long) &_start && 2.10 - addr <= (unsigned long) &_etext) 2.11 - return 1; 2.12 - return 0; 2.13 -} 2.14 - 2.15 -unsigned long kernel_text_end(void) 2.16 -{ 2.17 - return (unsigned long) &_etext; 2.18 -} 2.19 - 2.20 static void __init do_initcalls(void) 2.21 { 2.22 initcall_t *call;
3.1 --- a/xen/arch/powerpc/xen.lds.S Wed Jan 03 14:08:42 2007 +0000 3.2 +++ b/xen/arch/powerpc/xen.lds.S Wed Jan 03 23:53:27 2007 +0000 3.3 @@ -113,10 +113,10 @@ SECTIONS 3.4 3.5 . = ALIGN(32); 3.6 __setup_start = .; 3.7 - .setup.init : { *(.setup.init) } 3.8 + .init.setup : { *(.init.setup) } 3.9 __setup_end = .; 3.10 __initcall_start = .; 3.11 - .initcall.init : { *(.initcall.init) } 3.12 + .initcall.init : { *(.initcall1.init) } 3.13 __initcall_end = .; 3.14 __inithcall_start = .; 3.15 .inithcall.text : { *(.inithcall.text) }
4.1 --- a/xen/arch/x86/boot/x86_32.S Wed Jan 03 14:08:42 2007 +0000 4.2 +++ b/xen/arch/x86/boot/x86_32.S Wed Jan 03 23:53:27 2007 +0000 4.3 @@ -11,8 +11,6 @@ 4.4 .text 4.5 4.6 ENTRY(start) 4.7 -ENTRY(stext) 4.8 -ENTRY(_stext) 4.9 jmp __start 4.10 4.11 .align 4
5.1 --- a/xen/arch/x86/boot/x86_64.S Wed Jan 03 14:08:42 2007 +0000 5.2 +++ b/xen/arch/x86/boot/x86_64.S Wed Jan 03 23:53:27 2007 +0000 5.3 @@ -14,8 +14,6 @@ 5.4 #define SYM_PHYS(sym) (sym - __PAGE_OFFSET) 5.5 5.6 ENTRY(start) 5.7 -ENTRY(stext) 5.8 -ENTRY(_stext) 5.9 jmp __start 5.10 5.11 .org 0x004
6.1 --- a/xen/arch/x86/traps.c Wed Jan 03 14:08:42 2007 +0000 6.2 +++ b/xen/arch/x86/traps.c Wed Jan 03 23:53:27 2007 +0000 6.3 @@ -115,22 +115,6 @@ integer_param("debug_stack_lines", debug 6.4 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp) 6.5 #endif 6.6 6.7 -int is_kernel_text(unsigned long addr) 6.8 -{ 6.9 - extern char _stext, _etext; 6.10 - if (addr >= (unsigned long) &_stext && 6.11 - addr <= (unsigned long) &_etext) 6.12 - return 1; 6.13 - return 0; 6.14 - 6.15 -} 6.16 - 6.17 -unsigned long kernel_text_end(void) 6.18 -{ 6.19 - extern char _etext; 6.20 - return (unsigned long) &_etext; 6.21 -} 6.22 - 6.23 static void show_guest_stack(struct cpu_user_regs *regs) 6.24 { 6.25 int i; 6.26 @@ -187,7 +171,7 @@ static void show_trace(struct cpu_user_r 6.27 while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 ) 6.28 { 6.29 addr = *stack++; 6.30 - if ( is_kernel_text(addr) ) 6.31 + if ( is_kernel_text(addr) || is_kernel_inittext(addr) ) 6.32 { 6.33 printk("[<%p>]", _p(addr)); 6.34 print_symbol(" %s\n ", addr); 6.35 @@ -316,7 +300,7 @@ void show_stack_overflow(unsigned long e 6.36 while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 ) 6.37 { 6.38 addr = *stack++; 6.39 - if ( is_kernel_text(addr) ) 6.40 + if ( is_kernel_text(addr) || is_kernel_inittext(addr) ) 6.41 { 6.42 printk("%p: [<%p>]", stack, _p(addr)); 6.43 print_symbol(" %s\n ", addr);
7.1 --- a/xen/arch/x86/x86_32/xen.lds.S Wed Jan 03 14:08:42 2007 +0000 7.2 +++ b/xen/arch/x86/x86_32/xen.lds.S Wed Jan 03 23:53:27 2007 +0000 7.3 @@ -19,7 +19,8 @@ PHDRS 7.4 SECTIONS 7.5 { 7.6 . = 0xFF000000 + 0x100000; 7.7 - _text = .; /* Text and read-only data */ 7.8 + _start = .; 7.9 + _stext = .; /* Text and read-only data */ 7.10 .text : { 7.11 *(.text) 7.12 *(.fixup) 7.13 @@ -51,14 +52,16 @@ SECTIONS 7.14 7.15 . = ALIGN(4096); /* Init code and data */ 7.16 __init_begin = .; 7.17 - .text.init : { *(.text.init) } :text 7.18 - .data.init : { *(.data.init) } :text 7.19 + _sinittext = .; 7.20 + .init.text : { *(.init.text) } :text 7.21 + _einittext = .; 7.22 + .init.data : { *(.init.data) } :text 7.23 . = ALIGN(32); 7.24 __setup_start = .; 7.25 - .setup.init : { *(.setup.init) } :text 7.26 + .init.setup : { *(.init.setup) } :text 7.27 __setup_end = .; 7.28 __initcall_start = .; 7.29 - .initcall.init : { *(.initcall.init) } :text 7.30 + .initcall.init : { *(.initcall1.init) } :text 7.31 __initcall_end = .; 7.32 . = ALIGN(PAGE_SIZE); 7.33 __init_end = .; 7.34 @@ -80,8 +83,8 @@ SECTIONS 7.35 7.36 /* Sections to be discarded */ 7.37 /DISCARD/ : { 7.38 - *(.text.exit) 7.39 - *(.data.exit) 7.40 + *(.exit.text) 7.41 + *(.exit.data) 7.42 *(.exitcall.exit) 7.43 } 7.44
8.1 --- a/xen/arch/x86/x86_64/xen.lds.S Wed Jan 03 14:08:42 2007 +0000 8.2 +++ b/xen/arch/x86/x86_64/xen.lds.S Wed Jan 03 23:53:27 2007 +0000 8.3 @@ -17,7 +17,8 @@ PHDRS 8.4 SECTIONS 8.5 { 8.6 . = 0xFFFF830000100000; 8.7 - _text = .; /* Text and read-only data */ 8.8 + _start = .; 8.9 + _stext = .; /* Text and read-only data */ 8.10 .text : { 8.11 *(.text) 8.12 *(.fixup) 8.13 @@ -49,14 +50,16 @@ SECTIONS 8.14 8.15 . = ALIGN(4096); /* Init code and data */ 8.16 __init_begin = .; 8.17 - .text.init : { *(.text.init) } :text 8.18 - .data.init : { *(.data.init) } :text 8.19 + _sinittext = .; 8.20 + .init.text : { *(.init.text) } :text 8.21 + _einittext = .; 8.22 + .init.data : { *(.init.data) } :text 8.23 . = ALIGN(32); 8.24 __setup_start = .; 8.25 - .setup.init : { *(.setup.init) } :text 8.26 + .init.setup : { *(.init.setup) } :text 8.27 __setup_end = .; 8.28 __initcall_start = .; 8.29 - .initcall.init : { *(.initcall.init) } :text 8.30 + .initcall.init : { *(.initcall1.init) } :text 8.31 __initcall_end = .; 8.32 . = ALIGN(PAGE_SIZE); 8.33 __init_end = .; 8.34 @@ -78,8 +81,8 @@ SECTIONS 8.35 8.36 /* Sections to be discarded */ 8.37 /DISCARD/ : { 8.38 - *(.text.exit) 8.39 - *(.data.exit) 8.40 + *(.exit.text) 8.41 + *(.exit.data) 8.42 *(.exitcall.exit) 8.43 } 8.44
9.1 --- a/xen/common/kexec.c Wed Jan 03 14:08:42 2007 +0000 9.2 +++ b/xen/common/kexec.c Wed Jan 03 23:53:27 2007 +0000 9.3 @@ -150,12 +150,10 @@ static int kexec_get_reserve(xen_kexec_r 9.4 return 0; 9.5 } 9.6 9.7 -extern unsigned long _text; 9.8 - 9.9 static int kexec_get_xen(xen_kexec_range_t *range) 9.10 { 9.11 - range->start = virt_to_maddr(&_text); 9.12 - range->size = (unsigned long)&_end - (unsigned long)&_text; 9.13 + range->start = virt_to_maddr(_start); 9.14 + range->size = (unsigned long)_end - (unsigned long)_start; 9.15 return 0; 9.16 } 9.17
10.1 --- a/xen/common/symbols.c Wed Jan 03 14:08:42 2007 +0000 10.2 +++ b/xen/common/symbols.c Wed Jan 03 23:53:27 2007 +0000 10.3 @@ -12,6 +12,7 @@ 10.4 10.5 #include <xen/config.h> 10.6 #include <xen/symbols.h> 10.7 +#include <xen/kernel.h> 10.8 #include <xen/init.h> 10.9 #include <xen/lib.h> 10.10 #include <xen/string.h> 10.11 @@ -99,7 +100,7 @@ const char *symbols_lookup(unsigned long 10.12 namebuf[KSYM_NAME_LEN] = 0; 10.13 namebuf[0] = 0; 10.14 10.15 - if (!is_kernel_text(addr)) 10.16 + if (!is_kernel_text(addr) && !is_kernel_inittext(addr)) 10.17 return NULL; 10.18 10.19 /* do a binary search on the sorted symbols_addresses array */ 10.20 @@ -130,7 +131,8 @@ const char *symbols_lookup(unsigned long 10.21 10.22 /* if we found no next symbol, we use the end of the section */ 10.23 if (!symbol_end) 10.24 - symbol_end = kernel_text_end(); 10.25 + symbol_end = is_kernel_inittext(addr) ? 10.26 + (unsigned long)_einittext : (unsigned long)_etext; 10.27 10.28 *symbolsize = symbol_end - symbols_addresses[low]; 10.29 *offset = addr - symbols_addresses[low];
11.1 --- a/xen/include/asm-ia64/init.h Wed Jan 03 14:08:42 2007 +0000 11.2 +++ b/xen/include/asm-ia64/init.h Wed Jan 03 23:53:27 2007 +0000 11.3 @@ -1,29 +1,4 @@ 11.4 #ifndef _XEN_ASM_INIT_H 11.5 #define _XEN_ASM_INIT_H 11.6 11.7 -/* 11.8 - * Mark functions and data as being only used at initialization 11.9 - * or exit time. 11.10 - */ 11.11 -#define __init \ 11.12 - __attribute__ ((__section__ (".init.text"))) 11.13 -#define __exit \ 11.14 - __attribute_used__ __attribute__ ((__section__(".text.exit"))) 11.15 -#define __initdata \ 11.16 - __attribute__ ((__section__ (".init.data"))) 11.17 -#define __exitdata \ 11.18 - __attribute_used__ __attribute__ ((__section__ (".data.exit"))) 11.19 -#define __initsetup \ 11.20 - __attribute_used__ __attribute__ ((__section__ (".init.setup"))) 11.21 -#define __init_call \ 11.22 - __attribute_used__ __attribute__ ((__section__ (".initcall1.init"))) 11.23 -#define __exit_call \ 11.24 - __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) 11.25 - 11.26 -/* For assembly routines 11.27 -#define __INIT .section ".text.init","ax" 11.28 -#define __FINIT .previous 11.29 -#define __INITDATA .section ".data.init","aw" 11.30 -*/ 11.31 - 11.32 #endif /* _XEN_ASM_INIT_H */
12.1 --- a/xen/include/asm-powerpc/init.h Wed Jan 03 14:08:42 2007 +0000 12.2 +++ b/xen/include/asm-powerpc/init.h Wed Jan 03 23:53:27 2007 +0000 12.3 @@ -21,25 +21,6 @@ 12.4 #ifndef _XEN_ASM_INIT_H 12.5 #define _XEN_ASM_INIT_H 12.6 12.7 -/* 12.8 - * Mark functions and data as being only used at initialization 12.9 - * or exit time. 12.10 - */ 12.11 -#define __init \ 12.12 - __attribute__ ((__section__ (".init.text"))) 12.13 -#define __exit \ 12.14 - __attribute_used__ __attribute__ ((__section__(".text.exit"))) 12.15 -#define __initdata \ 12.16 - __attribute__ ((__section__ (".init.data"))) 12.17 -#define __exitdata \ 12.18 - __attribute_used__ __attribute__ ((__section__ (".data.exit"))) 12.19 -#define __initsetup \ 12.20 - __attribute_used__ __attribute__ ((__section__ (".setup.init"))) 12.21 -#define __init_call \ 12.22 - __attribute_used__ __attribute__ ((__section__ (".initcall.init"))) 12.23 -#define __exit_call \ 12.24 - __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) 12.25 - 12.26 struct cpu_user_regs; 12.27 typedef void (*hcall_handler_t)(struct cpu_user_regs *regs); 12.28
13.1 --- a/xen/include/asm-x86/config.h Wed Jan 03 14:08:42 2007 +0000 13.2 +++ b/xen/include/asm-x86/config.h Wed Jan 03 23:53:27 2007 +0000 13.3 @@ -84,10 +84,6 @@ 13.4 13.5 #define CONFIG_DMA_BITSIZE 30 13.6 13.7 -#ifndef __ASSEMBLY__ 13.8 -extern unsigned long _end; /* standard ELF symbol */ 13.9 -#endif /* __ASSEMBLY__ */ 13.10 - 13.11 #if defined(__x86_64__) 13.12 13.13 #define CONFIG_X86_64 1
14.1 --- a/xen/include/asm-x86/init.h Wed Jan 03 14:08:42 2007 +0000 14.2 +++ b/xen/include/asm-x86/init.h Wed Jan 03 23:53:27 2007 +0000 14.3 @@ -1,29 +1,4 @@ 14.4 #ifndef _XEN_ASM_INIT_H 14.5 #define _XEN_ASM_INIT_H 14.6 14.7 -/* 14.8 - * Mark functions and data as being only used at initialization 14.9 - * or exit time. 14.10 - */ 14.11 -#define __init \ 14.12 - __attribute__ ((__section__ (".init.text"))) 14.13 -#define __exit \ 14.14 - __attribute_used__ __attribute__ ((__section__(".text.exit"))) 14.15 -#define __initdata \ 14.16 - __attribute__ ((__section__ (".init.data"))) 14.17 -#define __exitdata \ 14.18 - __attribute_used__ __attribute__ ((__section__ (".data.exit"))) 14.19 -#define __initsetup \ 14.20 - __attribute_used__ __attribute__ ((__section__ (".setup.init"))) 14.21 -#define __init_call \ 14.22 - __attribute_used__ __attribute__ ((__section__ (".initcall.init"))) 14.23 -#define __exit_call \ 14.24 - __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) 14.25 - 14.26 -/* For assembly routines 14.27 -#define __INIT .section ".text.init","ax" 14.28 -#define __FINIT .previous 14.29 -#define __INITDATA .section ".data.init","aw" 14.30 -*/ 14.31 - 14.32 #endif /* _XEN_ASM_INIT_H */
15.1 --- a/xen/include/xen/init.h Wed Jan 03 14:08:42 2007 +0000 15.2 +++ b/xen/include/xen/init.h Wed Jan 03 23:53:27 2007 +0000 15.3 @@ -4,6 +4,25 @@ 15.4 #include <xen/config.h> 15.5 #include <asm/init.h> 15.6 15.7 +/* 15.8 + * Mark functions and data as being only used at initialization 15.9 + * or exit time. 15.10 + */ 15.11 +#define __init \ 15.12 + __attribute__ ((__section__ (".init.text"))) 15.13 +#define __exit \ 15.14 + __attribute_used__ __attribute__ ((__section__(".exit.text"))) 15.15 +#define __initdata \ 15.16 + __attribute__ ((__section__ (".init.data"))) 15.17 +#define __exitdata \ 15.18 + __attribute_used__ __attribute__ ((__section__ (".exit.data"))) 15.19 +#define __initsetup \ 15.20 + __attribute_used__ __attribute__ ((__section__ (".init.setup"))) 15.21 +#define __init_call \ 15.22 + __attribute_used__ __attribute__ ((__section__ (".initcall1.init"))) 15.23 +#define __exit_call \ 15.24 + __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) 15.25 + 15.26 /* These macros are used to mark some functions or 15.27 * initialized data (doesn't apply to uninitialized data) 15.28 * as `initialization' functions. The kernel can take this
16.1 --- a/xen/include/xen/kernel.h Wed Jan 03 14:08:42 2007 +0000 16.2 +++ b/xen/include/xen/kernel.h Wed Jan 03 23:53:27 2007 +0000 16.3 @@ -56,6 +56,23 @@ 16.4 1; \ 16.5 }) 16.6 16.7 +extern char _start[], _end[]; 16.8 +#define is_kernel(p) ({ \ 16.9 + char *__p = (char *)(unsigned long)(p); \ 16.10 + (__p >= _start) && (__p <= _end); \ 16.11 +}) 16.12 + 16.13 +extern char _stext[], _etext[]; 16.14 +#define is_kernel_text(p) ({ \ 16.15 + char *__p = (char *)(unsigned long)(p); \ 16.16 + (__p >= _stext) && (__p <= _etext); \ 16.17 +}) 16.18 + 16.19 +extern char _sinittext[], _einittext[]; 16.20 +#define is_kernel_inittext(p) ({ \ 16.21 + char *__p = (char *)(unsigned long)(p); \ 16.22 + (__p >= _sinittext) && (__p <= _einittext); \ 16.23 +}) 16.24 16.25 #endif /* _LINUX_KERNEL_H */ 16.26
17.1 --- a/xen/include/xen/symbols.h Wed Jan 03 14:08:42 2007 +0000 17.2 +++ b/xen/include/xen/symbols.h Wed Jan 03 23:53:27 2007 +0000 17.3 @@ -6,9 +6,6 @@ 17.4 17.5 #define KSYM_NAME_LEN 127 17.6 17.7 -extern int is_kernel_text(unsigned long addr); 17.8 -extern unsigned long kernel_text_end(void); 17.9 - 17.10 /* Lookup an address. */ 17.11 const char *symbols_lookup(unsigned long addr, 17.12 unsigned long *symbolsize, 17.13 @@ -16,7 +13,7 @@ const char *symbols_lookup(unsigned long 17.14 char *namebuf); 17.15 17.16 /* Replace "%s" in format with address, if found */ 17.17 -extern void __print_symbol(const char *fmt, unsigned long address); 17.18 +void __print_symbol(const char *fmt, unsigned long address); 17.19 17.20 /* This macro allows us to keep printk typechecking */ 17.21 static void __check_printsym_format(const char *fmt, ...)
18.1 --- a/xen/tools/symbols.c Wed Jan 03 14:08:42 2007 +0000 18.2 +++ b/xen/tools/symbols.c Wed Jan 03 23:53:27 2007 +0000 18.3 @@ -5,7 +5,7 @@ 18.4 * This software may be used and distributed according to the terms 18.5 * of the GNU General Public License, incorporated herein by reference. 18.6 * 18.7 - * Usage: nm -n <object-file> | scripts/symbols [--all-symbols] > symbols.S 18.8 + * Usage: nm -n vmlinux | scripts/symbols [--all-symbols] > symbols.S 18.9 * 18.10 * ChangeLog: 18.11 * 18.12 @@ -24,75 +24,37 @@ 18.13 * 18.14 */ 18.15 18.16 +#define _GNU_SOURCE 18.17 + 18.18 #include <stdio.h> 18.19 #include <stdlib.h> 18.20 #include <string.h> 18.21 #include <ctype.h> 18.22 18.23 -/* maximum token length used. It doesn't pay to increase it a lot, because 18.24 - * very long substrings probably don't repeat themselves too often. */ 18.25 -#define MAX_TOK_SIZE 11 18.26 #define KSYM_NAME_LEN 127 18.27 18.28 -/* we use only a subset of the complete symbol table to gather the token count, 18.29 - * to speed up compression, at the expense of a little compression ratio */ 18.30 -#define WORKING_SET 1024 18.31 - 18.32 -/* first find the best token only on the list of tokens that would profit more 18.33 - * than GOOD_BAD_THRESHOLD. Only if this list is empty go to the "bad" list. 18.34 - * Increasing this value will put less tokens on the "good" list, so the search 18.35 - * is faster. However, if the good list runs out of tokens, we must painfully 18.36 - * search the bad list. */ 18.37 -#define GOOD_BAD_THRESHOLD 10 18.38 - 18.39 -/* token hash parameters */ 18.40 -#define HASH_BITS 18 18.41 -#define HASH_TABLE_SIZE (1 << HASH_BITS) 18.42 -#define HASH_MASK (HASH_TABLE_SIZE - 1) 18.43 -#define HASH_BASE_OFFSET 2166136261U 18.44 -#define HASH_FOLD(a) ((a)&(HASH_MASK)) 18.45 - 18.46 -/* flags to mark symbols */ 18.47 -#define SYM_FLAG_VALID 1 18.48 -#define SYM_FLAG_SAMPLED 2 18.49 18.50 struct sym_entry { 18.51 unsigned long long addr; 18.52 - char type; 18.53 - unsigned char flags; 18.54 - unsigned char len; 18.55 + unsigned int len; 18.56 unsigned char *sym; 18.57 }; 18.58 18.59 18.60 static struct sym_entry *table; 18.61 -static int size, cnt; 18.62 -static unsigned long long _stext, _etext; 18.63 +static unsigned int table_size, table_cnt; 18.64 +static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext; 18.65 static int all_symbols = 0; 18.66 static char symbol_prefix_char = '\0'; 18.67 18.68 -struct token { 18.69 - unsigned char data[MAX_TOK_SIZE]; 18.70 - unsigned char len; 18.71 - /* profit: the number of bytes that could be saved by inserting this 18.72 - * token into the table */ 18.73 - int profit; 18.74 - struct token *next; /* next token on the hash list */ 18.75 - struct token *right; /* next token on the good/bad list */ 18.76 - struct token *left; /* previous token on the good/bad list */ 18.77 - struct token *smaller; /* token that is less one letter than this one */ 18.78 - }; 18.79 - 18.80 -struct token bad_head, good_head; 18.81 -struct token *hash_table[HASH_TABLE_SIZE]; 18.82 +int token_profit[0x10000]; 18.83 18.84 /* the table that holds the result of the compression */ 18.85 -unsigned char best_table[256][MAX_TOK_SIZE+1]; 18.86 +unsigned char best_table[256][2]; 18.87 unsigned char best_table_len[256]; 18.88 18.89 18.90 -static void 18.91 -usage(void) 18.92 +static void usage(void) 18.93 { 18.94 fprintf(stderr, "Usage: symbols [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n"); 18.95 exit(1); 18.96 @@ -102,21 +64,19 @@ usage(void) 18.97 * This ignores the intensely annoying "mapping symbols" found 18.98 * in ARM ELF files: $a, $t and $d. 18.99 */ 18.100 -static inline int 18.101 -is_arm_mapping_symbol(const char *str) 18.102 +static inline int is_arm_mapping_symbol(const char *str) 18.103 { 18.104 return str[0] == '$' && strchr("atd", str[1]) 18.105 && (str[2] == '\0' || str[2] == '.'); 18.106 } 18.107 18.108 -static int 18.109 -read_symbol(FILE *in, struct sym_entry *s) 18.110 +static int read_symbol(FILE *in, struct sym_entry *s) 18.111 { 18.112 char str[500]; 18.113 - char *sym; 18.114 + char *sym, stype; 18.115 int rc; 18.116 18.117 - rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str); 18.118 + rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str); 18.119 if (rc != 3) { 18.120 if (rc != EOF) { 18.121 /* skip line */ 18.122 @@ -135,7 +95,15 @@ read_symbol(FILE *in, struct sym_entry * 18.123 _stext = s->addr; 18.124 else if (strcmp(sym, "_etext") == 0) 18.125 _etext = s->addr; 18.126 - else if (toupper(s->type) == 'A') 18.127 + else if (strcmp(sym, "_sinittext") == 0) 18.128 + _sinittext = s->addr; 18.129 + else if (strcmp(sym, "_einittext") == 0) 18.130 + _einittext = s->addr; 18.131 + else if (strcmp(sym, "_sextratext") == 0) 18.132 + _sextratext = s->addr; 18.133 + else if (strcmp(sym, "_eextratext") == 0) 18.134 + _eextratext = s->addr; 18.135 + else if (toupper(stype) == 'A') 18.136 { 18.137 /* Keep these useful absolute symbols */ 18.138 if (strcmp(sym, "__kernel_syscall_via_break") && 18.139 @@ -145,22 +113,24 @@ read_symbol(FILE *in, struct sym_entry * 18.140 return -1; 18.141 18.142 } 18.143 - else if (toupper(s->type) == 'U' || 18.144 + else if (toupper(stype) == 'U' || 18.145 is_arm_mapping_symbol(sym)) 18.146 return -1; 18.147 + /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */ 18.148 + else if (str[0] == '$') 18.149 + return -1; 18.150 18.151 /* include the type field in the symbol name, so that it gets 18.152 * compressed together */ 18.153 s->len = strlen(str) + 1; 18.154 - s->sym = (unsigned char *) malloc(s->len + 1); 18.155 + s->sym = malloc(s->len + 1); 18.156 strcpy((char *)s->sym + 1, str); 18.157 - s->sym[0] = s->type; 18.158 + s->sym[0] = stype; 18.159 18.160 return 0; 18.161 } 18.162 18.163 -static int 18.164 -symbol_valid(struct sym_entry *s) 18.165 +static int symbol_valid(struct sym_entry *s) 18.166 { 18.167 /* Symbols which vary between passes. Passes 1 and 2 must have 18.168 * identical symbol lists. The symbols_* symbols below are only added 18.169 @@ -189,7 +159,9 @@ symbol_valid(struct sym_entry *s) 18.170 /* if --all-symbols is not specified, then symbols outside the text 18.171 * and inittext sections are discarded */ 18.172 if (!all_symbols) { 18.173 - if (s->addr < _stext || s->addr > _etext) 18.174 + if ((s->addr < _stext || s->addr > _etext) 18.175 + && (s->addr < _sinittext || s->addr > _einittext) 18.176 + && (s->addr < _sextratext || s->addr > _eextratext)) 18.177 return 0; 18.178 /* Corner case. Discard any symbols with the same value as 18.179 * _etext _einittext or _eextratext; they can move between pass 18.180 @@ -197,7 +169,9 @@ symbol_valid(struct sym_entry *s) 18.181 * move then they may get dropped in pass 2, which breaks the 18.182 * symbols rules. 18.183 */ 18.184 - if (s->addr == _etext && strcmp((char *)s->sym + offset, "_etext")) 18.185 + if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) || 18.186 + (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) || 18.187 + (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext"))) 18.188 return 0; 18.189 } 18.190 18.191 @@ -212,20 +186,19 @@ symbol_valid(struct sym_entry *s) 18.192 return 1; 18.193 } 18.194 18.195 -static void 18.196 -read_map(FILE *in) 18.197 +static void read_map(FILE *in) 18.198 { 18.199 while (!feof(in)) { 18.200 - if (cnt >= size) { 18.201 - size += 10000; 18.202 - table = realloc(table, sizeof(*table) * size); 18.203 + if (table_cnt >= table_size) { 18.204 + table_size += 10000; 18.205 + table = realloc(table, sizeof(*table) * table_size); 18.206 if (!table) { 18.207 fprintf(stderr, "out of memory\n"); 18.208 exit (1); 18.209 } 18.210 } 18.211 - if (read_symbol(in, &table[cnt]) == 0) 18.212 - cnt++; 18.213 + if (read_symbol(in, &table[table_cnt]) == 0) 18.214 + table_cnt++; 18.215 } 18.216 } 18.217 18.218 @@ -269,10 +242,9 @@ static int expand_symbol(unsigned char * 18.219 return total; 18.220 } 18.221 18.222 -static void 18.223 -write_src(void) 18.224 +static void write_src(void) 18.225 { 18.226 - int i, k, off, valid; 18.227 + unsigned int i, k, off; 18.228 unsigned int best_idx[256]; 18.229 unsigned int *markers; 18.230 char buf[KSYM_NAME_LEN+1]; 18.231 @@ -289,33 +261,24 @@ write_src(void) 18.232 printf(".data\n"); 18.233 18.234 output_label("symbols_addresses"); 18.235 - valid = 0; 18.236 - for (i = 0; i < cnt; i++) { 18.237 - if (table[i].flags & SYM_FLAG_VALID) { 18.238 - printf("\tPTR\t%#llx\n", table[i].addr); 18.239 - valid++; 18.240 - } 18.241 + for (i = 0; i < table_cnt; i++) { 18.242 + printf("\tPTR\t%#llx\n", table[i].addr); 18.243 } 18.244 printf("\n"); 18.245 18.246 output_label("symbols_num_syms"); 18.247 - printf("\tPTR\t%d\n", valid); 18.248 + printf("\tPTR\t%d\n", table_cnt); 18.249 printf("\n"); 18.250 18.251 /* table of offset markers, that give the offset in the compressed stream 18.252 * every 256 symbols */ 18.253 - markers = (unsigned int *) malloc(sizeof(unsigned int)*((valid + 255) / 256)); 18.254 + markers = (unsigned int *) malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256)); 18.255 18.256 output_label("symbols_names"); 18.257 - valid = 0; 18.258 off = 0; 18.259 - for (i = 0; i < cnt; i++) { 18.260 - 18.261 - if (!(table[i].flags & SYM_FLAG_VALID)) 18.262 - continue; 18.263 - 18.264 - if ((valid & 0xFF) == 0) 18.265 - markers[valid >> 8] = off; 18.266 + for (i = 0; i < table_cnt; i++) { 18.267 + if ((i & 0xFF) == 0) 18.268 + markers[i >> 8] = off; 18.269 18.270 printf("\t.byte 0x%02x", table[i].len); 18.271 for (k = 0; k < table[i].len; k++) 18.272 @@ -323,12 +286,11 @@ write_src(void) 18.273 printf("\n"); 18.274 18.275 off += table[i].len + 1; 18.276 - valid++; 18.277 } 18.278 printf("\n"); 18.279 18.280 output_label("symbols_markers"); 18.281 - for (i = 0; i < ((valid + 255) >> 8); i++) 18.282 + for (i = 0; i < ((table_cnt + 255) >> 8); i++) 18.283 printf("\tPTR\t%d\n", markers[i]); 18.284 printf("\n"); 18.285 18.286 @@ -338,7 +300,7 @@ write_src(void) 18.287 off = 0; 18.288 for (i = 0; i < 256; i++) { 18.289 best_idx[i] = off; 18.290 - expand_symbol(best_table[i],best_table_len[i],buf); 18.291 + expand_symbol(best_table[i], best_table_len[i], buf); 18.292 printf("\t.asciz\t\"%s\"\n", buf); 18.293 off += strlen(buf) + 1; 18.294 } 18.295 @@ -353,153 +315,13 @@ write_src(void) 18.296 18.297 /* table lookup compression functions */ 18.298 18.299 -static inline unsigned int rehash_token(unsigned int hash, unsigned char data) 18.300 -{ 18.301 - return ((hash * 16777619) ^ data); 18.302 -} 18.303 - 18.304 -static unsigned int hash_token(unsigned char *data, int len) 18.305 -{ 18.306 - unsigned int hash=HASH_BASE_OFFSET; 18.307 - int i; 18.308 - 18.309 - for (i = 0; i < len; i++) 18.310 - hash = rehash_token(hash, data[i]); 18.311 - 18.312 - return HASH_FOLD(hash); 18.313 -} 18.314 - 18.315 -/* find a token given its data and hash value */ 18.316 -static struct token *find_token_hash(unsigned char *data, int len, unsigned int hash) 18.317 -{ 18.318 - struct token *ptr; 18.319 - 18.320 - ptr = hash_table[hash]; 18.321 - 18.322 - while (ptr) { 18.323 - if ((ptr->len == len) && (memcmp(ptr->data, data, len) == 0)) 18.324 - return ptr; 18.325 - ptr=ptr->next; 18.326 - } 18.327 - 18.328 - return NULL; 18.329 -} 18.330 - 18.331 -static inline void insert_token_in_group(struct token *head, struct token *ptr) 18.332 -{ 18.333 - ptr->right = head->right; 18.334 - ptr->right->left = ptr; 18.335 - head->right = ptr; 18.336 - ptr->left = head; 18.337 -} 18.338 - 18.339 -static inline void remove_token_from_group(struct token *ptr) 18.340 -{ 18.341 - ptr->left->right = ptr->right; 18.342 - ptr->right->left = ptr->left; 18.343 -} 18.344 - 18.345 - 18.346 -/* build the counts for all the tokens that start with "data", and have lenghts 18.347 - * from 2 to "len" */ 18.348 -static void learn_token(unsigned char *data, int len) 18.349 -{ 18.350 - struct token *ptr,*last_ptr; 18.351 - int i, newprofit; 18.352 - unsigned int hash = HASH_BASE_OFFSET; 18.353 - unsigned int hashes[MAX_TOK_SIZE + 1]; 18.354 - 18.355 - if (len > MAX_TOK_SIZE) 18.356 - len = MAX_TOK_SIZE; 18.357 - 18.358 - /* calculate and store the hash values for all the sub-tokens */ 18.359 - hash = rehash_token(hash, data[0]); 18.360 - for (i = 2; i <= len; i++) { 18.361 - hash = rehash_token(hash, data[i-1]); 18.362 - hashes[i] = HASH_FOLD(hash); 18.363 - } 18.364 - 18.365 - last_ptr = NULL; 18.366 - ptr = NULL; 18.367 - 18.368 - for (i = len; i >= 2; i--) { 18.369 - hash = hashes[i]; 18.370 - 18.371 - if (!ptr) ptr = find_token_hash(data, i, hash); 18.372 - 18.373 - if (!ptr) { 18.374 - /* create a new token entry */ 18.375 - ptr = (struct token *) malloc(sizeof(*ptr)); 18.376 - 18.377 - memcpy(ptr->data, data, i); 18.378 - ptr->len = i; 18.379 - 18.380 - /* when we create an entry, it's profit is 0 because 18.381 - * we also take into account the size of the token on 18.382 - * the compressed table. We then subtract GOOD_BAD_THRESHOLD 18.383 - * so that the test to see if this token belongs to 18.384 - * the good or bad list, is a comparison to zero */ 18.385 - ptr->profit = -GOOD_BAD_THRESHOLD; 18.386 - 18.387 - ptr->next = hash_table[hash]; 18.388 - hash_table[hash] = ptr; 18.389 - 18.390 - insert_token_in_group(&bad_head, ptr); 18.391 - 18.392 - ptr->smaller = NULL; 18.393 - } else { 18.394 - newprofit = ptr->profit + (ptr->len - 1); 18.395 - /* check to see if this token needs to be moved to a 18.396 - * different list */ 18.397 - if((ptr->profit < 0) && (newprofit >= 0)) { 18.398 - remove_token_from_group(ptr); 18.399 - insert_token_in_group(&good_head,ptr); 18.400 - } 18.401 - ptr->profit = newprofit; 18.402 - } 18.403 - 18.404 - if (last_ptr) last_ptr->smaller = ptr; 18.405 - last_ptr = ptr; 18.406 - 18.407 - ptr = ptr->smaller; 18.408 - } 18.409 -} 18.410 - 18.411 -/* decrease the counts for all the tokens that start with "data", and have lenghts 18.412 - * from 2 to "len". This function is much simpler than learn_token because we have 18.413 - * more guarantees (tho tokens exist, the ->smaller pointer is set, etc.) 18.414 - * The two separate functions exist only because of compression performance */ 18.415 -static void forget_token(unsigned char *data, int len) 18.416 -{ 18.417 - struct token *ptr; 18.418 - int i, newprofit; 18.419 - unsigned int hash=0; 18.420 - 18.421 - if (len > MAX_TOK_SIZE) len = MAX_TOK_SIZE; 18.422 - 18.423 - hash = hash_token(data, len); 18.424 - ptr = find_token_hash(data, len, hash); 18.425 - 18.426 - for (i = len; i >= 2; i--) { 18.427 - 18.428 - newprofit = ptr->profit - (ptr->len - 1); 18.429 - if ((ptr->profit >= 0) && (newprofit < 0)) { 18.430 - remove_token_from_group(ptr); 18.431 - insert_token_in_group(&bad_head, ptr); 18.432 - } 18.433 - ptr->profit=newprofit; 18.434 - 18.435 - ptr=ptr->smaller; 18.436 - } 18.437 -} 18.438 - 18.439 /* count all the possible tokens in a symbol */ 18.440 static void learn_symbol(unsigned char *symbol, int len) 18.441 { 18.442 int i; 18.443 18.444 for (i = 0; i < len - 1; i++) 18.445 - learn_token(symbol + i, len - i); 18.446 + token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++; 18.447 } 18.448 18.449 /* decrease the count for all the possible tokens in a symbol */ 18.450 @@ -508,117 +330,90 @@ static void forget_symbol(unsigned char 18.451 int i; 18.452 18.453 for (i = 0; i < len - 1; i++) 18.454 - forget_token(symbol + i, len - i); 18.455 + token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--; 18.456 } 18.457 18.458 -/* set all the symbol flags and do the initial token count */ 18.459 +/* remove all the invalid symbols from the table and do the initial token count */ 18.460 static void build_initial_tok_table(void) 18.461 { 18.462 - int i, use_it, valid; 18.463 + unsigned int i, pos; 18.464 18.465 - valid = 0; 18.466 - for (i = 0; i < cnt; i++) { 18.467 - table[i].flags = 0; 18.468 + pos = 0; 18.469 + for (i = 0; i < table_cnt; i++) { 18.470 if ( symbol_valid(&table[i]) ) { 18.471 - table[i].flags |= SYM_FLAG_VALID; 18.472 - valid++; 18.473 + if (pos != i) 18.474 + table[pos] = table[i]; 18.475 + learn_symbol(table[pos].sym, table[pos].len); 18.476 + pos++; 18.477 } 18.478 } 18.479 - 18.480 - use_it = 0; 18.481 - for (i = 0; i < cnt; i++) { 18.482 - 18.483 - /* subsample the available symbols. This method is almost like 18.484 - * a Bresenham's algorithm to get uniformly distributed samples 18.485 - * across the symbol table */ 18.486 - if (table[i].flags & SYM_FLAG_VALID) { 18.487 - 18.488 - use_it += WORKING_SET; 18.489 - 18.490 - if (use_it >= valid) { 18.491 - table[i].flags |= SYM_FLAG_SAMPLED; 18.492 - use_it -= valid; 18.493 - } 18.494 - } 18.495 - if (table[i].flags & SYM_FLAG_SAMPLED) 18.496 - learn_symbol(table[i].sym, table[i].len); 18.497 - } 18.498 + table_cnt = pos; 18.499 } 18.500 18.501 /* replace a given token in all the valid symbols. Use the sampled symbols 18.502 * to update the counts */ 18.503 -static void compress_symbols(unsigned char *str, int tlen, int idx) 18.504 +static void compress_symbols(unsigned char *str, int idx) 18.505 { 18.506 - int i, len, learn, size; 18.507 - unsigned char *p; 18.508 + unsigned int i, len, size; 18.509 + unsigned char *p1, *p2; 18.510 18.511 - for (i = 0; i < cnt; i++) { 18.512 - 18.513 - if (!(table[i].flags & SYM_FLAG_VALID)) continue; 18.514 + for (i = 0; i < table_cnt; i++) { 18.515 18.516 len = table[i].len; 18.517 - learn = 0; 18.518 - p = table[i].sym; 18.519 + p1 = table[i].sym; 18.520 + 18.521 + /* find the token on the symbol */ 18.522 + p2 = memmem(p1, len, str, 2); 18.523 + if (!p2) continue; 18.524 + 18.525 + /* decrease the counts for this symbol's tokens */ 18.526 + forget_symbol(table[i].sym, len); 18.527 + 18.528 + size = len; 18.529 18.530 do { 18.531 - /* find the token on the symbol */ 18.532 - p = (unsigned char *) strstr((char *) p, (char *) str); 18.533 - if (!p) break; 18.534 + *p2 = idx; 18.535 + p2++; 18.536 + size -= (p2 - p1); 18.537 + memmove(p2, p2 + 1, size); 18.538 + p1 = p2; 18.539 + len--; 18.540 18.541 - if (!learn) { 18.542 - /* if this symbol was used to count, decrease it */ 18.543 - if (table[i].flags & SYM_FLAG_SAMPLED) 18.544 - forget_symbol(table[i].sym, len); 18.545 - learn = 1; 18.546 - } 18.547 + if (size < 2) break; 18.548 18.549 - *p = idx; 18.550 - size = (len - (p - table[i].sym)) - tlen + 1; 18.551 - memmove(p + 1, p + tlen, size); 18.552 - p++; 18.553 - len -= tlen - 1; 18.554 + /* find the token on the symbol */ 18.555 + p2 = memmem(p1, size, str, 2); 18.556 + 18.557 + } while (p2); 18.558 18.559 - } while (size >= tlen); 18.560 + table[i].len = len; 18.561 18.562 - if(learn) { 18.563 - table[i].len = len; 18.564 - /* if this symbol was used to count, learn it again */ 18.565 - if(table[i].flags & SYM_FLAG_SAMPLED) 18.566 - learn_symbol(table[i].sym, len); 18.567 - } 18.568 + /* increase the counts for this symbol's new tokens */ 18.569 + learn_symbol(table[i].sym, len); 18.570 } 18.571 } 18.572 18.573 /* search the token with the maximum profit */ 18.574 -static struct token *find_best_token(void) 18.575 +static int find_best_token(void) 18.576 { 18.577 - struct token *ptr,*best,*head; 18.578 - int bestprofit; 18.579 + int i, best, bestprofit; 18.580 18.581 bestprofit=-10000; 18.582 - 18.583 - /* failsafe: if the "good" list is empty search from the "bad" list */ 18.584 - if(good_head.right == &good_head) head = &bad_head; 18.585 - else head = &good_head; 18.586 + best = 0; 18.587 18.588 - ptr = head->right; 18.589 - best = NULL; 18.590 - while (ptr != head) { 18.591 - if (ptr->profit > bestprofit) { 18.592 - bestprofit = ptr->profit; 18.593 - best = ptr; 18.594 + for (i = 0; i < 0x10000; i++) { 18.595 + if (token_profit[i] > bestprofit) { 18.596 + best = i; 18.597 + bestprofit = token_profit[i]; 18.598 } 18.599 - ptr = ptr->right; 18.600 } 18.601 - 18.602 return best; 18.603 } 18.604 18.605 /* this is the core of the algorithm: calculate the "best" table */ 18.606 static void optimize_result(void) 18.607 { 18.608 - struct token *best; 18.609 - int i; 18.610 + int i, best; 18.611 18.612 /* using the '\0' symbol last allows compress_symbols to use standard 18.613 * fast string functions */ 18.614 @@ -632,14 +427,12 @@ static void optimize_result(void) 18.615 best = find_best_token(); 18.616 18.617 /* place it in the "best" table */ 18.618 - best_table_len[i] = best->len; 18.619 - memcpy(best_table[i], best->data, best_table_len[i]); 18.620 - /* zero terminate the token so that we can use strstr 18.621 - in compress_symbols */ 18.622 - best_table[i][best_table_len[i]]='\0'; 18.623 + best_table_len[i] = 2; 18.624 + best_table[i][0] = best & 0xFF; 18.625 + best_table[i][1] = (best >> 8) & 0xFF; 18.626 18.627 /* replace this token in all the valid symbols */ 18.628 - compress_symbols(best_table[i], best_table_len[i], i); 18.629 + compress_symbols(best_table[i], i); 18.630 } 18.631 } 18.632 } 18.633 @@ -647,39 +440,28 @@ static void optimize_result(void) 18.634 /* start by placing the symbols that are actually used on the table */ 18.635 static void insert_real_symbols_in_table(void) 18.636 { 18.637 - int i, j, c; 18.638 + unsigned int i, j, c; 18.639 18.640 memset(best_table, 0, sizeof(best_table)); 18.641 memset(best_table_len, 0, sizeof(best_table_len)); 18.642 18.643 - for (i = 0; i < cnt; i++) { 18.644 - if (table[i].flags & SYM_FLAG_VALID) { 18.645 - for (j = 0; j < table[i].len; j++) { 18.646 - c = table[i].sym[j]; 18.647 - best_table[c][0]=c; 18.648 - best_table_len[c]=1; 18.649 - } 18.650 + for (i = 0; i < table_cnt; i++) { 18.651 + for (j = 0; j < table[i].len; j++) { 18.652 + c = table[i].sym[j]; 18.653 + best_table[c][0]=c; 18.654 + best_table_len[c]=1; 18.655 } 18.656 } 18.657 } 18.658 18.659 static void optimize_token_table(void) 18.660 { 18.661 - memset(hash_table, 0, sizeof(hash_table)); 18.662 - 18.663 - good_head.left = &good_head; 18.664 - good_head.right = &good_head; 18.665 - 18.666 - bad_head.left = &bad_head; 18.667 - bad_head.right = &bad_head; 18.668 - 18.669 build_initial_tok_table(); 18.670 18.671 insert_real_symbols_in_table(); 18.672 18.673 /* When valid symbol is not registered, exit to error */ 18.674 - if (good_head.left == good_head.right && 18.675 - bad_head.left == bad_head.right) { 18.676 + if (!table_cnt) { 18.677 fprintf(stderr, "No valid symbol.\n"); 18.678 exit(1); 18.679 } 18.680 @@ -688,8 +470,7 @@ static void optimize_token_table(void) 18.681 } 18.682 18.683 18.684 -int 18.685 -main(int argc, char **argv) 18.686 +int main(int argc, char **argv) 18.687 { 18.688 if (argc >= 2) { 18.689 int i;