Stuck in Stallman's GDB book trying debug m4 (macro processor) 'bug' example: m4 executable i have is a direct bin in /bin (nothing ".../gnu/ ./m4") - gdb

(There is another post here in Stackoverflow: (Which version of m4 does the author of Debugging with GDB use?), but answer referred links are broken and the solution doesn't look much deep or to the point. I have to say i tried them and also tried to look in other m4 versions in the gnu repository, but even that: "len_lquote = strlen(lquote);" looks deprecated since 2006 version, oldest i found).
VERY EASY EXPLANATION: first example in Stallman GDB book refers to a "./m4" executable (first weird sensation with that "./"), allegedly to be present in some (some old standard installation, perhaps?):
/gnu/m4 (?)
or
/work/Editorial/gdb/gnu/m4/ (?)
(and as i pointed, it looks to be executed with './' like it was indeed not like an environment executable [like mine. My "m4" that i installed through "sudo apt install m4" for the purpose]).
The problem is that if i run "gdb m4", it doesn't do the anything similar with the book's m4:
SHOULD BE (for example, setting a breakpoint in a KNOWN function. KNOWN, because i guess it should be some .c or something like that that GDB should load/consult in parallel with the executable, no?):
(gdb) break m4_changequote
Breakpoint 1 at 0x62f4: file builtin.c, line 879.
MINE:
$ gdb m4
GNU gdb (Debian 12.1-4+b1) 12.1 Copyright (C)
2022 Free Software Foundation, Inc. (......) Reading symbols from
m4... (No debugging symbols found in m4)
(gdb) break m4_changequote
Function "m4_changequote" not defined. Make breakpoint pending on
future shared library load? (y or [n]) n
Any USEFUL (direct to the point) help?
Any SOLUTION?
Any EQUIVALENT path?

VERY EASY EXPLANATION: first example in Stallman GDB book refers to a "./m4" executable (first weird sensation with that "./"), allegedly to be present in some (some old standard installation, perhaps?)
You are coming to this problem with the wrong set of assumptions.
In general, you most often use GDB on your own programs, i.e. programs you coded yourself. You usually debug these programs in the directory in which you built them, which is the current directory. On UNIX, current directory is named ., and if you want to refer to a program in your current directory, you use ./program notation.
In the book, Stallman is debugging m4 which he worked on and built.
You are trying to debug m4 which you didn't build, and thus you are having problems following the book.
I suggest that you actually download m4 sources and build it yourself (it should be as simple as ./configure && make), and then follow the book.
Debugging the system-provided m4 is also possible, but that's not what the book is about.
Update:
I did my homework and went through many files (.c, .h, etc) in many folders of m4 versions and i couldn't find anything like what you pointed back in your 2009 post: "...You can download any version of m4, change len_lquote = strlen(lquote); to len_lquote = strlen(rquote); in set_quotes(), and then redo the sample debugging session. ...".
The 2009 post referenced above is apparently this one.
I downloaded m4 version using:
git clone git://git.sv.gnu.org/m4
cd m4
git checkout branch-1.4
In src/input.c, I see this code:
719 void
720 set_quotes (const char *lq, const char *rq)
721 {
722 free (lquote.string);
723 free (rquote.string);
724
725 /* POSIX states that with 0 arguments, the default quotes are used.
726 POSIX XCU ERN 112 states that behavior is implementation-defined
727 if there was only one argument, or if there is an empty string in
728 either position when there are two arguments. We allow an empty
729 left quote to disable quoting, but a non-empty left quote will
730 always create a non-empty right quote. See the texinfo for what
731 some other implementations do. */
732 if (!lq)
733 {
734 lq = DEF_LQUOTE;
735 rq = DEF_RQUOTE;
736 }
737 else if (!rq || (*lq && !*rq))
738 rq = DEF_RQUOTE;
739
740 lquote.string = xstrdup (lq);
741 lquote.length = strlen (lquote.string);
742 rquote.string = xstrdup (rq);
743 rquote.length = strlen (rquote.string);
744 }
Obviously there is no longer len_lquote = strlen(lquote);, but the equivalent statement is now lquote.length = strlen (lquote.string); on line 741.
To introduce a bug, you would change line 741 to read lquote.length = strlen (rquote.string);
But suppose you really want the source to match what was described in the book. The book was first published in 1988, and the very first version of input.c in the Git repo is from 2000, so we need to find older version of m4 sources.
I found a reference to m4-1.0.3.tar.Z from 1992 here, and the file itself here: http://www.nic.funet.fi/index/gnu/funet/historical-funet-gnu-area-from-early-1990s/m4-1.0.3.tar.Z
In that TAR file, m4-1.0.3/input.c does have the source you are looking for:
555 void
556 set_quotes (char *lq, char *rq)
557 {
558 if (lquote != def_lquote)
559 xfree (lquote);
560 if (rquote != def_rquote)
561 xfree (rquote);
562
563 lquote = (lq == NULL) ? def_lquote : xstrdup (lq);
564 rquote = (rq == NULL) ? def_rquote : xstrdup (rq);
565
566 len_lquote = strlen (lquote);
567 len_rquote = strlen (rquote);
568 }
Beware: that source is very old and does not build with modern compilers (GCC-12.2.0 in my case). You'll need to get an ancient version of GCC to build it.

Related

Visual C++ for linux 'illegal characters in path' Error

I'm having problems running C++ programs through Visual C++ for Linux to a Raspberry Pi.
When I first tried a sample running a program, it worked. A couple weeks later, when I tried this again (now) it failed in this error.
The program only uses cstdio library so it should work. I've looked around and some people say it's because g++ can't find libraries or something.
The Error form the Error list is: Exception occurred while copying sources to remote machine - illegal characters in path.
and it also points me to line 162 of Linux.targets, which is:
162 <CopySources
163 Sources="#(FinalSourcesToCopyRemotely)"
164 AdditionalSources="#(AdditionalSourcesToCopyRemotely)"
165 ProjectDir="$(ProjectDir)"
166 …(continues on)
In the program output, it also says something similar to, 'CopySources - FAILED'
Thanks
I've figured it out - The filename/solution name can't have spaces (in my case). (I'm new to this so I am unfamiliar with this stuff.)

Valgrind: fatal error: memcheck.h: No such file or directory

We are trying to track down a Conditional jump or move depends on uninitialised value in a C++ project reported by Valgrind. The address provided in the finding is not really helpful because it points to the end of a GCC extended assembly block, and not the actual variable causing the trouble.
According to the Valgrind's Eliminating undefined values with Valgrind, the easy way, we can use VALGRIND_CHECK_MEM_IS_DEFINED or VALGRIND_CHECK_VALUE_IS_DEFINED after including <memcheck.h>. Additionally, those macros or functions are apparently documented in the header file (there is definitely no man page for them).
However, when I include <memcheck.h> or <valgrind/memcheck.h>, it results in:
fatal error: memcheck.h: No such file or directory
Based on Stack Overflow's How do I find which rpm package supplies a file I'm looking for?, I performed a RPM file search, but its returning 0 hits for memcheck.h.
QUESTIONS
The blog article is a bit dated. Does the information still apply?
If the information is accurate, then where do I find memcheck.h?
$ uname -a
Linux localhost.localdomain 4.1.4-200.fc22.x86_64 #1 SMP Tue Aug 4 03:22:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --version
g++ (GCC) 5.1.1 20150618 (Red Hat 5.1.1-4)
...
$ valgrind --version
valgrind-3.10.1
You have to install the RPM valgrind-devel which contains memcheck.h.
The *-devel packages are typically located in the "optional" repositories (e.g. rhel-x86_64-server-optional-6 on RHEL 6). Also, you can find the RPM on Google, download it, and install it on its own. With either approach, memcheck.h is typically placed in /usr/include/valgrind once installed.
Another way to dig into uninitialised value error with valgrind is to
use the embedded gdbserver.
You can then put breakpoints in your program, and interactively
check the definedness of various addresses/length using various
memcheck monitor commands such as:
check_memory [addressable|defined] <addr> [<len>]
check that <len> (or 1) bytes at <addr> have the given accessibility
and outputs a description of <addr>
See e.g. http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.monitor-commands
for more information

Can visual c++ 2013 do what Purify and Quntify do?

We develop a console application using VC 6.0, Purify, PC-Lint, and Quantify on Windows XP. VC6 will not work on Windows 7 and 8. I have looked at our options for development environments if we were to upgrade to Windows 8. Our application is standard C++ console application. Virtually all of our users are on Linux. Does anyone have experience with VC++ Pro 2013 or 2012 for cross platform c++ development? Specifically, can it do memory bounds checking, memory leak checking, and code performance analysis (how much time each function takes)?
Can visual c++ 2013 do what Purify and Quantify do?
Well, its not so much "can one do everything the other does". Its more like an intersection, and use them all to get the most coverage.
Purify is a runtime checker, so it will usually outperform Visual Studio's built-in memory checking facilities. But Purify does not do static analysis, so you will need to use Visual Studio. Its one big partnership.
I have looked at our options for development environments
...
Our application is [cross-platform] standard C++ console application.
The Bike Shedding begins... This is a great opportunity since you are writing portable code. So many folks write code that runs on one platform, they loose the diagnostics from other tools on other platforms.
Everything below is free (except Enterprise Code Analysis under Visual Studio Enterprise), and if you can get through the process cleanly then you'll have fairly solid code.
Windows
Use Visual Studio (any edition) and turn up warnings. They include /WAll and /W4. If you have Visual Studio Enterprise, be sure to add Enterprise Code Analysis or add the /analyze switch.
You get basic memory checking in Visual Studio. I'm not sure how the latest Purity works with it. (I don't use it because I write cross-platform code and use Linux for the heavy duty memory checking).
There's other things you should be doing for a Windows platform. You can find a discussion of development toolchains at OWASP's C-Based Toolchain Hardening.
Linux
Be sure to support GCC, Clang, and ICC. When using them be sure to crank up warnings, including -Wall, -Wextra, and -Wconversion. GCC is the mainstay, and your code probably works well on it. ICC is Intel's compiler, and its ruthless about removing undefined behavior. If your code breaks under ICC, its probably because the compiler/optimizer removed some undefined behavior (see Clang's undefined sanitizer below on how to locate the offending code).
Clang 3.3 really shines with its sanitizers (Clang 3.2 and below don't have them). Be sure to run with -fsanitize=address and -fsanitize=undefined. The sanitizers add runtime checkers and looks for violations during execution. The more self tests you have, the better. A complete list of sanitizers is available a Clang's Controlling Code Generation.
The Clang 3.3 recipes are below. They include how to fetch Clang, hot to build Clang, and how to execute your tests using the santizers.
After you get through compilation with GCC, Clang, and ICC, run the program under Valgrind. Valgrind is another dynamic memory checker.
There's other things you should be doing for a Linux platform. You can find a discussion of development toolchains at OWASP's C-Based Toolchain Hardening.
To download and build Clang 3.3 with the latest:
wget http://llvm.org/releases/3.3/llvm-3.3.src.tar.gz
wget http://llvm.org/releases/3.3/cfe-3.3.src.tar.gz
wget http://llvm.org/releases/3.3/compiler-rt-3.3.src.tar.gz
# wget http://llvm.org/releases/3.3/lldb-3.3.src.tar.gz
tar xvf llvm-3.3.src.tar.gz
cd llvm-3.3.src/tools
tar xvf ../../cfe-3.3.src.tar.gz
mv cfe-3.3.src clang
# tar xvf ../../lldb-3.3.src.tar.gz
# mv lldb-3.3.src/ lldb
cd ..
cd projects
tar xvf ../../compiler-rt-3.3.src.tar.gz
mv compiler-rt-3.3.src/ compiler-rt
cd ..
./configure --enable-optimized --prefix=/usr/local
make -j4
# Pause to wait for the password prompt
read -p "Press [Enter] key to install..."
# Begin install
sudo make install
# Install does not copy asan_symbolize.py
sudo cp projects/compiler-rt/lib/asan/scripts/asan_symbolize.py /usr/local/bin
# Install does not install scan-build and scan-view
# Perform the copy, and/or put them on-path
sudo mkdir /usr/local/bin/scan-build
sudo cp -r tools/clang/tools/scan-build /usr/local/bin
sudo mkdir /usr/local/bin/scan-view
sudo cp -r tools/clang/tools/scan-view /usr/local/bin
To use Clang:
export CC=/usr/local/bin/clang
export CXX=/usr/local/bin/clang++
export CFLAGS="-g3 -fsanitize=undefined"
export CXXFLAGS="-g3 -fsanitize=undefined -fno-sanitize=vptr"
./configure
make
make check | /usr/local/bin/asan_symbolize.py
If you get any memory issue it will look similar to the following (taken from Squid 3.3.9 Self Test Failures on Mac OS X 10.8):
==76794==ERROR: AddressSanitizer: global-buffer-overflow on address
0x000105ad50d2 at pc 0x105a364ab bp 0x7fff5a23f720 sp 0x7fff5a23f718
READ of size 19 at 0x000105ad50d2 thread T0
#0 0x105a364aa in MemBuf::append MemBuf.cc:248
#1 0x105a4ef57 in testHttpReply::testSanityCheckFirstLine
testHttpReply.cc:197
#2 0x1068d71d1 in CppUnit::TestCaseMethodFunctor::operator()() const (in
libcppunit-1.12.1.dylib) + 33
#3 0x1068cd9a3 in CppUnit::DefaultProtector::protect(CppUnit::Functor
const&, CppUnit::ProtectorContext const&) (in libcppunit-1.12.1.dylib) + 35
#4 0x1068d4d88 in CppUnit::ProtectorChain::ProtectFunctor::operator()()
const (in libcppunit-1.12.1.dylib) + 24
#5 0x1068d45e8 in CppUnit::ProtectorChain::protect(CppUnit::Functor const&,
CppUnit::ProtectorContext const&) (in libcppunit-1.12.1.dylib) + 456
#6 0x1068dcf78 in CppUnit::TestResult::protect(CppUnit::Functor const&,
CppUnit::Test*, std::string const&) (in libcppunit-1.12.1.dylib) + 56
#7 0x1068d6d1d in CppUnit::TestCase::run(CppUnit::TestResult*) (in
libcppunit-1.12.1.dylib) + 285
#8 0x1068d77b6 in
CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) (in
libcppunit-1.12.1.dylib) + 54
#9 0x1068d76be in CppUnit::TestComposite::run(CppUnit::TestResult*) (in
libcppunit-1.12.1.dylib) + 30
#10 0x1068d77b6 in
CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) (in
libcppunit-1.12.1.dylib) + 54
#11 0x1068d76be in CppUnit::TestComposite::run(CppUnit::TestResult*) (in
libcppunit-1.12.1.dylib) + 30
#12 0x1068dcde1 in CppUnit::TestResult::runTest(CppUnit::Test*) (in
libcppunit-1.12.1.dylib) + 33
#13 0x1068de9a5 in CppUnit::TestRunner::run(CppUnit::TestResult&,
std::string const&) (in libcppunit-1.12.1.dylib) + 53
#14 0x105a55a97 in main testMain.cc:31
#15 0x7fff90af07e0 in start (in libdyld.dylib) + 0
#16 0x0
0x000105ad50d2 is located 46 bytes to the left of global variable '.str28' from
'tests/testHttpReply.cc' (0x105ad5100) of size 16
'.str28' is ascii string 'HTTP/1.1 -000
0x000105ad50d2 is located 0 bytes to the right of global variable '.str27' from
'tests/testHttpReply.cc' (0x105ad50c0) of size 18
'.str27' is ascii string 'HTTP/1.10 Okay
And here's what undefined behavior and an illegal shift looks like (taken from Postgres's Clang 3.3 findings and Illegal Shifts):
make check
...
vacuuming database template1 ... localtime.c:127:20: runtime error:
left shift of negative value -1
pg_lzcompress.c:601:5: runtime error: left shift of negative value -68
pg_lzcompress.c:601:5: runtime error: left shift of negative value -68
pg_lzcompress.c:385:16: runtime error: left shift of negative value -68
pg_lzcompress.c:615:4: runtime error: left shift of negative value -68
If you are failing under Intel's ICC, then be sure to run it under Clang with -fsanitize=undefined because ICC will silently remove any offending code. Its the easiest way I've found to find the offending code.

Profiling in GO - No symbols

I'm trying to profile a GO program using the procedure described here:
http://blog.golang.org/2011/06/profiling-go-programs.html
.
However pprof shows addresses instead of function names in output:
(pprof) top10
Total: 2113 samples
298 14.1% 14.1% 298 14.1% 0000000000464d34
179 8.5% 22.6% 179 8.5% 0000000000418e83
157 7.4% 30.0% 157 7.4% 0000000000418e60
112 5.3% 35.3% 112 5.3% 0000000000403293
101 4.8% 40.1% 101 4.8% 0000000000464d4f
83 3.9% 44.0% 83 3.9% 000000000040329c
77 3.6% 47.7% 77 3.6% 0000000000418e7a
62 2.9% 50.6% 62 2.9% 0000000000456a38
37 1.8% 52.3% 37 1.8% 0000000000418e41
37 1.8% 54.1% 37 1.8% 0000000000435f57
Has anyone experienced that and found a fix?
There is a mention here of a 6prof tool to be used in alternative to the procedure described above. Does anyone know if it's still maintained and where to find it?
I'm using go1.0.2 on Win7 64.
Thanks!
I fixed the perl script to work under Windows.
Details here: http://exneehilo.blogspot.com.au/2012/07/profiling-go-with-pprof-under-windows.html
I haven't checked it myself, but as far as I remember, the problem with pprof script is that it uses standard (mingw) version of nm, instead of Go specific nm. Go distro has its own nm program:
C:>go tool nm
usage: nm [-aghnsTu] file ...
go tool nm: exit status 1
C:>
that understands all Go binary formats, while nm program that comes with mingw does not. Look inside pprof perl script for nm_commands variable. It lists couple of possible candidates, but none of them is what you want. If you change that to point to Go nm instead, it should work.
Feel free to report bug here http://code.google.com/p/go/issues. I think it used to work, because 6nm is listed in nm_commands, but Go nm has been renamed to just nm and moved out of user PATH.
Alex
I had similar problem.
Solution was in actual building application. So when I build with "go build test_app.go" and than run "./test_app" And after that I got right profiling file with function names in it.

Windows vs. Linux GCC argv[0] value [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Get path of executable
I'm programming on Windows using MinGW, gcc 4.4.3. When I use the main function like this:
int main(int argc, char* argv[]){
cout << "path is " << argv[0] << endl;
}
On Windows I get a full path like this: "C:/dev/stuff/bin/Test". When I run the same application on Linux, however, I get some sort of relative path: "bin/Test". It's breaking my application! Any idea on how to make sure the path is absolute on both systems?
No, there isn't. Under most shells on Linux, argv[0] contains exactly what the user typed to run the binary. This allows binaries to do different things depending on what the user types.
For example, a program with several different command-line commands may install the binary once, and then hard-link the various different commands to the same binary. For example, on my system:
$ ls -l /usr/bin/git*
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git
-rwxr-xr-x 2 root wheel 121453 16 May 18:43 /usr/bin/git-cvsserver
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git-receive-pack
-rwxr-xr-x 2 root wheel 1021264 16 May 18:44 /usr/bin/git-shell
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git-upload-archive
-rwxr-xr-x 2 root wheel 1042560 16 May 18:44 /usr/bin/git-upload-pack
-rwxr-xr-x 1 root wheel 323897 16 May 18:43 /usr/bin/gitk
Notice how some of these files have exactly the same size. More investigation reveals:
$ stat /usr/bin/git
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git
$ stat /usr/bin/git-receive-pack
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git-receive-pack
The inode number (459240) is identical and so these are two links to the same file on disk. When run, the binary uses the contents of argv[0] to determine which function to execute. You can see this (sort of) in the code for Git's main().
argv array
argv[0] is a parameter like any others: it can be an arbitrary NUL terminated byte string. It can be the empty string. It is whatever the launching process wants.
By default, the shell with set argv[0] to whatever is used to name the program: a name looked-up in $PATH, a relative or an absolute path. It can be a symbolic link or a regular file.
To invoke a program with some other value, with zsh (dunno with other shells) use:
ARGV0=whatever_you_want some_program arguments
If you really need the path to the executable, you cannot use the command line on Unix.
Linux only
On Linux: /proc/self/exe is a symbolic link to the executable file.
You can readlink it. You can also stat or open it directly.
Renaming and soft link
A normal soft link is a dumb string, and doesn't know what happens to its target (if it exists at all). But the /proc/self/exe soft link is magic.
In case of renaming, the soft-but-magic-link will follow renaming. In case there are several hard links, it will follow the name of the particular hard link that was used. (So different hard links to the same file are not perfectly equivalent under Linux.)
If this hard link is unlinked, I think " (deleted)" is appended to the value of the symbolic link. Note that this is a valid file name, so another unrelated file could have that name.
In any case, the symbolic link is a hard link to the file, so you can stat or open it directly.
I don't think you can count on anything on a network file system if the binary is renamed or unlinked on another system than the one where the executable is launched.
Security considerations
When your program gets to use the /proc/self/exe special file, it is possible for the file used to launch your program to be unlinked or renamed. This should be taken seriously in case the program is privileged (SUID or Set Capabilities): even if the user doesn't have write access to the original "Set Something" binary, he may be able to make a hard link to it if he has write access to a directory on the same file system, so he may be able to change the name if a running privileged binary.
By the time you readlink, the value returned may refer to another file. (Of course, there is always an unavoidable race condition with opening the result of readlink.)
As usual, NFS does not provides all the same guaranties that local file systems have.
There is no way to ensure that argv[0] is an absolute path because it is supposed to be exactly how the user invoked the program. So, if on a Linux command line you invoke your program via ./bin/Test, then argv[0] should be exactly "./bin/Test".
It seems like a bug in MinGW's runtime if when you invoke the program from a command prompt via .\bin\Test, argv[0] is "C:/dev/stuff/bin/Test". With the latest MinGW (gcc version 4.5.2), invoking a binary via .\bin\Test means argv[0] is ".\bin\Test". A Microsoft Visual C++-built binary (cl version 16.00.40219.01) invoked via .\bin\Test also has ".\bin\Test" for argv[0].