Adjust AccessProvider api to current security-server.
[platform/core/test/security-tests.git] / tests / common / gdbbacktrace.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /*
18  * @file        gdbbacktrace.cpp
19  * @author      Pawel Broda (p.broda@partner.samsung.com)
20  * @version     1.0
21  * @brief       API providing backtrace
22  */
23
24 #include <fcntl.h>
25 #include <iomanip>
26 #include <iostream>
27 #include <sstream>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include "gdbbacktrace.h"
32
33 namespace {
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");
37
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");
41
42 void print_colour(const std::string& err)
43 {
44     std::cerr << COLOUR_CODE_RED << err << COLOUR_CODE_RESET << std::endl;
45 }
46
47 bool backtrace_parse_line(const std::string& line, std::ostream& result, size_t line_number)
48 {
49     if (line.empty() || line[0] != '#')
50         return false;
51
52     // backtrace info - omit waitpid(), backtrace() and DPL frames
53     if (line.find(FRAME_PATTERN_WAITPID) == 0)
54         return false;
55
56     if (line.find(FRAME_PATTERN_BACKTRACE) == 0)
57         return false;
58
59     if (line.find(FRAME_PATTERN_DPL) != std::string::npos)
60         return false;
61
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"
66
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 <<
72                   std::endl;
73         return true;
74     }
75
76     return false;
77 }
78
79 std::string backtrace_read(int fd)
80 {
81     FILE *bt_fd = fdopen(fd, "r");
82     char read_buffer[MAX_BACKTRACE_LINE_LENGTH];
83     std::ostringstream result;
84
85     result << std::endl;
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))
89             ++line_number;
90     }
91
92     fclose(bt_fd);
93
94     // check if gdbbacktrace() called directly from the test
95     if (line_number == 2)
96         return "";
97
98     return result.str();
99 }
100 } // anonymous backtrace namespace end
101
102 std::string gdbbacktrace(void)
103 {
104     std::string pid_buf = std::to_string(getpid());
105     int pipe_fd[2];
106     pipe(pipe_fd);
107
108     int child_pid = fork();
109     if (child_pid == -1)
110     {
111         print_colour("fork needed to run gdb in batch mode failed...");
112         return "";
113     }
114
115     if (child_pid == 0) {
116         int devnull = open("/dev/null", O_WRONLY);
117         if (dup2(devnull, 2) == -1)
118             exit(2);
119         if (dup2(pipe_fd[1], 1) == -1)
120             exit(2);
121         execlp("/usr/bin/gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", "--pid",
122                pid_buf.c_str(), NULL);
123         // gdb failed to start...
124         exit(1);
125     }
126
127     int status;
128     int waitpid_res = waitpid(child_pid, &status, 0);
129
130     close(pipe_fd[1]);
131
132     std::string result;
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...");
139     } else {
140         result.append(backtrace_read(pipe_fd[0]));
141     }
142
143     close(pipe_fd[0]);
144
145     return result;
146 }