#include "gdb_wait.h"
#include "x86-cpuid.h"
#include "filestuff.h"
+#include "common/scoped_fd.h"
+#include "common/scoped_mmap.h"
#include <inttypes.h>
static int
perf_event_pt_event_type (int *type)
{
- FILE *file;
- int found;
-
- file = fopen ("/sys/bus/event_source/devices/intel_pt/type", "r");
- if (file == NULL)
+ gdb_file_up file
+ = gdb_fopen_cloexec ("/sys/bus/event_source/devices/intel_pt/type", "r");
+ if (file == nullptr)
return -1;
- found = fscanf (file, "%d", type);
-
- fclose (file);
-
+ int found = fscanf (file.get (), "%d", type);
if (found == 1)
return 0;
return -1;
static struct btrace_target_info *
linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
{
- struct perf_event_mmap_page *header;
- struct btrace_target_info *tinfo;
struct btrace_tinfo_bts *bts;
size_t size, pages;
__u64 data_offset;
int pid, pg;
- tinfo = XCNEW (struct btrace_target_info);
+ gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
+ (XCNEW (btrace_target_info));
tinfo->ptid = ptid;
tinfo->conf.format = BTRACE_FORMAT_BTS;
pid = ptid_get_pid (ptid);
errno = 0;
- bts->file = syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0);
- if (bts->file < 0)
- goto err_out;
+ scoped_fd fd (syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0));
+ if (fd.get () < 0)
+ return nullptr;
/* Convert the requested size in bytes to pages (rounding up). */
pages = ((size_t) conf->size / PAGE_SIZE
/* We try to allocate the requested size.
If that fails, try to get as much as we can. */
+ scoped_mmap data;
for (; pages > 0; pages >>= 1)
{
size_t length;
continue;
/* The number of pages we request needs to be a power of two. */
- header = ((struct perf_event_mmap_page *)
- mmap (NULL, length, PROT_READ, MAP_SHARED, bts->file, 0));
- if (header != MAP_FAILED)
+ data.reset (nullptr, length, PROT_READ, MAP_SHARED, fd.get (), 0);
+ if (data.get () != MAP_FAILED)
break;
}
if (pages == 0)
- goto err_file;
+ return nullptr;
+ struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
+ data.get ();
data_offset = PAGE_SIZE;
#if defined (PERF_ATTR_SIZE_VER5)
/* Check for overflows. */
if ((__u64) size != data_size)
- {
- munmap ((void *) header, size + PAGE_SIZE);
- goto err_file;
- }
+ return nullptr;
}
#endif /* defined (PERF_ATTR_SIZE_VER5) */
- bts->header = header;
- bts->bts.mem = ((const uint8_t *) header) + data_offset;
bts->bts.size = size;
bts->bts.data_head = &header->data_head;
+ bts->bts.mem = (const uint8_t *) data.get () + data_offset;
bts->bts.last_head = 0ull;
+ bts->header = header;
+ bts->file = fd.release ();
- tinfo->conf.bts.size = (unsigned int) size;
- return tinfo;
-
- err_file:
- /* We were not able to allocate any buffer. */
- close (bts->file);
+ data.release ();
- err_out:
- xfree (tinfo);
- return NULL;
+ tinfo->conf.bts.size = (unsigned int) size;
+ return tinfo.release ();
}
#if defined (PERF_ATTR_SIZE_VER5)
static struct btrace_target_info *
linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
{
- struct perf_event_mmap_page *header;
- struct btrace_target_info *tinfo;
struct btrace_tinfo_pt *pt;
- size_t pages, size;
+ size_t pages;
int pid, pg, errcode, type;
if (conf->size == 0)
if (pid == 0)
pid = ptid_get_pid (ptid);
- tinfo = XCNEW (struct btrace_target_info);
+ gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
+ (XCNEW (btrace_target_info));
tinfo->ptid = ptid;
tinfo->conf.format = BTRACE_FORMAT_PT;
pt->attr.exclude_idle = 1;
errno = 0;
- pt->file = syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0);
- if (pt->file < 0)
- goto err;
+ scoped_fd fd (syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0));
+ if (fd.get () < 0)
+ return nullptr;
/* Allocate the configuration page. */
- header = ((struct perf_event_mmap_page *)
- mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
- pt->file, 0));
- if (header == MAP_FAILED)
- goto err_file;
+ scoped_mmap data (nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd.get (), 0);
+ if (data.get () == MAP_FAILED)
+ return nullptr;
+
+ struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
+ data.get ();
header->aux_offset = header->data_offset + header->data_size;
/* We try to allocate the requested size.
If that fails, try to get as much as we can. */
+ scoped_mmap aux;
for (; pages > 0; pages >>= 1)
{
size_t length;
if ((__u64) UINT_MAX < data_size)
continue;
- size = (size_t) data_size;
+ length = (size_t) data_size;
/* Check for overflows. */
- if ((__u64) size != data_size)
+ if ((__u64) length != data_size)
continue;
header->aux_size = data_size;
- length = size;
- pt->pt.mem = ((const uint8_t *)
- mmap (NULL, length, PROT_READ, MAP_SHARED, pt->file,
- header->aux_offset));
- if (pt->pt.mem != MAP_FAILED)
+ aux.reset (nullptr, length, PROT_READ, MAP_SHARED, fd.get (),
+ header->aux_offset);
+ if (aux.get () != MAP_FAILED)
break;
}
if (pages == 0)
- goto err_conf;
+ return nullptr;
- pt->header = header;
- pt->pt.size = size;
+ pt->pt.size = aux.size ();
+ pt->pt.mem = (const uint8_t *) aux.release ();
pt->pt.data_head = &header->aux_head;
+ pt->header = header;
+ pt->file = fd.release ();
- tinfo->conf.pt.size = (unsigned int) size;
- return tinfo;
-
- err_conf:
- munmap((void *) header, PAGE_SIZE);
-
- err_file:
- close (pt->file);
+ data.release ();
- err:
- xfree (tinfo);
- return NULL;
+ tinfo->conf.pt.size = (unsigned int) pt->pt.size;
+ return tinfo.release ();
}
#else /* !defined (PERF_ATTR_SIZE_VER5) */