As we know, assembly files(.S) would get preprocessing before assembling, but I found that after preprocessing there may be struct/function prototypes in the resulting assembly files, How would the gnu as deal with these prototypes? Just ignored it?
For example, the following command:
gcc -E -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
and the resulting assembly file (tmp.result) is:
# 1 "arch/x86/boot/copy.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "arch/x86/boot/copy.S"
# 11 "arch/x86/boot/copy.S"
# 1 "include/linux/linkage.h" 1
# 1 "include/linux/compiler.h" 1
# 5 "include/linux/linkage.h" 2
# 1 "include/linux/stringify.h" 1
# 6 "include/linux/linkage.h" 2
# 1 "include/linux/export.h" 1
# 26 "include/linux/export.h"
struct kernel_symbol
{
unsigned long value;
const char *name;
};
# 7 "include/linux/linkage.h" 2
# 1 "arch/x86/include/asm/linkage.h" 1
# 8 "include/linux/linkage.h" 2
# 12 "arch/x86/boot/copy.S" 2
.code16
.text
GLOBAL(memcpy)
pushw %si
pushw %di
movw %ax, %di
movw %dx, %si
pushw %cx
shrw $2, %cx
rep; movsl
popw %cx
andw $3, %cx
rep; movsb
popw %di
popw %si
retl
ENDPROC(memcpy)
but when trying to assemble this file:
as -o tmp.o tmp.result
produce following error:
include/linux/export.h: Assembler messages:
include/linux/export.h:26: Error: no such instruction: `struct kernel_symbol'
include/linux/export.h:27: Error: junk at end of line, first unrecognized character is `{'
include/linux/export.h:28: Error: no such instruction: `unsigned long value'
include/linux/export.h:29: Error: no such instruction: `const char *name'
include/linux/export.h:30: Error: junk at end of line, first unrecognized character is `}'
arch/x86/boot/copy.S:20: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:34: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:36: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:49: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:51: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:58: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:60: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:67: Error: invalid character '(' in mnemonic
It seems that the assembler can not deal with the struct in tmp.result. How can Linux source code(.S) get through the assembling?
as
cannot process struct
and function prototypes - they are just for the C compiler, and get "pulled in" in your preprocessing by mistake. In facts, if you look at the header that provides that struct
definition, you'll see:
#ifndef __ASSEMBLY__
struct kernel_symbol
{
unsigned long value;
const char *name;
};
So, the header above is thought to be included both from assembly and from C, but you didn't define __ASSEMBLY__
to tell it that you are including it into an assembly file.
Interestingly, gcc does have a builtin __ASSEMBLER__
predefined macro to discriminate between an inclusion in an assembly file or a C file, but it seems that the kernel does not use it for historical reasons, relying instead on defining manually __ASSEMBLY__
when preprocessing assembly files.
Long story short: to get the correct output from the preprocessor, you should be doing something like
gcc -E -D__ASSEMBLY__ -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
(disclaimer: I'm not entirely familiar with the kernel build process, the line above may have other problems with include paths, or maybe the correct way would be to invoke cpp
instead of gcc
or whatever - I don't know)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With