File: messages.c

package info (click to toggle)
libpulp 0.3.16-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,976 kB
  • sloc: ansic: 11,792; python: 1,216; sh: 881; makefile: 871; cpp: 582; asm: 387
file content (185 lines) | stat: -rw-r--r-- 4,277 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 *  libpulp - User-space Livepatching Library
 *
 *  Copyright (C) 2017-2021 SUSE Software Solutions GmbH
 *
 *  This file is part of libpulp.
 *
 *  libpulp is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  libpulp is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with libpulp.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <argp.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <link.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/user.h>
#include <unistd.h>
#include <argp.h>

#include "arguments.h"
#include "config.h"
#include "introspection.h"
#include "messages.h"
#include "msg_queue.h"
#include "ulp_common.h"

static Elf64_Addr
get_msgq_address(const struct ulp_process *p)
{
  struct ulp_dynobj *dyn;
  Elf64_Addr msgq_addr = 0;

  for (dyn = p->dynobj_libpulp; dyn != NULL; dyn = dyn->next) {
    if (dyn->msg_queue) {
      msgq_addr = dyn->msg_queue;
      break;
    }
  }

  return msgq_addr;
}

static void
msgq_print(struct msg_queue *msg_queue)
{
  int bottom = msg_queue->bottom;
  int distance = msg_queue->distance;

  while (distance > 0) {
    putchar(msg_queue->buffer[bottom]);
    bottom = (bottom + 1) % MSGQ_BUFFER_MAX;
    distance--;
  }
}

static void
msgq_debug(struct msg_queue *msg_queue)
{
  int i;
  for (i = 0; i < MSGQ_BUFFER_MAX; i++) {
    if (msg_queue->buffer[i] == '\0')
      putchar('.');
    else
      putchar(msg_queue->buffer[i]);
  }
  putchar('\n');

  for (i = 0; i < MSGQ_BUFFER_MAX; i++) {
    if (msg_queue->bottom == i)
      putchar('B');
    else if (msg_queue->top == i)
      putchar('T');
    else
      putchar(' ');
  }
  putchar('\n');
}

static int
print_message_buffer(const struct ulp_process *p, bool debug)
{
  static struct msg_queue msg_queue;
  int ret;

  Elf64_Addr msgq_addr = get_msgq_address(p);

  memset(&msg_queue, 0, sizeof(struct msg_queue));

  if (!msgq_addr) {
    WARN("could not find libpulp.so message queue in process %d.", p->pid);
    return 1;
  }

  if (attach(p->pid)) {
    DEBUG("unable to attach to %d to read string.", p->pid);
    return 1;
  }

  ret = read_memory((void *)&msg_queue, sizeof(struct msg_queue), p->pid,
                    msgq_addr);

  if (detach(p->pid)) {
    DEBUG("unable to detach from %d.", p->pid);
    return 1;
  }

  if (ret > 0) {
    WARN("could not read libpulp.so message queue in process %d.", p->pid);
    return 1;
  }

  if (debug)
    msgq_debug(&msg_queue);
  else
    msgq_print(&msg_queue);

  return ret;
}

int
run_messages(struct arguments *arguments)
{
  int ret = 0;
  struct ulp_process *target = calloc(1, sizeof(struct ulp_process));

  /* Set the verbosity level in the common introspection infrastructure. */
  ulp_verbose = arguments->verbose;
  ulp_quiet = arguments->quiet;

  if (isnumber(arguments->process_wildcard)) {
    target->pid = atoi(arguments->process_wildcard);
  }
  else {
    WARN("messages only accepts PID when passing -p.");
    ret = 1;
    goto ulp_process_clean;
  }

  ret = initialize_data_structures(target);
  if (ret) {
    WARN("error gathering target process information.");
    ret = 1;
    goto ulp_process_clean;
  }

  ret = print_message_buffer(target, false);
  if (ret > 0) {
    WARN("message queue reading failed.");
    ret = 1;
    goto ulp_process_clean;
  }

ulp_process_clean:
  release_ulp_process(target);
  return ret;
}

struct argp_option *
get_command_option_messages(void)
{
  static struct argp_option options[] = {
    { 0, 0, 0, 0, "Options:", 0 },
    { "verbose", 'v', 0, 0, "Produce verbose output", 0 },
    { "quiet", 'q', 0, 0, "Don't produce any output", 0 },
    { "process", 'p', "process", 0, "Target process name, wildcard, or PID", 0 },
    { 0 }
  };
  return options;
}