Can I get the file name from fd (file descriptor) passed by a syscall in kernel code? - linux-kernel

I doubt it but in the kernel code, can I get the file name for an fd(file descriptor) that was passed by a syscall?
In a situation, I get syscall from user space and in do_el0_svc(struct pt_regs *regs) function (arch/arm64/kernel/syscall.c, linux-5.10.0-rc5), I can print the fd value which is in x0. But can I know the file name from the fd value?
The syscall list for arm64 is here with number and function, arguments.

Related

How can GCC know argc if we did not specify it? [duplicate]

Everytime I create a project (standard command line utility) with Xcode, my
main function starts out looking like this:
int main(int argc, const char * argv[])
What's all this in the parenthesis? Why use this rather than just
int main()?
main receives the number of arguments and the arguments passed to it when you start the program, so you can access it.
argc contains the number of arguments, argv contains pointers to the arguments.
argv[argc] is always a NULL pointer. The arguments usually include the program name itself.
Typically if you run your program like ./myprogram
argc is 1;
argv[0] is the string "./myprogram"
argv[1] is a NULL pointer
If you run your program like ./myprogram /tmp/somefile
argc is 2;
argv[0] is the string "./myprogram"
argv[1] is the string "/tmp/somefile"
argv[2] is a NULL pointer
Although not covered by standards, on Windows and most flavours of Unix and Linux, main can have up to three arguments:
int main(int argc, char *argv[], char *envp[])
The last one is similar to argv (which is an array of strings, as described in other answers, specifying arguments to the program passed on the command line.)
But it contains the environment variables, e.g. PATH or anything else you set in your OS shell. It is null terminated so there is no need to provide a count argument.
These are for using the arguments from the command line -
argc contains the number of arguments on
the command line (including the program name), and argv is the list of
actual arguments (represented as character strings).
These are used to pass command line paramters.
For ex: if you want to pass a file name to your process from outside then
myExe.exe "filename.txt"
the command line "filename.txt" will be stored in argv[], and the number of command line parameter ( the count) will be stored in argc.
main() is a function which actually can take maximum three parameters or no parameters.
The following are the parameters that main() can take is as follows:-
1) int argc : It holds the number of arguments passed (from the command prompt) during the execution of program or you can say it is used ot keep a track of the number of variables passed during the execution of program. It cannot hold the negative value. Eg. If you pass your executable file "./a.out" then that will be considered as a parameter and hence argc value will be 0 i.e 1 value is passed.
2) char *argv[] : it is an array of character pointers which holds the address of the strings(array of characters) that are passed from the command prompt during execution of program. Eg. in above example if you wrote argv[argc] i.e argv[0] in cout then it will give ./a.out as output.
3) char*envp[] : it is also an array of character pointer which is used to hold the address of the environments variables being used in the program. Environment variables are the set of dynamic named value that can affect the way the running process will behave on the computer. For example running process want to store temporary files then it will invoke TEMP environment variables to get a suitable location.

fork() moving to the start of main()

I have the following code:
#include <stdio.h>
int main() {
printf("Hello\n");
fork();
return 0;
}
This gives output:
Hello
Which is as expected. But if i modify the code to:
#include <stdio.h>
int main() {
printf("Hello");
fork();
return 0;
}
Removing, the \n gives output:
HelloHello
Why is printf called two times. Isn't the child process supposed to execute the next instruction: return 0;
The printf function call places the hello characters into a buffer associated with the stdout stream. The buffer is subsequently flushed when the process exits, and that's when we see the output. You've forked before this happened, so two processes perform this buffer flushing in two separate address spaces when each of them exits. Each process has a copy of the stream, with the buffer and its hello contents.
When the stdout stream is connected to an interactive device (like a TTY on Unix), then it is line buffered. Line buffering means that the buffer is flushed whenever a newline character is output.
If we flush the buffer before fork (such as by printing a newline or by calling fflush(stdout)) then the flushing takes place in the parent process. The buffer is empty at the time the fork; though the child process inherits a copy of it, there is nothing left to flush in either process.
In the duplicated output case, something is in fact called twice. It's just not printf, but rather the write system call which sends the buffered characters to the output device.
It's not called twice. Remember that a console-connected stdout is line-buffered by default. Since you haven't ended your printf argument with a newline, it won't go to the console yet. It'll only go to the buffer first. So printf("Hello"); copies "Hello", into the output buffer, fork() creates a process copy with a copy of the address space (which includes stdout's output buffer with the "Hello" string in it) and return 0; returns control back to libc, which flushes the output buffer, but since this is happening after fork(), it'll happen twice -- once in the parent and once in the child, and so you get "HelloHello" in the final output.

How Golang implement stdin/stdout/stderr

I did a little program which was able to parse input from command line. It worked well by means of std.in. However, when I looked up the official document for further learning, I found there was too much stuff for me.
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
)
I read the document of func NewFile, type uintpty, Package syscall individually but could not figure out the whole. Also, I did not know the meaning of /dev/stdin, either.
I never learned another static programming language except for go. How could I realize the magic of stdin?
From the syscall package, Stdin is just the number 0:
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
This is simply because the posix standard is that stdin is attached to the first file descriptor, 0.
Since stdin is always present and open by default, os.NewFile can just turn this file descriptor into an os.File, and uses the standard Linux filepath "/dev/stdin" as an easily recognizable file name.

Bash incorrect behaviour if there is not space beetwen args and redirection

I have an issue.
I wrote a program where I have to validate some arguments passed with the command line (I am using argv[]) and to use a file redirected on stdin as input.
The program works but I have issues if there is not space between the arguments and the redirection
as ./aout -s 30 20< ficso
is this normal? I thought the character < was reserved by the bash.
Thanks
A number placed directly against a redirection operator like this turns it into a different redirection operator, in this case one that takes its input from FD 20 instead of FD 0.
When you write
20< filename
it means that instead of redirecting standard input (file descriptor 0) to the file, it should redirect file descriptor 20 to the file.
From the manual
3.6.1 Redirecting Input
Redirection of input causes the file whose name results from the expansion of word to be opened for reading on file descriptor n, or the standard input (file descriptor 0) if n is not specified.
The general format for redirecting input is:
[n]<word

How do I find the file something was defined in using gdb?

When I type list mystruct into gdb, I receive the lines of code used to define mystruct. How can I ask gdb to give me the file it is reading from to print those lines? Getting that file from the gdb python interface would be preferable. The more easily parsable the better.
Thanks!
For showing definition of a type there is a command ptype:
$ ptype mystruct
...
To know where type is defined, command info types regex:
$ info types ^mystruct$
<filename>:<line>
And to print lines of source file, command list filename:start_line,filename:end_line:
$ list myfile.c:100,myfile.c:110
if not enough
$ list +
Note that there is possible several same type definitions, so info types can give several locations.
Update
Since this is a matter of compatibility between compiler (that generates debugging information, e.g. DWARF) and gdb that reads it, for some reason, it's not always possible to retrieve detailed information, e.g. line number. This can be workaround-ed by using specific tools, e.g. for DWARF there is a dwarfdump tool, that has access to all DWARF information in the file. The output for structure type
struct mystruct {
int i;
struct sample *less;
}
looks like:
$ dwarfdump -ie ./a.out
...
< 1><0x00000079> structure_type
name "mystruct"
byte_size 0x0000000c
decl_file 0x00000002 ../sample.h
decl_line 0x00000003
sibling <0x000000a8>
< 2><0x00000085> member
name "i"
decl_file 0x00000002 ../sample.h
decl_line 0x00000004
type <0x0000004f>
data_member_location 0
< 2><0x0000008f> member
name "less"
decl_file 0x00000002 ../sample.h
decl_line 0x00000005
type <0x000000a8>
data_member_location 4
Here you have information on which line not only type declaration starts, but also line number for each member.
The output format is not very convenient, and heavy - you should write your own parser. But it could be better to write your own tool using libdwarf or utilize pyelftools on python. Here is one of examples.
In case you have compiled with debug information (-g3) option,
you can use:
info macro mystruct
e.g
info macro SOCK_RAW
(gdb) info macro SOCK_RAW
Defined at /usr/include/x86_64-linux-gnu/bits/socket_type.h:33
included at /usr/include/x86_64-linux-gnu/bits/socket.h:38
included at /usr/include/x86_64-linux-gnu/sys/socket.h:38
included at /home/nirl/cpp_tut/filter/filter.cpp:1
``

Resources