Usage of %line directive in NASM with dwarf debug format does not result in expected line numbers - x86-64

I'm compiling the following code with NASM (nasm -g -F dwarf -f elf64 test.asm && gcc -g3 test.o).
global main
section .text
main:
%line 1 test.txt
PUSH 1337
%line 2 test.txt
PUSH 1338
%line 3 test.txt
PUSH 1339
%line 8 test.txt
POP RAX
%line 9 test.txt
POP RAX
%line 10 test.txt
POP RAX
RET
I would expect this to add the lines 1, 2, 3, 8, 9 and 10 to the dwarf data, however when I explore the file (using DWARF explorer, readelf or own code) I instead get the following lines:
test.txt 2 0x1130 (PUSH 1337)
test.txt 3 0x1135 (PUSH 1338)
test.txt 4 0x113a (PUSH 1339)
test.txt 9 0x113f (POP RAX)
test.txt 10 0x1140 (POP RAX)
test.txt 11 0x1141 (POP RAX)
test.txt 13 0x1142 (RET)
Every line number is one higher than what I provided in the assembly and in addition there is an extra line #13 situated at the ret statement. Could anyone explain what is going on here, and what I should do to get the expected result?

PUSH 1337 is on the line after the line you made line 1. So it seems %line sets the number of this line, and NASM's normal mechanism for counting line numbers continues to operate as normal. (Unlike GAS's deprecated .line which sets the line number of the next line.)
The RET is 2 lines after the last POP RAX, so that makes sense.
According to the manual, the full syntax includes an optional parameter to control line-number incrementing; apparently mmm defaults to 1:
%line nnn[+mmm] filename
So possibly (untested)
%line 1+0 test.txt
NASM -g is designed to make debug info for the asm source itself, not for the line numbers of some higher-level source file that was compiled to a .asm NASM file. The manual says it's intended for use with a macro-preprocessor (other than NASM's built-in macros), where it would make sense to have source line numbers increment.
But if you want to hack up that functionality, if +0 doesn't work, I guess you could keep resetting the %line before every instruction, with the same line number repeatedly for ones in a block that all came from the same higher-level source line.
And use the number before the one you want NASM to use. So I guess use %line 0 test.txt if you want the instruction on the next line to be reported as line 1 of test.txt, because 0 is the number before 1.
(Assuming NASM supports using 0 as a line number, and rewinding the line number to have the same line twice.)
I don't know of NASM directives equivalent in design to GAS's .loc which is intended for generating debug info for a C or other high-level source which compiled to a .s.

Related

Correlate stack trace with source code in MATLAB .mexa64 file

I have custom C bindings called from Matlab and sometimes I get a segmentation fault. How can I identify in my source code what the corresponding statement is producing the SEGFAULT?
My C function is called Pairing in the source file Pairing.c
Stack Trace (from fault):
[ 0] 0x00007fff6bc76d00 Pairing.mexa64+00015616
[ 1] 0x00007fff6bc74330 Pairing.mexa64+00004912 mexFunction+00001862
[ 2] 0x00007fffe2b4f213 MATLAB/R2020a/bin/glnxa64/libmex.so+00582163
The result of nm -a Pairing.mexa64 | grep ' N ' is
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_str
here is my trick (works every single time), run this in a terminal window
matlab -nojvm -nosplash -r 'my_script' -D"valgrind --error-limit=no --tool=memcheck -v --log-file=valgrind.log"
preferably run this under Linux or Mac, but you can also do this in Windows using cygwin64/msys2. Need to install valgrind before use - once it dumps the log in valgrind.log, open it using a text editor, and you can see all memory errors captured by valgrind.
for CUDA codes, you can also replace the valgrind command and parameters by cuda-memcheck, does something similar, but for the GPU.
make your test script my_script.m very simple, for example, load a .mat file, and then call your mex function immediately to avoid lengthy overhead.
The way I solved it was following these steps
1) Use objdump -d Pairing.mexa64 > Pairing_obj.
2) Translate 00015616 to hex=0x3d00.
3) Find the relevant statement and recognize the produced assembly.
4) Realize this is the first time a certain variable is dereferenced.
I am still looking for some way that this could be done easier.

Easiest way to check for include

I would like to check for cpp files to contain
#include <stdafx.h>
Since I do not want this thing to fail, when e.g. comments are in front of the include, I would prefer a way of checking, that honors the actual c++ syntax.
Can this be easily done (in a cross-platform way (using cygwin sh on Windows))?
cpp, the C preprocessor from the GNU compiler collection, has an -M flag that lists the files a C file depends on, i.e. the headers it includes. You could run cpp on all your files, then filter out stdafx.h. I don't personally use Cygwin, but I believe something like this should work:
find . -type f -name "*.cpp" -exec sh -c "echo {} && cpp -M {} | grep -c stdafx.h" \;
This finds every file with a name that ends with cpp, then executes a shell that in turn echoes the file name we're looking at. It then runs it through cpp, finally grepping cpp's output for the header we're looking for and counting the lines. The output should look something like this (looking for stdio.h in the Git source tree):
./diff.c
0
./gettext.c
1
./gpg-interface.c
0
./hashmap.c
0
./hex.c
0
./environment.c
0
./remote-testsvn.c
0
./server-info.c
0
./compat/fopen.c
1
./compat/basename.c
1
./compat/strtoimax.c
1
./compat/hstrerror.c
1
./compat/pread.c
1
./compat/gmtime.c
1
./compat/setenv.c
1
Of course, if you only want to check a single file, you don't need the whole find invocation, you can just do "cpp -M myfile.cpp | grep -c stdafx.h" which will give you either a 0 if it's not in there or a 1 if it is.

grep command to print follow-up lines after a match

how to use "grep" command to find a match and to print followup of 10 lines from the match. this i need to get some error statements from log files. (else need to download use match for log time and then copy the content). Instead of downloading bulk size files i need to run a command to get those number of lines.
A default install of Solaris 10 or 11 will have the /usr/sfw/bin file tree. Gnu grep - /usr/sfw/bin/ggrep is there. ggrep supports /usr/sfw/bin/ggrep -A 10 [pattern] [file] which does what you want.
Solaris 9 and older may not have it. Or your system may not have been a default install. Check.
Suppose, you have a file /etc/passwd and want to filter user "chetan"
Please try below command:
cat /etc/passwd | /usr/sfw/bin/ggrep -A 2 'chetan'
It will print the line with letter "chetan" and the next two lines as well.
-- Tested in Solaris 10 --

How to move part of file to its end

rpm automatically place a new installed kernel as the first option. However, I want to move it as the last one - to end of the file.
Grub configuration file looks like this:
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Fedora (2.6.29.6-217.2.7.fc11.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.29.6-217.2.7.fc11.x86_64 ro root=/dev/mapper/main-root rhgb quiet
initrd /initrd-2.6.29.6-217.2.7.fc11.x86_64.img
title Fedora (2.6.29.6-217.2.3.fc11.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.29.6-217.2.3.fc11.x86_64 ro root=/dev/mapper/main-root rhgb quiet
initrd /initrd-2.6.29.6-217.2.3.fc11.x86_64.img
title Fedora (2.6.29.6-213.fc11.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.29.6-213.fc11.x86_64 ro root=/dev/mapper/main-root rhgb quiet
initrd /initrd-2.6.29.6-213.fc11.x86_64.img
My goal is to move first option (217.2.3) to end. Now I figure out how to delete it:
sed -e '/(2.6.29.6-217.2.7.fc11.x86_64)/,+3d' /boot/grub/menu.lst
p command only prints current line (not as in vim, where it means paste).
Do you have any ideas how to automatically move this part of file to its end?
I have to answer myself. :-)
sed '/\(2.6.18-157.el5\)/,+4 { H; d; }; $ { p; x; }' /boot/grub/menu.lst
If you are not fluent with sed (me neither), there is more verbose version
sed '
/\(2.6.18-157.el5\)/,+3 { #Find line which contains version of our kernel in parentheses and took also 3 following lines
H # Append this line into buffer
d # Delete line
}
$ { # On the last line
p # Print current line
x # Change current line with buffer and vice versa
# Afterwards sed print current line => in our case deleted line
}' /boot/grub/menu.lst
A very similar task was covered extensively here
Yes, there is some satisfaction in a well crafted sed command, but I think I would tend to use an editor, so I could see the lines I was going to move around, and not have to worry about getting the line numbers wrong in a command.

Appending and overwriting the beginning of a text file (windows)

I have two text files. I'd like to take the content of file1.txt that has four lines and append on the first four lines of the file2.txt. That has to be done overwriting all the records of the first four lines of file2.txt but keeping the rest of the original content (the other lines).
How can I do that using a batch or the windows prompt?
copy file1.txt temp.txt
echo. >> temp.txt
more +5 file2.txt >> temp.txt
move /y temp.txt file2.txt
EDIT: added the "echo. >> temp.txt" instruction, which should add a newline to temp.txt, thereby allowing for a "clean" merge of file2.txt (if file1.txt doesn't end with a newline).
Unless the four lines at the start of the two files occupy exactly the same amount of space, you can't, without rewriting the whole file.
You can't insert or delete data into files at arbitrary points - you can overwrite existing data (byte for byte), truncate the file or append to the end, but not remove or insert into the middle.
So basically you'd need to:
Start a new file consisting of the first four lines of file1.txt
Skip past the first four lines of file2.txt
Append the rest of file1.txt to the new file2.txt
You can do this fairly easily with the head/tail commands from Unix, which you could get from Cygwin if that's an acceptable solution. It's likely that the head/tail from the Windows Services for Unix would work too.
If you grab the coreutils from Gnutils you'll be able to do a lot of the stuff you can do with Cygwin without having to install cygwin.
Then you can use things like head, tail and cat which will allow you to do what you're looking to.
e.g.
head -n 4 file2.txt
to get the first four lines of file2.
Extract the zip from the page linked above, and grab whichever of the utils you need to use out of the bin directory and put them in a directory in your path - e.g. for the below you'd want mv, head and tail. You could use the built in DOS move command, but you'd need to change the options slightly.
The question is a little unclear, but if you're looking to remove the first four lines of file2.txt and append them to file1.txt you can do the following:
head -n 4 file2.txt >> file1.txt
tail -n +5 file2.txt >> temp.txt
mv temp.txt file2.txt
With batch alone I'm not sure you can do it.
With Unix commands you can -- and you can easily use Unix commands under Windows using Cygwin.
In that case you want:
#!/bin/bash
head -n 4 file1.txt > result.txt # first 4 lines of file1
tail -n +5 file2.txt >> result.txt # append lines 5, 6, 7... of file2
mv result.txt file2.txt # replace file2.txt with the result
you could do it if you wrote a script in something other than windows batch. vbscript or jscript with windows scripting host should be able to do it. Each of those would have a method to grab lines from one file and overwrite the lines of another.
You can do this by creating a temporary third file, pulling the lines from the first file and adding them to the temp file, then reading the second file and, after reading in four carriage return/linefeed pairs, write the rest to the temp file. Then, delete the second file and rename the temp file to the second file name.