- Как отлаживать программы на языке C в Linux с помощью отладчика GDB
- Основные аспекты использования GDB
- Пример использования GDB
- Заключение
- Linux Applications Debugging Techniques/The debugger
- Contents
- Preparations [ edit | edit source ]
- The «symbol server» [ edit | edit source ]
- Source Code [ edit | edit source ]
- Remote debugging [ edit | edit source ]
- Attaching to a process [ edit | edit source ]
- Debugging programs that spawn multiple children [ edit | edit source ]
- Embedding breakpoints in the source [ edit | edit source ]
- Data breakpoints (watchpoints) [ edit | edit source ]
- Breakpoints conditional on caller [ edit | edit source ]
- The text user interface [ edit | edit source ]
- .gdbinit [ edit | edit source ]
- C++ support [ edit | edit source ]
- How to Enable Shell Script Debugging Mode in Linux?
Как отлаживать программы на языке C в Linux с помощью отладчика GDB
Оригинал: How to debug C programs in Linux using gdb
Автор: Himanshu Arora
Дата публикации: 16 января 2017 г.
Перевод: А.Панин
Дата перевода: 7 марта 2017 г.
Вне зависимости от вашего опыта программирования, все разработанное вами программное обеспечение просто не может не содержать ошибок. По этой причине поиск и устранение ошибок являются одними из наиболее важных задач, выполняемых в рамках цикла разработки программного обеспечения. Хотя и существует несколько способов выявления ошибок в коде (тестирование, самостоятельный аудит кода и другие), для этой цели создан отдельный тип программного обеспечения под названием «отладчики», позволяющего вам найти проблемный фрагмент кода и максимально быстро исправить его.
Если вы разрабатываете программное обеспечение на языках C/C++ или пользуетесь такими более редкими языками программирования, как Fortran и Modula-2, вам будет полезно знать о существовании отличного отладчика под названием GDB , который позволяет достаточно просто отлаживать ваш код, помогая устранять ошибки и различные проблемные конструкции. В рамках данной статьи мы постараемся обсудить основные приемы работы с GDB, включая некоторые полезные функции/параметры данного инструмента.
Но перед тем, как двинуться дальше, стоит упомянуть о том, что все инструкции и примеры, приведенные в данной статье, были протестированы в системе Ubuntu 14.04 LTS. В статье был использован пример кода на языке C; в качестве командной оболочки использовалась командная оболочка Bash (версии 4.3.11); также стоит сказать о том, что для отладки тестовой программы использовался отладчик GDB версии 7.7.1.
Основные аспекты использования GDB
По сути, GDB позволяет вам заглянуть внутрь программы в процессе ее исполнения, способствуя тем самым идентификации и локализации проблемы. Мы обсудим методику использования отладчика GDB на основе примера в следующем разделе, но перед этим стоит рассмотреть несколько основных аспектов использования отладчика, которые окажутся полезными в будущем.
Во-первых, для успешного использования таких отладчиков, как GDB, вам придется компилировать вашу программу таким образом, чтобы компилятор генерировал отладочную информацию, необходимую отладчикам. Например, в случае компилятора GCC, который будет впоследствии использоваться для компиляции примера программы на языке C, вам придется дополнительно передать параметр -g на этапе компиляции кода.
Вы можете получить дополнительную информацию о данном параметре компилятора на его странице руководства .
На следующем шаге следует убедиться в том, что отладчик GDB установлен в вашей системе. Если он не установлен и вы используете основанный на Debian дистрибутив, такой, как Ubuntu, вы можете установить данный инструмент с помощью следующей команды:
Инструкции по установке отладчика в других дистрибутивах приведены на данной странице .
Теперь, когда вы скомпилировали вашу программу со специальным параметром компилятора для ее подготовки к отладке и установили в систему отладчик GDB, вы можете выполнить программу в режиме отладки с помощью следующей команды:
Хотя данная команда и инициирует запуск отладчика GDB, ваша программа не начнет исполняться сразу же после его запуска. В этот момент у вас имеется возможность задать параметры отладки. Например, вы можете установить точку останова, сообщающую отладчику GDB о том, что следует приостановить исполнение программы на строке с определенным номером или функции.
Для того, чтобы инициировать исполнение вашей программы, вам придется выполнить следующую команду GDB:
Стоит упомянуть и о том, что в том случае, если вашей программе нужно передать некие аргументы командной строки, вы можете передать их вместе с данной командной. Например:
GDB поддерживает большое количество полезных команд, которые находят свое применение в процессе отладки программных продуктов. Мы обсудим некоторые из них в следующем разделе.
Пример использования GDB
Теперь вы имеете базовое представление об отладчике GDB и принципе его использования. Поэтому предлагаю рассмотреть пример и применить полученные знания на практике. Это код примера:
В общем, данный код берет каждое значение из массива val , устанавливает это значение в качестве значения целочисленной переменной out , после чего рассчитывает значение переменной tot путем суммирования ее предыдущего значения и результата вычисления 0xffffffff/out .
Проблема заключается в том, что после запуска скомпилированного кода выводится следующее сообщение об ошибке:
Итак, для отладки кода в первую очередь следует скомпилировать код программы с использованием параметра компилятора -g . Это команда компиляции:
Далее предлагаю запустить отладчик GDB и сообщить ему имя исполняемого файла, который мы хотим отлаживать. Для этого используется следующая команда:
Теперь следует обратить внимание на то, что в процессе исполнения программы выводится сообщение об ошибке «floating point exception» и, как многие из вас наверняка знают, данная ошибка обычно связана с делением произвольного значения на ноль. Помня об этом, я помещаю точку останова в строку под номером 11, где осуществляется деление. Это делается следующим образом:
Обратите внимание на приветствие отладчика (gdb) , после которого я ввел команду break 11 .
Теперь я прошу GDB начать исполнение программы:
При достижении точки останова в первый раз GDB выводит следующую информацию:
Как несложно заметить, отладчик вывел код строки, в которой была установлена точка останова. Теперь давайте выведем текущее значение переменной out . Это делается следующим образом:
Очевидно, что отладчик вывел значение 5 . На основе этой информации можно сделать вывод, что в текущее время программа работает корректно. Поэтому я прошу отладчик продолжить исполнение программы до достижения следующей точки останова путем ввода команды c .
Я продолжаю выполнять аналогичные действия до того момента, пока не вижу нулевое значение переменной out .
Теперь для подтверждения предположения о том, что имеется проблема, я использую команду GDB s (или step ) вместо c . Это делается потому, что я хочу, чтобы строка 11, на которой на данный момент остановилось исполнение программы, была исполнена, в результате чего исполнение программы может аварийно завершиться.
В результате случается следующее:
Да, приведенный выше вывод подтверждает, что системный сигнал генерируется именно в этой строке. Окончательное подтверждение происходит при попытке повторного исполнения команды s :
Вы можете отлаживать свои программы с помощью GDB аналогичным образом.
Заключение
В данной статье мы рассмотрели лишь малую толику возможностей отладчика GDB, доступных для изучения и использования. Обратитесь к странице руководства GDB для получения дополнительной информации о данном инструменте и попытайтесь самостоятельно использовать его для отладки своего кода. Рассматриваемый отладчик не является дружелюбным, но трата времени на его изучение вполне оправдана.
Источник
Linux Applications Debugging Techniques/The debugger
Contents
Preparations [ edit | edit source ]
Someday some hard to reproduce issue will be found on a production machine. Typically, such a machine is difficult to access, has no development environment and nothing can be installed on it. At most it will have gdb, but very likely not. Typically also, the heaviest user will be the one to find the issue and typically still, the heaviest user is the one being the bigger — money-wise. And that issue has to be root cause diagnosed and fixed.
Unless the application has been prepared for this forensic gathering moment, not much can be done to diagnose where the issue is. Thus, preparations should start with compilation:
- Have a «symbol server» and make sure it is reacheable. Compile on the symbol server.
- Compile the release with debugging symbols. Strip them if you do not want to ship them but keep them.
- Ship gdbserver with the application for remote debugging.
These preparations will allow one to:
- Debug the application running on any machine, including machines where there is no gdb installed.
- Debug from any machine that has network visibility to the symbol server.
Also, think beforehand how would you debug on the machine:
- Embed a breakpoint in the code, at hard of reach places of interest, then
- Start the application
- Attach to it with the debugger
- Wait until the breakpoint is hit
The «symbol server» [ edit | edit source ]
One way to easily reach the right code from within the debugger is to build the binaries within an auto-mounted folder, each build in its own sub-folder. The same auto-mount share should be accessible from the machine you are debugging on.
Debian [ edit | edit source ]
- Install autofs
- In /etc/auto.master uncomment the line:
- In /etc/exports export the folder:
- As root: restart autofs & nfs and export the build share:
Redhat [ edit | edit source ]
- Export the folder: edit /etc/exports
- As root (RedHat): service autofs start
Finally, build the binaries within the automounted directory on the build machine (here the build machine is bear):
Notice the filename path that is resolved with the symbol information:
If the symbols have been stripped from the binaries, point gdb to the folders where the symbols are with the debug-file-directory directive.
References [ edit | edit source ]
Source Code [ edit | edit source ]
To point the debugger to the source files:
Remote debugging [ edit | edit source ]
- On the machine where the application runs (appmachine):
- If gdbserver is not present, copy it over.
- Start the application.
- Start gdbserver: gdbserver gdbmachine:2345 --attach program
- On gdbmachine:
- At the gdb prompt, enter: target remote appmachine:2345
Sometimes you may have to tunnel over ssh:
- On gdbmachine:
- ssh -L 5432:appmachine:2345 user@appmachine
- At the gdb prompt: target remote localhost:5432
References [ edit | edit source ]
Attaching to a process [ edit | edit source ]
Find out the PID of the process, then:
Debugging programs that spawn multiple children [ edit | edit source ]
- set detach-on-fork off
- see «all-stop» vs «non-stop» modes in the GDB documentation and their related settings
Embedding breakpoints in the source [ edit | edit source ]
On x86 platforms:
Or a more elaborate one:
This will break into the debugger on hard to reach conditions:
References [ edit | edit source ]
Data breakpoints (watchpoints) [ edit | edit source ]
Watchpoints can be implemented either in software either in hardware if the CPU supports it. Typically on an Intel processor there are eight debug registers out of which only four can be used for hardware breakpoints and this limits the number of watchpoints system wide.
Breakpoints conditional on caller [ edit | edit source ]
This requires gdb 7.9 or later, configured with python support:
The text user interface [ edit | edit source ]
GDB features a text user interface for code, disassembler and registers. For instance:
- Ctrl-x 1 will show the code pane
- Ctrl-x a will hide the TUI panes
None of the GUI interfaces to gdb (Qt Creator stands out for being intuitive and easy to use) can offer access to all of the gdb functionality.
curses gdb offers an improved TUI. A comprehensive list of debugger GUIs is available here.
Reverse debugging [ edit | edit source ]
As an example, reverse debugging is a functionality no GUI offers access to:
Register watch [ edit | edit source ]
You can watch registers. Note this will force the debugger to single step the debugged program and it will run very slowly:
References [ edit | edit source ]
.gdbinit [ edit | edit source ]
As a note, in upcoming gdb releases, .gdbinit will be replaced by gdb-gdb.gdb:
C++ support [ edit | edit source ]
Canned gdb macros [ edit | edit source ]
Mangling [ edit | edit source ]
gdb might need a bit of guidance with C++11 binaries:
Templates [ edit | edit source ]
One can eventually use templight to debug and profile templates.
Источник
How to Enable Shell Script Debugging Mode in Linux?
Linux is a very popular operating system especially among developers and in the computer science world, as it comes along with its powerful ability to play with the kernel. Major Linux distributions (often referred to as Linux distros) are Open Source (Source Code available and can be modified on request) in nature like Ubuntu, CentOS, etc.
Bash is a very popular shell scripting language that is executed in the back-end when you open the terminal in Linux. DevOps (Operations Team responsible for deployment more often) use Bash/Shell scripting (series of commands written in a file to execute together in an ordered fashion) to automate usual/minimalist/trivial tasks for example running checking of time stamps on which file is generated/updated, checking for a number of files, etc.
Debugging is terminology that means the process of identifying errors and possibly resolving them in computer hardware or software. Just like all the other programming/coding languages debugging is crucial in bash/shell scripting in order to understand the flow of the program and resolve any errors if they occur.
In this article let us discuss two ways of debugging a shell script, to help strengthen the understanding I will try to take 1 simple shell script (Hello World and List) and will build on it with an example of a conditional shell script (odd/even).
1. Using bash options (-x, -n, -v): The following are various options explained in detail:
Output:
Figure 1: Tracing HelloWorld.sh Output using -x option of bash.
In the above figure we see code traced (printed) before it is executed, then its relevant output, and further the code for listing (ls) is traced followed by its execution. Let’s build further with the following example (OddEven.sh) which prompts the user for input and tells whether the entered number is Odd/Even Number.
Output:
Figure 2: Tracing OddEven.sh Output using -x option of bash.
Similar to the prior example each line of code is traced before it is executed.
- -n:It helps in checking the syntax errors if there are any in the shell script prior to executing it. With a boom in the technology of cloud computing, it is essential to know various command-line options to check syntax errors. It is difficult to have GUI (Graphical User Interfaces) or designated IDEs (Integrated Development Environments) on Virtual Machines executing in the cloud. So this option helps with getting syntax checks performed on a script using CLI (Command Line Interface). Let’s understand its application using the example below which has OddEven.sh Script which by purpose has a small syntax error.
Output:
Figure 3: Checking Syntax-Errors in OddEven.sh using -n option of bash.
When the script is executed with -n option output shows the exact line number location of the line of code where it got a syntax error. Then when the error is fixed and run it again with the same option the following output is shown-
Figure 4: After correcting Syntax-Errors in OddEven.sh using -n option of bash.
This shows that the script is syntax-errors-free.
- -v:If there is a need to read the comments and entire script while the script is executing, then -v option helps us achieve this goal. The following example screenshot shows how -v and -x differ from each other and how we can use -v option. The same OddEven.sh script file as shown in the above examples is used in the below example.
Figure 5: View Comments and Code while they are executing in OddEven.sh
In the above code all comments and code are visible (like the entire “if block” and not only the lines which are executed).
One slight drawback with this is there is a need to perform debug checks on the entire script, if the script is huge it is quite tough/tedious to find useful insights from the output of -x option. So let us have a look at debugging only some specific part of a script in the Next way of Debugging.
2. Using set -x inside script for the specific script.
Let’s assume we want to debug/trace only a certain logical part of OddEven.sh Script and not the whole script. We can set -x flag before the code we want to debug and then set it again back to +x where tracing of code needs to be disabled. The following example code and screenshot help us depict this scenario.
Output:
Figure 6: Debugging/Tracing on certain lines of code in a Shell Script.
Источник