1 /* 2 * Copyright (c) 2013-2019, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef PT_SECTION_H 30 #define PT_SECTION_H 31 32 #include <stdint.h> 33 #include <stddef.h> 34 35 #if defined(FEATURE_THREADS) 36 # include <threads.h> 37 #endif /* defined(FEATURE_THREADS) */ 38 39 #include "intel-pt.h" 40 41 struct pt_block_cache; 42 43 44 /* A section of contiguous memory loaded from a file. */ 45 struct pt_section { 46 /* The name of the file. */ 47 char *filename; 48 49 /* The offset into the file. */ 50 uint64_t offset; 51 52 /* The (adjusted) size in bytes. The size is truncated to match the 53 * actual file size. 54 */ 55 uint64_t size; 56 57 /* A pointer to OS-specific file status for detecting changes. 58 * 59 * The status is initialized on first pt_section_map() and will be 60 * left in the section until the section is destroyed. This field 61 * is owned by the OS-specific mmap-based section implementation. 62 */ 63 void *status; 64 65 /* A pointer to implementation-specific mapping information - NULL if 66 * the section is currently not mapped. 67 * 68 * This field is set in pt_section_map() and owned by the mapping 69 * implementation. 70 */ 71 void *mapping; 72 73 /* A pointer to an optional block cache. 74 * 75 * The cache is created on request and destroyed implicitly when the 76 * section is unmapped. 77 * 78 * We read this field without locking and only lock the section in order 79 * to install the block cache. 80 * 81 * We rely on guaranteed atomic operations as specified in section 8.1.1 82 * in Volume 3A of the Intel(R) Software Developer's Manual at 83 * http://www.intel.com/sdm. 84 */ 85 struct pt_block_cache *bcache; 86 87 /* A pointer to the iscache attached to this section. 88 * 89 * The pointer is initialized when the iscache attaches and cleared when 90 * it detaches again. There can be at most one iscache attached to this 91 * section at any time. 92 * 93 * In addition to attaching, the iscache will need to obtain a reference 94 * to the section, which it needs to drop again after detaching. 95 */ 96 struct pt_image_section_cache *iscache; 97 98 /* A pointer to the unmap function - NULL if the section is currently 99 * not mapped. 100 * 101 * This field is set in pt_section_map() and owned by the mapping 102 * implementation. 103 */ 104 int (*unmap)(struct pt_section *sec); 105 106 /* A pointer to the read function - NULL if the section is currently 107 * not mapped. 108 * 109 * This field is set in pt_section_map() and owned by the mapping 110 * implementation. 111 */ 112 int (*read)(const struct pt_section *sec, uint8_t *buffer, 113 uint16_t size, uint64_t offset); 114 115 /* A pointer to the memsize function - NULL if the section is currently 116 * not mapped. 117 * 118 * This field is set in pt_section_map() and owned by the mapping 119 * implementation. 120 */ 121 int (*memsize)(const struct pt_section *section, uint64_t *size); 122 123 #if defined(FEATURE_THREADS) 124 /* A lock protecting this section. 125 * 126 * Most operations do not require the section to be locked. All 127 * actual locking should be handled by pt_section_* functions. 128 */ 129 mtx_t lock; 130 131 /* A lock protecting the @iscache and @acount fields. 132 * 133 * We need separate locks to protect against a deadlock scenario when 134 * the iscache is mapping or unmapping this section. 135 * 136 * The attach lock must not be taken while holding the section lock; the 137 * other way round is OK. 138 */ 139 mtx_t alock; 140 #endif /* defined(FEATURE_THREADS) */ 141 142 /* The number of current users. The last user destroys the section. */ 143 uint16_t ucount; 144 145 /* The number of attaches. This must be <= @ucount. */ 146 uint16_t acount; 147 148 /* The number of current mappers. The last unmaps the section. */ 149 uint16_t mcount; 150 }; 151 152 /* Create a section. 153 * 154 * The returned section describes the contents of @file starting at @offset 155 * for @size bytes. 156 * 157 * If @file is shorter than the requested @size, the section is silently 158 * truncated to the size of @file. 159 * 160 * If @offset lies beyond the end of @file, no section is created. 161 * 162 * The returned section is not mapped and starts with a user count of one and 163 * instruction caching enabled. 164 * 165 * Returns zero on success, a negative pt_error_code otherwise. 166 * Returns -pte_internal if @psection is NULL. 167 * Returns -pte_nomem when running out of memory. 168 * Returns -pte_bad_file if @filename cannot be opened. 169 * Returns -pte_invalid if @offset lies beyond @file. 170 * Returns -pte_invalid if @filename is too long. 171 */ 172 extern int pt_mk_section(struct pt_section **psection, const char *filename, 173 uint64_t offset, uint64_t size); 174 175 /* Lock a section. 176 * 177 * Locks @section. The section must not be locked. 178 * 179 * Returns a new section on success, NULL otherwise. 180 * Returns -pte_bad_lock on any locking error. 181 */ 182 extern int pt_section_lock(struct pt_section *section); 183 184 /* Unlock a section. 185 * 186 * Unlocks @section. The section must be locked. 187 * 188 * Returns a new section on success, NULL otherwise. 189 * Returns -pte_bad_lock on any locking error. 190 */ 191 extern int pt_section_unlock(struct pt_section *section); 192 193 /* Add another user. 194 * 195 * Increments the user count of @section. 196 * 197 * Returns zero on success, a negative error code otherwise. 198 * Returns -pte_internal if @section is NULL. 199 * Returns -pte_overflow if the user count would overflow. 200 * Returns -pte_bad_lock on any locking error. 201 */ 202 extern int pt_section_get(struct pt_section *section); 203 204 /* Remove a user. 205 * 206 * Decrements the user count of @section. Destroys the section if the 207 * count reaches zero. 208 * 209 * Returns zero on success, a negative error code otherwise. 210 * Returns -pte_internal if @section is NULL. 211 * Returns -pte_internal if the user count is already zero. 212 * Returns -pte_bad_lock on any locking error. 213 */ 214 extern int pt_section_put(struct pt_section *section); 215 216 /* Attaches the image section cache user. 217 * 218 * Similar to pt_section_get() but sets @section->iscache to @iscache. 219 * 220 * Returns zero on success, a negative error code otherwise. 221 * Returns -pte_internal if @section or @iscache is NULL. 222 * Returns -pte_internal if a different cache is already attached. 223 * Returns -pte_overflow if the attach count would overflow. 224 * Returns -pte_bad_lock on any locking error. 225 */ 226 extern int pt_section_attach(struct pt_section *section, 227 struct pt_image_section_cache *iscache); 228 229 /* Detaches the image section cache user. 230 * 231 * Similar to pt_section_put() but clears @section->iscache. 232 * 233 * Returns zero on success, a negative error code otherwise. 234 * Returns -pte_internal if @section or @iscache is NULL. 235 * Returns -pte_internal if the attach count is already zero. 236 * Returns -pte_internal if @section->iscache is not equal to @iscache. 237 * Returns -pte_bad_lock on any locking error. 238 */ 239 extern int pt_section_detach(struct pt_section *section, 240 struct pt_image_section_cache *iscache); 241 242 /* Return the filename of @section. */ 243 extern const char *pt_section_filename(const struct pt_section *section); 244 245 /* Return the offset of the section in bytes. */ 246 extern uint64_t pt_section_offset(const struct pt_section *section); 247 248 /* Return the size of the section in bytes. */ 249 extern uint64_t pt_section_size(const struct pt_section *section); 250 251 /* Return the amount of memory currently used by the section in bytes. 252 * 253 * We only consider the amount of memory required for mapping @section; we 254 * ignore the size of the section object itself and the size of the status 255 * object. 256 * 257 * If @section is currently not mapped, the size is zero. 258 * 259 * Returns zero on success, a negative pt_error_code otherwise. 260 * Returns -pte_internal if @size of @section is NULL. 261 */ 262 extern int pt_section_memsize(struct pt_section *section, uint64_t *size); 263 264 /* Allocate a block cache. 265 * 266 * Returns zero on success, a negative error code otherwise. 267 * Returns -pte_internal if @section is NULL. 268 * Returns -pte_nomem if the block cache can't be allocated. 269 * Returns -pte_bad_lock on any locking error. 270 */ 271 extern int pt_section_alloc_bcache(struct pt_section *section); 272 273 /* Request block caching. 274 * 275 * The caller must ensure that @section is mapped. 276 */ 277 static inline int pt_section_request_bcache(struct pt_section *section) 278 { 279 if (!section) 280 return -pte_internal; 281 282 if (section->bcache) 283 return 0; 284 285 return pt_section_alloc_bcache(section); 286 } 287 288 /* Return @section's block cache, if available. 289 * 290 * The caller must ensure that @section is mapped. 291 * 292 * The cache is not use-counted. It is only valid as long as the caller keeps 293 * @section mapped. 294 */ 295 static inline struct pt_block_cache * 296 pt_section_bcache(const struct pt_section *section) 297 { 298 if (!section) 299 return NULL; 300 301 return section->bcache; 302 } 303 304 /* Create the OS-specific file status. 305 * 306 * On success, allocates a status object, provides a pointer to it in @pstatus 307 * and provides the file size in @psize. 308 * 309 * The status object will be free()'ed when its section is. 310 * 311 * This function is implemented in the OS-specific section implementation. 312 * 313 * Returns zero on success, a negative error code otherwise. 314 * Returns -pte_internal if @pstatus, @psize, or @filename is NULL. 315 * Returns -pte_bad_image if @filename can't be opened. 316 * Returns -pte_nomem if the status object can't be allocated. 317 */ 318 extern int pt_section_mk_status(void **pstatus, uint64_t *psize, 319 const char *filename); 320 321 /* Perform on-map maintenance work. 322 * 323 * Notifies an attached image section cache about the mapping of @section. 324 * 325 * This function is called by the OS-specific pt_section_map() implementation 326 * after @section has been successfully mapped and @section has been unlocked. 327 * 328 * Returns zero on success, a negative error code otherwise. 329 * Returns -pte_internal if @section is NULL. 330 * Returns -pte_bad_lock on any locking error. 331 */ 332 extern int pt_section_on_map_lock(struct pt_section *section); 333 334 static inline int pt_section_on_map(struct pt_section *section) 335 { 336 if (section && !section->iscache) 337 return 0; 338 339 return pt_section_on_map_lock(section); 340 } 341 342 /* Map a section. 343 * 344 * Maps @section into memory. Mappings are use-counted. The number of 345 * pt_section_map() calls must match the number of pt_section_unmap() 346 * calls. 347 * 348 * This function is implemented in the OS-specific section implementation. 349 * 350 * Returns zero on success, a negative error code otherwise. 351 * Returns -pte_internal if @section is NULL. 352 * Returns -pte_bad_image if @section changed or can't be opened. 353 * Returns -pte_bad_lock on any locking error. 354 * Returns -pte_nomem if @section can't be mapped into memory. 355 * Returns -pte_overflow if the map count would overflow. 356 */ 357 extern int pt_section_map(struct pt_section *section); 358 359 /* Share a section mapping. 360 * 361 * Increases the map count for @section without notifying an attached image 362 * section cache. 363 * 364 * This function should only be used by the attached image section cache to 365 * resolve a deadlock scenario when mapping a section it intends to cache. 366 * 367 * Returns zero on success, a negative error code otherwise. 368 * Returns -pte_internal if @section is NULL. 369 * Returns -pte_internal if @section->mcount is zero. 370 * Returns -pte_bad_lock on any locking error. 371 */ 372 extern int pt_section_map_share(struct pt_section *section); 373 374 /* Unmap a section. 375 * 376 * Unmaps @section from memory. 377 * 378 * Returns zero on success, a negative error code otherwise. 379 * Returns -pte_internal if @section is NULL. 380 * Returns -pte_bad_lock on any locking error. 381 * Returns -pte_internal if @section has not been mapped. 382 */ 383 extern int pt_section_unmap(struct pt_section *section); 384 385 /* Read memory from a section. 386 * 387 * Reads at most @size bytes from @section at @offset into @buffer. @section 388 * must be mapped. 389 * 390 * Returns the number of bytes read on success, a negative error code otherwise. 391 * Returns -pte_internal if @section or @buffer are NULL. 392 * Returns -pte_nomap if @offset is beyond the end of the section. 393 */ 394 extern int pt_section_read(const struct pt_section *section, uint8_t *buffer, 395 uint16_t size, uint64_t offset); 396 397 #endif /* PT_SECTION_H */ 398