Invoking the preprocessor from a shell or shell-like program - shell

As mentioned in the title I want to invoke the preprocessor from a shell.
Let me clarify:
Suppose I have to invoke Preprocessor for command patch in Linux say:
patch -p1 -D `"{what and how should i write here }"` < patch.patch
Patch command has an option -D where I can define a preprocessor (to my understanding). I tried searching on Google I got only one link I couldn't understand it properly.
Please guide me with an example (or proper reference).
What all can be written in -D option of any command?
Are constructs same for all command are different for different commands?
What can be the input variables?

The -D option to patch means that the changes made to the patched file will be surrounded by #ifndef X / #else / #endif if X is what you specify as the argument to the -D option.
For example:
$ cat file-1.c
#include <stdio.h>
int main(void)
{
printf("Hello world\n");
return 0;
}
$ cat file-2.c
#include <stdio.h>
int main(void)
{
puts("Hello world");
return 0;
}
$ diff -u file-1.c file-2.c > patch
$ patch -DPRINTF_TO_PUTS -i patch --verbose
Hmm... Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- file-1.c 2013-02-01 00:33:01.000000000 -0800
|+++ file-2.c 2013-02-01 00:33:17.000000000 -0800
--------------------------
Patching file file-1.c using Plan A...
Hunk #1 succeeded at 2.
done
$ file-1.c
#include <stdio.h>
int main(void)
{
#ifndef PRINTF_TO_PUTS
printf("Hello world\n");
#else
puts("Hello world");
#endif
return 0;
}
$
So, to answer your questions:
You should put a valid C identifier after -D on the patch command line.
Different commands apply different meanings to any given option letter. You can find information about common interpretations for options at The Art of Unix Programming, but there are only 52 alphabetic (single-letter) options and there are many more different meanings for arguments to different commands than that.
I'm not sure what you mean by this.
None of this invokes a C preprocessor from the command line. If you need to do that, look for a program cpp on your system. If you can't find cpp anywhere, you may end up invoking gcc -E instead.

Related

How can Autoconf be made to test source code from an external file?

We use GNUmakefile as our primary build system. The makefile performs feature tests using test programs in source files:
$ ls TestPrograms/
dump2def.cxx test_arm_sm4.cxx test_x86_avx.cxx
test_32bit.cxx test_cxx.cxx test_x86_avx2.cxx
test_64bit.cxx test_mixed_asm.cxx test_x86_avx512.cxx
...
A test program is what one would expect:
$ cat test_cxx.cxx
#include <string>
int main(int argc, char* argv[])
{
unsigned int x=0;
return x;
}
We support Autotools for distros like Debian and Fedora. We want Autotools to use the test programs like GNUmakefile and CMake. Autools documentation on AC_COMPILE_IFELSE is here, but it is pathetic as usual. It does not discuss the topic or provide examples.
Taking stabs in the dark:
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([TestPrograms/test_x86_sse2.cxx])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
Results in:
checking if g++ supports -msse2 and Foo Bar... no
And the same result with cat'ing the file into a string:
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(`cat TestPrograms/test_x86_sse2.cxx`)],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
The result is incorrect on a Skylake machine. SSE2 is part of the core instruction set and always available:
$ g++ -msse2 TestPrograms/test_x86_sse2.cxx
$
How do we tell Autoconf to compile the test file?
Autools documentation on AC_COMPILE_IFELSE [...] is pathetic as usual. It does not discuss the topic or provide examples.
Although that individual page does not provide full details, it is part of a larger manual that provides more detail and some relevant examples in nearby sections. Even that page itself suggests AC_LANG_PROGRAM as an appropriate means to produce the input parameter for that macro, however, and the documentation for that macro gives a reasonable idea of the general form it produces -- actual source code for a program, not a file name.
When it comes to taking stabs at an answer, I suggest not being willfully in the dark. Even if you do not find the documentation adequate, at least configure's log file (config.log) should contain a lot of information about what, exactly, failed, and how. In the event of a failure, it will show you the complete source of the test program it used, the commands it executed to actually perform the test, and any diagnostics emitted.
For example, using a configure script derived from this configure.ac inspired by your examples ...
AC_INIT([test_test], [0.0.1])
AC_CONFIG_SRCDIR([test_src/test_cxx.cxx])
AC_PROG_CXX
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([`cat test_src/test_cxx.cxx`])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
AC_OUTPUT
... I get a failure result with this relevant output in the log:
configure:2891: gcc -o conftest -g -O2 conftest.c >&5
conftest.c:9:18: fatal error: string: No such file or directory
#include <string>
^
compilation terminated.
configure:2891: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "test_test"
| #define PACKAGE_TARNAME "test_test"
| #define PACKAGE_VERSION "0.0.1"
| #define PACKAGE_STRING "test_test 0.0.1"
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL ""
| /* end confdefs.h. */
| #include <string>
| int main(int argc, char* argv[])
| {
| unsigned int x=0;
| return x;
| }
| int
| main ()
| {
|
| ;
| return 0;
| }
configure:2895: result: no
This shows that source code is indeed being read from the external file, and it also reveals two key problems:
AC_LANG_PROGRAM is providing more than you want in this case (consistent with its documentation). In fact, you don't need it at all if you are providing complete source for the test program.
The test program is being compiled and linked as a C program, but its source is C++. This default is documented in the manual.
Issue (1) can be resolved by just feeding the source directly to AC_LINK_IFELSE, without wrapping it via AC_LANG_PROGRAM, but Autoconf will warn in that case about not seeing AC_LANG_SOURCE. A reasonably comfortable solution to that is to use AC_LANG_SOURCE directly, instead of AC_LANG_PROGRAM. That will add some additional #defines to the provided source, however, which might not suit you. If you don't want that, then I think it will be safe to ignore the warnings in this case.
Issue (2) can be resolved by using the AC_LANG macro to tell Autoconf that test should be performed using the C++ compiler and the relevant Autotools variables for C++ flags.
Thus, if I update my configure.ac to
AC_INIT([test_test], [0.0.1])
AC_CONFIG_SRCDIR([test_src/test_cxx.cxx])
AC_PROG_CXX
AC_LANG([C++])
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
[AC_LANG_SOURCE([`cat test_src/test_cxx.cxx`])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
AC_OUTPUT
then my configure run succeeds, and I see in the log that the compilation command it executed, successfully, was
configure:2296: g++ -o conftest -msse2 conftest.cpp >&5
. That is, it compiled using the selected C++ compiler, using flags as specified in CXXFLAGS, and naming the test source file appropriately for compilation as C++.

Implementing a syscall on real-time Debian Wheezy

For educational purposes, I want to implement a system call in Debian Wheezy. I wish to implement it on the kernel that comes in the linux-image-3.2.0--rt-amd64 package. Here is an overview of what I have tried:
To get the kernel source:
apt-get source linux-image-3.2.0-4-rt-amd64
From that, I get the following files/directories the directory I executed in:
linux_3.2.41.orig.tar.xz
linux_3.2.41-2+deb7u2.dsc
linux_3.2.41-2+deb7u2.debian.tar.xz
as well as:
linux_3.2.41
which contains the source code for the kernel.
Then, to make the necessary changes in order to add the system call, I basically followed this page:
How to write system calls on debian/ubuntu
The following is a condensed version of the instructions given there modified to reflect the changes I made.
+File 1: linux-x.x.x/vpart_syscalls/vpart_syscalls.c
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long insert_partition(char*dest, const char* src)
{
printk("<--- the syscall has been called!");
return 0;
}
File 2: linux-x.x.x/vpart_syscalls/Makefile. Create a Makefile within the same test directory you created above and put this line in it:
obj-y := vpart_syscalls.o
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S. Now, you have to add your system call to the system call table. Append to the file the following line:
.long insert_partition
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
In this file, the names of all the system calls will be associated with a unique number. After the last system call-number pair, add a line
#define __NR_insert_partition 349
Then replace NR_syscalls value, stating total number of system calls with (the existing number incremented by 1) i.e. in this case the NR_syscalls should've been 338 and the new value is 339.
#define NR_syscalls 350
File 5: linux-x.x.x/include/linux/syscalls.h
Append to the file the prototype of our function.
asmlinkage long insert_partition(int lenTicks, int vpid);
just before the #endif line in the file.
File 6: Makefile at the root of source directory.
Open Makefile and find the line where core-y is defined and add the directory test to the end of that line.
core-y += kernel/ mm/ fs/ test/ vpart_syscalls/
I then proceeded to build the kernel in a different fashion than is described there:
make localmodconfig
make menuconfig (making no changes)
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=+tm kernel_image kernel_headers
cd ..
dpkg -i linux-image-3.8.*
dpkg -i linux-headers-3.8.*
The kernel that is installed boots fine. I made the following c program to test the syscall:
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
printk("Calling the new syscall!\n");
int ret = 100;
ret = syscall(349, 1, 2);
printf("call return value: %i\n", ret);
return 0;
}
When I compile and run this program, I get a return value of -1. I check the messages using dmesg and there is no evidence of my printk being called..
If anyone knows where my problem is I would be really really happy! I should say I am not too experienced at changing and building the kernel, but I have learned a lot about it. I read Robert Loves book - linux kernel development and several guides on the webs.
I think, the steps 3 and 4 may be incorrect for 64-bit kernels:
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S.
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
There are two files here: http://lxr.linux.no/linux+v3.2.41/arch/x86/kernel/
syscall_64.c 668 2008-12-24 14:26:58 -0800
syscall_table_32.S 8659 2012-01-04 14:55:50 -0800
First one defines syscall table contents for 64-bit mode using C file and macro-cheating with unistd_64.h
#define __SYSCALL(nr, sym) [nr] = sym,
const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
....
#include <asm/unistd_64.h>
};
Where asm/unistd_64.h is
#define __NR_read 0
__SYSCALL(__NR_read, sys_read)
and so on.
And second one, which you changed - is for 32-bit mode and written using asm file and labels (.long sys_call_name).
So, you defined syscall for 32-bit mode and you are using linux-image-3.2.0-4-rt-amd64 which is basically for " 64-bit PCs".
I think you compiled your test program as gcc test.c, which defaults to 64-bit mode. You can try -m32 option of gcc: gcc -m32 test.c to get 32-bit application (this will only work if you have correct cross environment for 32-bit builds) or compile this test on some 32-bit linux.
Or the other choice is to make step "4a": edit arch/x86/include/asm/unistd_64.h to add two lines:
#define __NR_insert_partition YOUR_NUMBER
__SYSCALL(__NR_insert_partition, insert_partition)
I'm not sure where and how NR_syscalls for 64bit is defined. It may be generated during build.

How can I specify an include file from the GCC Command Line?

Using GCC under Windows, I would like to be able to specify on the gcc command line (or from a manually managed makefile) the name of a specific include file to be included in the file being compiled. As I see it, ideally the source code file would contain a line something like…
#include INCLUDEFILENAME
…then a filename specified on the gcc command line would be substituted for the INCLUDEFILENAME text.
It seems I can get close to achieving this by defining a macro called INCLUDEFILENAME on the gcc command line using the -D option (eg. -D INCLUDEFILENAME="C:\TestLib\Test1.h") but when the filename text gets substituted into the #include statement it is not enclosed in double quotes, and without these it is not recognized as a file to be included. Of course…
#include "INCLUDEFILENAME"
…doesn’t work as INCLUDEFILENAME then becomes a string literal and does not get replaced by the macro value. I have tried other ways of specifying the double quotes (\x22, \", "\"", etc) but these don’t seem to work on the #include line.
I am aware of the gcc -include option which it seems can force a file to be included without it being mentioned in any way in the source file, but I would prefer that the source file indicates that an include file is to be included here but that it’s name is specified “externally” to the source file (ultimately, from the makefile).
Any suggestions on how I can achieve this would be appreciated.
You have to include the double quotes " as part of the define (or <>, as the case may be):
% cat test.c
#include <stdio.h>
#include OTHERFILE
int main() { printf("%s\n", func()); }
% cat func.c
char *func() { return "It worked."; }
% gcc test.c -DOTHERFILE='"func.c"'
% ./a.out
It worked.
%
You can use the ugly but classic stringification trick:
#define STRINGIFY2(x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#include STRINGIFY(INCLUDEFILENAME)

sys_call_table in linux kernel 2.6.18

I am trying to set the sys exit call to a variable by
extern void *sys_call_table[];
real_sys_exit = sys_call_table[__NR_exit]
however, when I try to make, the console gives me the error
error: ‘__NR_exit’ undeclared (first use in this function)
Any tips would be appreciated :) Thank you
Since you are in kernel 2.6.x , sys_call_table isnt exported any more.
If you want to avoid the compilation error try this include
#include<linux/unistd.h>
however, It will not work. So the work around to "play" with the sys_call_table is to find the address of sys_call_table in SystemXXXX.map (located at /boot) with this command:
grep sys_call System.map-2.6.X -i
this will give the addres, then this code should allow you to modify the table:
unsigned long *sys_call_table;
sys_call_table = (unsigned long *) simple_strtoul("0xc0318500",NULL,16);
original_mkdir = sys_call_table[__NR_mkdir];
sys_call_table[__NR_mkdir] = mkdir_modificado;
Hope it works for you, I have just tested it under kernel 2.6.24, so should work for 2.6.18
also check here, Its a very good
http://commons.oreilly.com/wiki/index.php/Network_Security_Tools/Modifying_and_Hacking_Security_Tools/Fun_with_Linux_Kernel_Modules
If you haven't included the file syscall.h, you should do that ahead of the reference to __NR_exit. For example,
#include <syscall.h>
#include <stdio.h>
int main()
{
printf("%d\n", __NR_exit);
return 0;
}
which returns:
$ cc t.c
$ ./a.out
60
Some other observations:
If you've already included the file, the usual reasons __NR_exit wouldn't be defined are that the definition was being ignored due to conditional compilation (#ifdef or #ifndef at work somewhere) or because it's being removed elsewhere through a #undef.
If you're writing the code for kernel space, you have a completely different set of headers to use. LXR (http://lxr.linux.no/linux) searchable, browsable archive of the kernel source is a helpful resource.

How to undefine a define at commandline using gcc

How do I at compile time undefine a compiler macro using gcc. I tried some compile args to gcc like -D but I can't get to see the "not defined" message.
Thanks
#include <iostream>
#define MYDEF
int main(){
#ifdef MYDEF
std::cout<<"defined\n";
#else
std::cout<<"not defined\n";
#endif
}
You can use the -U option with gcc, but it won't undefine a macro defined in your source code. As far as I know, there's no way to do that.
You should wrap the MYDEF definition in a preprocessor macro, the presence of which (defined on the command line) would then prevent MYDEF from being defined. A bit convoluted to be sure but you can then control the build in the way you want from the command line (or Makefile). Example:
#ifndef DONT_DEFINE_MYDEF
#define MYDEF
#endif
Then from the command line when you don't want MYDEF:
gcc -DDONT_DEFINE_MYDEF ...
http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Preprocessor-Options.html#Preprocessor-Options
The -U options seemed like what you could have needed... but then again you can't override a definition contained in your source code without resorting to more preprocessor directives.
You can resort to filtering source code and give this back to gcc for compilation, like this pseudo code:
grep -v "define MYDEF" yourFile.c | gcc -o yourFile.o -xc -
Hope it helps.
The code use case is not right. As I see, you have hard coded #define in the file. If compiler initially assumes MYDEF undefined, it will define it once it start processing the file.
You should remove the line #define MYDEF. And I hope your test case will work, if you pass MYDEF to -D and -U.
Here is one possibility that doesn't completely cover your use case but which I found to be helpful in my case.
If your MYDEF were #defined in a separate header file #included from the .c file you could force the definition of the #include guard macro with the -D option (thus preventing the MYDEF #definition) then either actively #define (still with the -D option) MYDEF to something else or just leave it undefined.
It is clear that anything else defined in the header file would also be missing but this was for me a solution to forcedly undefine a macro without changing the third-party code.

Resources