aboutsummaryrefslogtreecommitdiffstats
path: root/memcheck/memcheck_util.h
blob: d15eedf7999dab57c917dc281a9e0ad3257679cd (plain)
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* Copyright (C) 2007-2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program 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 General Public License for more details.
*/

/*
 * Contains declarations of utility routines for memchecker framework.
 */

#ifndef QEMU_MEMCHECK_MEMCHECK_UTIL_H
#define QEMU_MEMCHECK_MEMCHECK_UTIL_H

#include "memcheck_common.h"
#include "elff/elff_api.h"
#include "exec.h"

#ifdef __cplusplus
extern "C" {
#endif

// =============================================================================
// Transfering data between guest and emulator address spaces.
// =============================================================================

/* Copies buffer residing in the guest's virtual address space to a buffer
 * in the emulator's address space.
 * Param:
 *  guest_address - Address of the bufer in guest's virtual address space.
 *  qemu_address - Address of the bufer in the emulator's address space.
 *  buffer_size - Byte size of the guest's buffer.
 */
void memcheck_get_guest_buffer(void* qemu_address,
                               target_ulong guest_address,
                               size_t buffer_size);

/* Copies buffer residing in the emulator's address space to a buffer in the
 * guest's virtual address space.
 * Param:
 *  qemu_address - Address of the bufer in the emulator's address space.
 *  guest_address - Address of the bufer in guest's virtual address space.
 *  buffer_size - Byte size of the emualtor's buffer.
 */
void memcheck_set_guest_buffer(target_ulong guest_address,
                               const void* qemu_address,
                               size_t buffer_size);

/* Copies zero-terminated string residing in the guest's virtual address space
 * to a string buffer in emulator's address space.
 * Param:
 *  qemu_str - Address of the string bufer in the emulator's address space.
 *  guest_str - Address of the string in guest's virtual address space.
 *  qemu_buffer_size - Size of the emulator's string buffer.
 * Return
 *  Length of the string that has been copied.
 */
size_t memcheck_get_guest_string(char* qemu_str,
                                 target_ulong guest_str,
                                 size_t qemu_buffer_size);

/* Copies zero-terminated string residing in the guest's kernel address space
 * to a string buffer in emulator's address space.
 * Param:
 *  qemu_str - Address of the string bufer in the emulator's address space.
 *  guest_str - Address of the string in guest's kernel address space.
 *  qemu_buffer_size - Size of the emulator's string buffer.
 * Return
 *  Length of the string that has been copied.
 */
size_t memcheck_get_guest_kernel_string(char* qemu_str,
                                        target_ulong guest_str,
                                        size_t qemu_buffer_size);

// =============================================================================
// Helpers for transfering memory allocation information.
// =============================================================================

/* Copies memory allocation descriptor from the guest's address space to the
 * emulator's memory.
 * Param:
 *  qemu_address - Descriptor address in the emulator's address space where to
 *      copy descriptor.
 *  guest_address - Descriptor address in the guest's address space.
 */
static inline void
memcheck_get_malloc_descriptor(MallocDesc* qemu_address,
                               target_ulong guest_address)
{
    memcheck_get_guest_buffer(qemu_address, guest_address, sizeof(MallocDesc));
}

/* Copies memory allocation descriptor from the emulator's memory to the guest's
 * address space.
 * Param:
 *  guest_address - Descriptor address in the guest's address space.
 *  qemu_address - Descriptor address in the emulator's address space where to
 *  copy descriptor.
 */
static inline void
memcheck_set_malloc_descriptor(target_ulong guest_address,
                               const MallocDesc* qemu_address)
{
    memcheck_set_guest_buffer(guest_address, qemu_address, sizeof(MallocDesc));
}

/* Copies memory free descriptor from the guest's address space to the
 * emulator's memory.
 * Param:
 *  qemu_address - Descriptor address in the emulator's address space where to
 *      copy descriptor.
 *  guest_address - Descriptor address in the guest's address space.
 */
static inline void
memcheck_get_free_descriptor(MallocFree* qemu_address,
                             target_ulong guest_address)
{
    memcheck_get_guest_buffer(qemu_address, guest_address, sizeof(MallocFree));
}

/* Copies memory allocation query descriptor from the guest's address space to
 * the emulator's memory.
 * Param:
 *  guest_address - Descriptor address in the guest's address space.
 *  qemu_address - Descriptor address in the emulator's address space where to
 *      copy descriptor.
 */
static inline void
memcheck_get_query_descriptor(MallocDescQuery* qemu_address,
                              target_ulong guest_address)
{
    memcheck_get_guest_buffer(qemu_address, guest_address,
                              sizeof(MallocDescQuery));
}

/* Fails allocation request (TRACE_DEV_REG_MALLOC event).
 * Allocation request failure is reported by zeroing 'libc_pid' filed in the
 * allocation descriptor in the guest's address space.
 * Param:
 *  guest_address - Allocation descriptor address in the guest's address space,
 *      where to record failure.
 */
void memcheck_fail_alloc(target_ulong guest_address);

/* Fails free request (TRACE_DEV_REG_FREE_PTR event).
 * Free request failure is reported by zeroing 'libc_pid' filed in the free
 * descriptor in the guest's address space.
 * Param:
 *  guest_address - Free descriptor address in the guest's address space, where
 *      to record failure.
 */
void memcheck_fail_free(target_ulong guest_address);

/* Fails memory allocation query request (TRACE_DEV_REG_QUERY_MALLOC event).
 * Query request failure is reported by zeroing 'libc_pid' filed in the query
 * descriptor in the guest's address space.
 * Param:
 *  guest_address - Query descriptor address in the guest's address space, where
 *      to record failure.
 */
void memcheck_fail_query(target_ulong guest_address);

// =============================================================================
// Misc. utility routines.
// =============================================================================

/* Converts PC address in the translated block to a corresponded PC address in
 * the guest address space.
 * Param:
 *  tb_pc - PC address in the translated block.
 * Return:
 *  Corresponded PC address in the guest address space on success, or NULL if
 *  conversion has failed.
 */
static inline target_ulong
memcheck_tpc_to_gpc(target_ulong tb_pc)
{
    const TranslationBlock* tb = tb_find_pc(tb_pc);
    return tb != NULL ? tb_search_guest_pc_from_tb_pc(tb, tb_pc) : 0;
}

/* Invalidates TLB table pages that contain given memory range.
 * This routine is called after new entry is inserted into allocation map, so
 * every access to the allocated block will cause __ld/__stx_mmu to be called.
 * Param:
 *  start - Beginning of the allocated block to invalidate pages for.
 *  end - End of (past one byte after) the allocated block to invalidate pages
 *      for.
 */
void invalidate_tlb_cache(target_ulong start, target_ulong end);

/* Gets routine, file path and line number information for a PC address in the
 * given module.
 * Param:
 *  abs_pc - PC address.
 *  rdesc - Mapped memory range descriptor for the module containing abs_pc.
 *  info - Upon successful return will contain routine, file path and line
 *      information for the given PC address in the given module.
 *      NOTE: Pathnames, saved into this structure are contained in mapped
 *      sections of the symbols file for the module addressed by module_path.
 *      Thus, pathnames are accessible only while elff_handle returned from this
 *      routine remains opened.
 *      NOTE: each successful call to this routine requires the caller to call
 *      elff_free_pc_address_info for Elf_AddressInfo structure.
 *  elff_handle - Upon successful return will contain a handle to the ELFF API
 *      that wraps symbols file for the module, addressed by module_path. The
 *      handle must remain opened for as long as pathnames in the info structure
 *      are accessed, and must be eventually closed via call to elff_close.
 * Return:
 *  0 on success, 1, if symbols file for the module has not been found, or -1 on
 *  other failures. If a failure is returned from this routine content of info
 *  and elff_handle parameters is undefined.
 */
int memcheck_get_address_info(target_ulong abs_pc,
                              const MMRangeDesc* rdesc,
                              Elf_AddressInfo* info,
                              ELFF_HANDLE* elff_handle);

/* Dumps content of an allocation descriptor to stdout.
 * Param desc - Allocation descriptor to dump.
 * print_flags - If 1, flags field of the descriptor will be dumped to stdout.
 *      If 0, flags filed will not be dumped.
 * print_proc_info - If 1, allocator's process information for the descriptor
 *      will be dumped to stdout. If 0, allocator's process information will
 *      not be dumped.
 */
void memcheck_dump_malloc_desc(const MallocDescEx* desc,
                               int print_flags,
                               int print_proc_info);

#ifdef __cplusplus
};  /* end of extern "C" */
#endif

#endif  // QEMU_MEMCHECK_MEMCHECK_UTIL_H