The way to capture the correct preprocessed translation unit for a kernel source file is to first determine the exact command line that is being used to compile the .o. Then run the same command line, but add -E.  Also, change the -o option.
To obtain the full kernel command line you have to add V=1 to the make command line. To avoid searching through a long, verbose log, build everything first, then just remove the .o in question, and rebuild with V=1.
For instance, I'm compiling for arm using a gcc called arm-linux-gnueabi-gcc. To get the preprocessed version of kernel/spinlock.c, this works in my case:
arm-linux-gnueabi-gcc-E-B arm-linux-gnueabi- -Wp,-MD,kernel/.spinlock.o.d  -nostdinc -isystem /usr/lib/gcc/arm-linux-gnueabi/4.6/include -I/personal/localhome/kaz/git/kernel/arch/arm/include -Iarch/arm/include/generated -Iinclude  -include include/generated/autoconf.h -D__KERNEL__ -mlittle-endian -Iarch/arm/mach-capri/include -Iarch/arm/plat-kona/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -O2 -marm -fno-dwarf2-cfi-asm -mabi=aapcs-linux -mno-thumb-interwork -funwind-tables -D__LINUX_ARM_ARCH__=7 -march=armv7-a -Uarm -mfpu=vfp3 -mfloat-abi=softfp -Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-but-set-variable -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -DCC_HAVE_ASM_GOTO    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(spinlock)"  -D"KBUILD_MODNAME=KBUILD_STR(spinlock)" -c-o kernel/spinlock.prepro.ckernel/spinlock.c
I cut and pasted the line from the verbose compiler output, added -E and changed -o to capture the output in a file. (You can remove the -o <arg> to get it on standard output, of course).
Of course, many of the options in that command line do not affect preprocessing, but some do, such as anything that defines a macro, alters the include paths.
You don't want to be guessing at these things manually.
Note that if you invoke make using make -C <dir> ..., then make changes directory to <dir> before doing anything. It reads the Makefile from that directory, and so forth; it is almost the same as executing the command (cd <dir>; make ...). In this case, the command line that you get out of the build output will contain relative paths that only resolve in <dir>; change to <dir> before trying to run the command, or wrap it with (cd <dir>; <command>).