How to print the current source line in windbg? - windbg

I was wondering if it's possible to display the current source line in windbg?
Right now I am able to step through the code and display 5 lines before and after the current line every time I step through the code. This is great, but it would be nice if there was a command to print the current source line on demand instead of having to step to the next line.

if you want to print a single source line use lsp
The default value is 20 (0x14)
> lsp -a 1
WARNING: Source line display is disabled
At the prompt, display 0 source lines before and 1 after
For lsa commands, display 0 source lines before
For ls and lsa commands, display 1 source lines
now use lsa where .denotes the current Eip/Rip
0:000:x86> lsa .
> 28: void main(int argc, char *argv[]) {
or provide an address
0:000:x86> lsa #$ip+42
> 30: SymInitialize(hProcess, NULL, FALSE);
you can also provide the source line to lsa
0:000> lsa `symtype!symtype.cpp:16`
> 16: if (maxcmplen == pSymInfo->NameLen) {
0:000> lsa `symtype!symtype.cpp:28`
> 28: void main(int argc, char *argv[]) {

Related

"Program too large" threshold greater than actual instruction count

I've written a couple production BPF agents, but my approach is very iterative until I please the verifier and can move on. I've reached my limit again.
Here's a program that works if I have one fewer && condition -- and breaks otherwise. The confusing part is that the warning implies that 103 insns is greater-than at most 4096 insns. There's obviously something I'm misunderstanding about how this is all strung together.
My ultimate goal is to do logging based on a process' environment -- so alternative approaches are welcome. :)
Error:
$ sudo python foo.py
bpf: Argument list too long. Program too large (103 insns), at most 4096 insns
Failed to load BPF program b'tracepoint__sched__sched_process_exec': Argument list too long
BPF Source:
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <linux/version.h>
int tracepoint__sched__sched_process_exec(
struct tracepoint__sched__sched_process_exec* args
) {
struct task_struct* task = (typeof(task))bpf_get_current_task();
const struct mm_struct* mm = task->mm;
unsigned long env_start = mm->env_start;
unsigned long env_end = mm->env_end;
// Read up to 512 environment variables -- only way I could find to "limit"
// the loop to satisfy the verifier.
char var[12];
for (int n = 0; n < 512; n++) {
int result = bpf_probe_read_str(&var, sizeof var, (void*)env_start);
if (result <= 0) {
break;
}
env_start += result;
if (
var[0] == 'H' &&
var[1] == 'I' &&
var[2] == 'S' &&
var[3] == 'T' &&
var[4] == 'S' &&
var[5] == 'I' &&
var[6] == 'Z' &&
var[7] == 'E'
) {
bpf_trace_printk("Got it: %s\n", var);
break;
}
}
return 0;
}
Basic loader program for reproducing:
#!/usr/bin/env python3
import sys
from bcc import BPF
if __name__ == '__main__':
source = open("./foo.c").read()
try:
BPF(text=source.encode("utf-8")).trace_print()
except Exception as e:
error = str(e)
sys.exit(error)
bpf: Argument list too long. Program too large (103 insns), at most 4096 insns
Looking at the error message, my guess would be that your program has 103 instructions and it's rejected because it's too complex. That is, the verifier gave up before analyzing all instructions on all paths.
On Linux 5.15 with a privileged user, the verifier gives up after reading 1 million instructions (the complexity limit). Since it has to analyze all paths through the program, a program with a small number of instructions can have a very high complexity. That's particularly the case when you have loops and many conditions, as is your case.
Why is the error message confusing? This error message is coming from libbpf.c:
if (ret < 0 && errno == E2BIG) {
fprintf(stderr,
"bpf: %s. Program %s too large (%u insns), at most %d insns\n\n",
strerror(errno), attr->name, insns_cnt, BPF_MAXINSNS);
return -1;
}
Since the bpf(2) syscall returns E2BIG both when the program is too large and when its complexity is too high, libbpf prints the same error message for both cases, always with at most 4096 instructions. I'm confident upstream would accept a patch to improve that error message.

PostgreSQL ECPG database connection issue

I am trying to connect to PostgreSQL database using ecpg program and I am getting below error.
cc testecpg.c
/tmp/ccSzqgA7.o: In function `main':
testecpg.c:(.text+0x5d): undefined reference to `ECPGconnect'
testecpg.c:(.text+0x62): undefined reference to `ECPGget_sqlca'
testecpg.c:(.text+0x70): undefined reference to `sqlprint'
collect2: error: ld returned 1 exit status
testecpg.c file generated after executing ecpg testecpg.pgc
/* Processed by ecpg (4.11.0) */
/* These include files are added by the preprocessor */
#include "/opt/rh/rh-postgresql95/root/usr/include/ecpglib.h"
#include "/opt/rh/rh-postgresql95/root/usr/include/ecpgerrno.h"
#include "/opt/rh/rh-postgresql95/root/usr/include/sqlca.h"
/* End of automatic include section */
#line 1 "testecpg.pgc"
#include <stdio.h>
#include "/opt/rh/rh-postgresql95/root/usr/include/libpq-fe.h"
int main(void)
{
/* exec sql begin declare section */
#line 6 "testecpg.pgc"
char * dbname = "dbname" ;
#line 7 "testecpg.pgc"
char * db = "dbname#hostname:5432" ;
#line 8 "testecpg.pgc"
char * user = "user" ;
#line 9 "testecpg.pgc"
char * passwd = "password" ;
#line 10 "testecpg.pgc"
const char * target = "dbname#hostname:5432" ;
/* exec sql end declare section */
#line 11 "testecpg.pgc"
/* exec sql whenever sqlerror sqlprint ; */
#line 12 "testecpg.pgc"
{ ECPGconnect(0, 0, target , user , passwd , NULL, 0);
#line 13 "testecpg.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 13 "testecpg.pgc"
printf("connection succssfull");
}
Is there any library to be included or any step I have missed?
You forgot to link with the ECPG library.
On Unix systems, that would look somewhat like
cc -o testecpg testecpg.c -lecpg
You have to add the appropriate -I and -L options so that the compiler can find the include files and the libraries.

file read using fgetc adds FF at the end

I'm reading a file using fgetc. File reading starts at an offset.At the end I see 8'hFF getting appended at the end of file.I'm expecting 6 bytes in the file but see 7 in them.I'm not sure why this is happening. Any ideas?
Below is my code:
module file_read();
integer fd,fd1,file_char,status;
logic [7:0] captured_data;
initial begin
fd = $fopen("input_file", "rb");
fd1 =$fopen("write_file","w");
status=$fseek(fd,1872,0);
assert (status);
// while ($fgetc(fd) != `EOF) begin
while (!$feof(fd)) begin
file_char=$fgetc(fd);
$display("file char is %h",file_char);
end
end // initial begin
Below are the file contents(in hex):
last line of input_file(total file size =1878):
0000750: 0000 1567 d48d ...g..
write_file:
0000000: 0000 1567 d48d ff ...g...
Thanks!
The reason you are getting the extra 'hff at the end of the written file is due to how $feof (or generally the foef C function) works. Simply put, it doesn't check if the next read is off the end of the file but if the previous read read off the end of the file. So, if you are reading character by character (byte by byte) using $fgetc, $feof will only return true once $fgetc reads off the end of the file, and returns EOF itself (ie, -1 or 'hff if converted to logic [7:0]). You should be checking for this error condition each time you read a byte, something like this:
integer fd, ch;
...
fd = $fopen("file.bin", "rb");
...
while ((ch = $fgetc(fd)) != -1) begin
$display(ch);
end

Running Program from Call Doesn't Seg Fault

My program writenotes keeps seg faulting when I try to write a note that is too long.
./writenotes lolololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololo
[ * ] Writing notes
Segmentation fault
Anyways, I was trying to write a python script that calls the program and curiously enough, calling it from a python script doesn't bring a seg fault, which I thought was rather peculiar.
Heres this code:
#!/usr/bin/python
from subprocess import call
call(["./writenotes", "lolololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololo"])
Which returns
[ * ] Writing notes
Is this because of parent processing or something like such? How would calling a program through subprocess save a program from a segfault though? Are there other ways to call programs from a script that suffer seg faults?
As a note, the writenotes program was written in C. The other script is python.
You'll almost certainly find your C program is crashing but that Python is hiding that from you. Try instead with:
print call(["./writenotes", "lolololol..."])
and see what you get as a return value.
For example, this program tries to modify a string literal and, when run normally dumps core:
int main (void) {
*"xyzzy" = 'X';
return 0;
}
However, when run from the following script:
from subprocess import call
print call(["./testprog"])
I get the output -11, indicating that signal 11 (usually SIGSEGV) was raised, as per the documentation discussing Popen.returncode which subprocess.call() uses under the covers:
A negative value -N indicates that the child was terminated by signal N (Unix only).
An alternative to checking the return code is to import check_call and CalledProcessError instead of call and then use that function. It will raise an exception if the return code is non-zero.
That's probably not so important if you're only calling one executable (just get the return value in that case) but, if you're doing a lot in sequence, catching an exception from the entire group may be more readable.
Changing the C program to only crash when the first argument is 3:
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
if (argc > 1) {
printf ("hello there %s\n", argv[1]);
if (strcmp (argv[1], "3") == 0)
*"xyzzy" = 'X';
}
return 0;
}
and the script to call it with several different arguments:
from subprocess import check_call, CalledProcessError
try:
check_call(["./testprog", "0"])
check_call(["./testprog", "1"])
check_call(["./testprog", "2"])
check_call(["./testprog", "3"])
check_call(["./testprog", "4"])
check_call(["./testprog", "5"])
check_call(["./testprog", "6"])
check_call(["./testprog", "7"])
check_call(["./testprog", "8"])
check_call(["./testprog", "9"])
except CalledProcessError as e:
print e.cmd, "failed with", e.returncode
else:
print "Everything went well"
shows that in action:
hello there 0
hello there 1
hello there 2
hello there 3
['./testprog', '3'] failed with -11

Why system doesn't return main's value?

[root# test]$ cat return10.c
#include <stdio.h>
int main(int argc, char *argv[]){
return 10;
}
[root# test]$ perl -e 'print system("/path_to_return10")'
2560
I was expecting 10 but got 2560,why?
See $? in perldoc perlvar.
You got 10 * 256 (return value = 10) + 0 * 128 (there was no core dump) + 0 (process wasn't killed by signal).
as specified in the documentation for the system call in perl (http://perldoc.perl.org/functions/system.html):
The return value is the exit status of the program as returned by the
wait call. To get the actual exit value, shift right by eight (see
below).
indeed: 2560 >> 8 = 10