The following kprobe_based event example works well:
$ echo 'p:myprobe do_sys_open' > /sys/kernel/debug/tracing/kprobe_events
But, adding fetching arguments doesn't work:
$ echo 'p:myprobe do_sys_open dfd=%ax filename=%dx flags=%cx mode=+4($stack)' > /sys/kernel/debug/tracing/kprobe_events
Invalid argument
I think that the problem is %ax, %dx...
What is their meaning? And how can I make this code work?
%ax, %dx, etc. refer to the registers of your system. As hinted in the documentation, you'll need to change these if your architecture is not x86:
Note, which register/stack entry is assigned to each function argument depends on arch-specific ABI.
Since it looks like you're on arm (raspberry-pi tag), you can use the following:
$ echo 'p:myprobe do_sys_open dfd=%r0 filename=%r1 flags=%r2 mode=%r3' > /sys/kernel/debug/tracing/kprobe_events
Related
I try to use printf from my assembler code, this is a minimal example which should just print hello to stdout:
.section .rodata
hello:
.ascii "hello\n\0"
.section .text
.globl _start
_start:
movq $hello, %rdi # first parameter
xorl %eax, %eax # 0 - number of used vector registers
call printf
#exit
movq $60, %rax
movq $0, %rdi
syscall
I build it with
gcc -nostdlib try_printf.s -o try_printf -lc
and when I run it, it seems to work: the string hello is printed out and the exit status is 0:
XXX$ ./try_printf
hello
XXX$ echo $?
0
XXX$
But when I try to capture the text, it is obvious, that something is not working properly:
XXX$ output=$(./try_printf)
XXX$ echo $output
XXX$
The variable output should have the value hello, but is empty.
What is wrong with my usage of printf?
Use call exit instead of a raw _exit syscall after using stdio functions like printf. This flushes stdio buffers (write system call) before making an exit_group system call).
(Or if your program defines a main instead of _start, returning from main is equivalent to calling exit. You can't ret from _start.) Calling fflush(NULL) should also work.
As Michael explained, it is OK to link the C-library dynamically. This is also how it is introduced in the "Programming bottom up" book (see chapter 8).
However it is important to call exit from the C-library in order to end the program and not to bypass it, which was what I wrongly did by calling exit-syscall. As hinted by Michael, exit does a lot of clean up like flushing streams.
That is what happened: As explained here, the C-library buffers the the standard streams as follows:
No buffering for standard error.
If standard out/in is a terminal, it is line-buffered.
If standard out/in is a not a terminal, it is fully-buffered and thus flush is needed before a raw exit system call.
Which case applies is decided when printf is called for the first time for a stream.
So if printf_try is called directly in the terminal, the output of the program can be seen because hello has \n at the end (which triggers the flush in the line-buffered mode) and it is a terminal, also the 2. case.
Calling printf_try via $(./printf_try) means that the stdout is no longer a terminal (actually I don't know whether is is a temp file or a memory file) and thus the 3. case is in effect - there is need for an explicit flush i.e. call to C-exit.
The C standard library often contains initialization code for the standard I/O streams — initialization code that you're bypassing by defining your own entry point. Try defining main instead of _start:
.globl main
main:
# _start code here.
and then build with gcc try_printf.s -o try_printf (i.e., without -nostdlib).
This is regarding gcc used for RISC-V, but it probably also applies to other targets.
If I declare a function as ISR using __attribute__((interrupt)), gcc automatically saves and restores all used registers by the ISR. GCC will also generate a return-from-interrupt instruction (mret) at the end of the function instead of a regular function return (ret).
Is it possible to instruct gcc to save all used registers just like with an ISR, but instead of generating an mret instruction it should generate a regular ret?
There is no builtin support for this in GCC. Typically this is resolved by making a small trampoline stub which saves all caller-saved registers and then calls the real function normally.
Or, if the only needed change is replacing mret with ret, you could simply postprocess generated assembly code:
$ gcc file.c -S -o file.s
$ sed -i -e 's/\bmret\b/ret/'
I am using gcc to compile a set of c codes. And my question is: can I tell gcc not to generate some specific instructions?
e.g. I don't want gcc to generate MUL instruction, how should I do?
I'm working on self implemented MIPS cpu and related codes, and for some reasons, I don't want gcc to generate some weird instructions that I've not implemented. It seems that I need to hack the gcc a little bit.
Based on Krister Walfridsson's blog, the way to do it could be:
Add an command line option to the machine.opt file, so to create a global variable.
Find the instruction node in machine.md or other files, that emits the instruction you want to disable. Change the condition to be on the new variable you'v added. When the condition is not met, gcc would emit a call to a function that you'll supply in your .c file or lib file.
As a simpler example, take a look at the ft32 architecture directory. It creates an global variable NODIV based on a -mnodiv command line option. The instruction node in the ft32.md file contains:
(define_insn "divsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(div:SI
(match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
"!TARGET_NODIV"
"div.l %0,%1,%2")
In this ft32 case, when the variable is not set, gcc emits div.l assembly code. When it is set, it would make a call to a function named __divsi3.
Though I have not tried this out. Will update with exact information when I get a chance to try it out.
I am adding quite a few mocks, using cmocka, which require me to alias them using the GC Clinker opetion --wrap=
I am passing a linker option of the format
-Wl,--wrap=foo,--wrap=bar,--wrap=baz,--wrap= ...
Is there any way to shorten it?
-Wl,--wrap=foo,bar,baz,... did not work. Any suggestions?
Is there any way to shorten it?
No.
Why would you want to? If you care about the length of the resulting command line, note that GCC supports response files:
echo "-Wl,--wrap=foo,--wrap=bar,--wrap=baz,--wrap=..." > cmd
gcc #cmd ...
I have a rule something, that works on the variable VAR. I also have another rule something-all, that needs to run something, with VAR set to each value in vars.
vars = hello world
something:
echo $(VAR)
something-all:
$(foreach VAR,$(vars),something)
This doesn't quite work, I get
noob#work:~/Desktop$ make something-all
something something
make: something: No such file or directory
make: *** [something-all] Error 1
It should probably print hello\nworld.
I used to do this with wildcard rules by retrieving VAR from %, but got the feeling that was the wrong way to do it. This looked like this:
vars = hello world
all: $(foreach VAR,$(vars),something-$(VAR))
something-%:
echo $*
The below should fix your problem
Using foreach (Tried on GNU Make 3.80 on sparc-solaris 2.8 and windows)
vars = hello world
something:
echo $(VAR)
something-all:
$(foreach i, $(vars), $(MAKE) something VAR=$i || exit 1;)
Using shell for-loop (Tried on GNU Make 3.80 and cc make on sparc-solaris 2.8)
vars = hello world
something:
echo $(VAR)
something-all:
for i in $(vars); do $(MAKE) something VAR=$$i || exit 1; done
TL;DR: If you want to program make, drop GNU Make in favor of BSD Make.
This is a personal recommendation. While BSD Make seems more limited than GNU Make, as it offers less programming facilities, it is much easier to program and has a few unique killer features. This is why I propose a solution with GNU Make and another solution for BSD Make:
Doing it in GNU Make
Using GNU Make, you can write a macro to define a target. The canonical way to define a sequence in a Makefile is to add the steps of the sequence as dependencies to a target, as reflected by the snippet below:
vars= hello world
define something_t =
something: something-$(1)
something-$(1):
#echo $(1)
endef
$(foreach _,$(vars),$(eval $(call something_t,$_)))
It is recommended to use this organisation (rather than defining just one target), because you can work on it to make the task easily resumable if you interrupt the sequence. A Makefile describes a job whose advancement is entirely described by the state of the file system. A task is then easily resumable, if each step is associated to a file, usually a compilation object but sometimes also an empty file which is touch'ed to indicate that important checkpoints have been passed.
Using an auxiliary macro is a flexible solution that can be adapted to more complicated tasks than just echoing a name. Note that this does work with newest versions of GNU Make (4.1). On GNU Make 3.81, you should remove the equal sign from the macro definition.
Adapting your example for BSD Make
If this is an option for you, I recommand dropping the use of GNU Make and replace it by BSD Make, which is way easier to program: it has a short and to the point documentation, while the documentation of GNU Make is very verbose and somewhat unclear, BSD Make has industrial-strength examples of complex rulesets (FreeBSD Build system or BSD Owl), and it has a simple and predictable macro language.
vars= hello world
something:
.for _var in ${vars}
echo ${_var}
.endfor
This can evolve to support more complicated tasks, just by replacing the echo by the adapted commands, or using intermediary steps.
Allow the user to override some tasks, also in BSD Make
In this slightly more advanced variation, we allow the user to override our own recipes for building targets something-hello and something-world.
For each item in our list, a target something-* is created it if it does not already exist, and added to the dependencies of something. The whole operation of defining these targets only happens if something has been left undefined. Therefore, users of these macros can:
Override the recipes for something-hello and something-world
Override the full procedure bound to something.
Implementing such customisation possibilities is mandatory if we want to write useful, reusable, macros for Make. Unluckily, customisation of this sort is nearly impossible in GNU Make.
vars = hello world
.if!target(depend)
.for _var in ${vars}
.if!target(something-${_var})
something-${_var}:
echo ${_var}
.endif
something: something-${_var}
.endfor
.endif
Here's one way to do it:
VARS := hello world
THINGS := $(addprefix something-, $(VARS))
allthings: $(THINGS)
something-%:
echo $*
It should be no surprise that
vars := hello world
something-all:
$(foreach VAR,$(vars),something)
tries to run something something. That's exactly what the foreach expands to, since you don't reference VAR in the third expression.
All you need to do is reference VAR and use a command such as echo:
vars := hello world
something-all:
$(foreach VAR,$(vars),echo $(VAR);)
$ make
echo hello; echo world;
hello
world
Note how chaining the commands with a semicolon avoids forking several shells or -- GASP! -- recursive make invocations. It doesn't get more performant than that.
Alternatively, if your command accepts several somethings as arguments,
vars := hello world
something-all:
echo $(foreach VAR,$(vars),$(VAR))
$ make
echo hello world
hello world
But that is equivalent to the super simple echo $(vars). So it might pay off to think outside the box trying to change your requirements to make this simple solution work.