2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file gdbbacktrace.cpp
19 * @author Pawel Broda (p.broda@partner.samsung.com)
21 * @brief API providing backtrace
30 #include <sys/types.h>
31 #include "gdbbacktrace.h"
34 const size_t MAX_BACKTRACE_LINE_LENGTH = 1024;
35 const std::string COLOUR_CODE_RED("\033[31m");
36 const std::string COLOUR_CODE_RESET("\033[0m");
38 const std::string FRAME_PATTERN_WAITPID("#0 ");
39 const std::string FRAME_PATTERN_BACKTRACE("#1 ");
40 const std::string FRAME_PATTERN_DPL("in DPL::Test");
42 void print_colour(const std::string& err)
44 std::cerr << COLOUR_CODE_RED << err << COLOUR_CODE_RESET << std::endl;
47 bool backtrace_parse_line(const std::string& line, std::ostream& result, size_t line_number)
49 if (line.empty() || line[0] != '#')
52 // backtrace info - omit waitpid(), backtrace() and DPL frames
53 if (line.find(FRAME_PATTERN_WAITPID) == 0)
56 if (line.find(FRAME_PATTERN_BACKTRACE) == 0)
59 if (line.find(FRAME_PATTERN_DPL) != std::string::npos)
62 // example std::string line content:
63 // "#5 0x000000000040198d in main () at ../src/backtrace.cpp:105"
64 // should result in (i.e. would be written into char line_formatted):
65 // "main () at ../src/backtrace.cpp:105"
67 char line_formatted[MAX_BACKTRACE_LINE_LENGTH];
68 line_formatted[0] = '\0';
69 sscanf(line.c_str(), "%*s %*s %[^\n]", line_formatted);
70 if (line_formatted[0] != '\0') {
71 result << "#" << std::left << std::setw(2) << line_number << " " << line_formatted <<
79 std::string backtrace_read(int fd)
81 FILE *bt_fd = fdopen(fd, "r");
82 char read_buffer[MAX_BACKTRACE_LINE_LENGTH];
83 std::ostringstream result;
86 size_t line_number = 1;
87 while (fgets(read_buffer, sizeof(read_buffer) - 1, bt_fd) != NULL) {
88 if (backtrace_parse_line(read_buffer, result, line_number))
94 // check if gdbbacktrace() called directly from the test
100 } // anonymous backtrace namespace end
102 std::string gdbbacktrace(void)
104 std::string pid_buf = std::to_string(getpid());
108 int child_pid = fork();
111 print_colour("fork needed to run gdb in batch mode failed...");
115 if (child_pid == 0) {
116 int devnull = open("/dev/null", O_WRONLY);
117 if (dup2(devnull, 2) == -1)
119 if (dup2(pipe_fd[1], 1) == -1)
121 execlp("/usr/bin/gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", "--pid",
122 pid_buf.c_str(), NULL);
123 // gdb failed to start...
128 int waitpid_res = waitpid(child_pid, &status, 0);
133 if (waitpid_res == -1) {
134 print_colour("Backtrace not available (waitpid failed)");
135 } else if (status == 2) {
136 print_colour("Error: file descriptor duplication failed... failed to start gdb...");
137 } else if (status != 0) {
138 print_colour("Error: no gdb or failed to start gdb...");
140 result.append(backtrace_read(pipe_fd[0]));