Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 44 additions & 11 deletions compiler-rt/lib/asan/asan_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,10 @@ DECLARE_REAL(hsa_status_t, hsa_amd_ipc_memory_attach,
DECLARE_REAL(hsa_status_t, hsa_amd_ipc_memory_detach, void *mapped_ptr)
DECLARE_REAL(hsa_status_t, hsa_amd_vmem_address_reserve_align, void** ptr,
size_t size, uint64_t address, uint64_t alignment, uint64_t flags)
DECLARE_REAL(hsa_status_t, hsa_amd_vmem_address_free, void* ptr, size_t size);
DECLARE_REAL(hsa_status_t, hsa_amd_vmem_address_free, void* ptr, size_t size)
DECLARE_REAL(hsa_status_t, hsa_amd_pointer_info, const void* ptr,
hsa_amd_pointer_info_t* info, void* (*alloc)(size_t),
uint32_t* num_agents_accessible, hsa_agent_t** accessible)

namespace __asan {

Expand Down Expand Up @@ -1452,18 +1455,22 @@ static struct AP64<LocalAddressSpaceView> AP_;
static struct AP32<LocalAddressSpaceView> AP_;
#endif

hsa_status_t asan_hsa_amd_ipc_memory_create(void *ptr, size_t len,
hsa_amd_ipc_memory_t * handle) {
void *ptr_;
size_t len_ = get_allocator().GetActuallyAllocatedSize(ptr);
if (len_) {
hsa_status_t asan_hsa_amd_ipc_memory_create(void* ptr, size_t len,
hsa_amd_ipc_memory_t* handle) {
void* ptr_ = get_allocator().GetBlockBegin(ptr);
AsanChunk* m = ptr_
? instance.GetAsanChunkByAddr(reinterpret_cast<uptr>(ptr_))
: nullptr;
if (ptr_ && m) {
static_assert(AP_.kMetadataSize == 0, "Expression below requires this");
ptr_ = reinterpret_cast<void *>(reinterpret_cast<uptr>(ptr) - kPageSize_);
} else {
ptr_ = ptr;
len_ = len;
uptr p = reinterpret_cast<uptr>(ptr);
uptr p_ = reinterpret_cast<uptr>(ptr_);
if (p == p_ + kPageSize_ && len == m->UsedSize()) {
size_t len_ = get_allocator().GetActuallyAllocatedSize(ptr_);
return REAL(hsa_amd_ipc_memory_create)(ptr_, len_, handle);
}
}
return REAL(hsa_amd_ipc_memory_create)(ptr_, len_, handle);
return REAL(hsa_amd_ipc_memory_create)(ptr, len, handle);
}

hsa_status_t asan_hsa_amd_ipc_memory_attach(const hsa_amd_ipc_memory_t *handle,
Expand Down Expand Up @@ -1540,5 +1547,31 @@ hsa_status_t asan_hsa_amd_vmem_address_free(void* ptr, size_t size,
}
return REAL(hsa_amd_vmem_address_free)(ptr, size);
}

hsa_status_t asan_hsa_amd_pointer_info(const void* ptr,
hsa_amd_pointer_info_t* info,
void* (*alloc)(size_t),
uint32_t* num_agents_accessible,
hsa_agent_t** accessible) {
void* ptr_ = get_allocator().GetBlockBegin(ptr);
AsanChunk* m = ptr_
? instance.GetAsanChunkByAddr(reinterpret_cast<uptr>(ptr_))
: nullptr;
hsa_status_t status = HSA_STATUS_ERROR_NOT_INITIALIZED;
if (ptr_ && m) {
status = REAL(hsa_amd_pointer_info)(ptr, info, alloc, num_agents_accessible,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use ptr_ here instead of ptr? It might be a bit clearer to do so.

Copy link
Author

@ampandey-AMD ampandey-AMD Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want hsa_amd_pointer_info interception to be unwavered and return successfully when ASan is enabled. Here the user pointer ptr is not the actual ASan mapped ptr_. The ROCr runtime, given an interior pointer, returns the base of the whole mapped region (the page-aligned(kPageSize_) start: ptr_) when ASan is enabled.

[guard/unused page] | [user payload of size m->UsedSize()]
^ ptr_ (GetBlockBegin)      ^ ptr (returned to user)

To keep the ASan illusion (that the user pointer is the “base” of the allocation and to hide the leading guard page), we shift the reported agentBaseAddress and hostBaseAddress forward by kPageSize_. We also replace sizeInBytes with m->UsedSize() (user payload only), instead of the full mapping size that includes the guard page.

If we passed ptr_ to the real function we would not add the offset, but then other interceptors (IPC create/attach) that rely on “user base = reported base” would break.

The current chosen scheme below:

  • Export full mapping when necessary (IPC create) using ptr_ and full length.
  • For hsa_amd_pointer_info, keep calling with ptr so runtime finds the allocation, then adjust addresses to present the payload-only view.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not the case that the call at line 1562 to the real pointer info function will return the same result when given either ptr or ptr_? If that is true then I think ptr_ is a better choice since it is the illusion free value passed to the illusion free function.

accessible);
if (status == HSA_STATUS_SUCCESS && info) {
static_assert(AP_.kMetadataSize == 0, "Expression below requires this");
info->agentBaseAddress = reinterpret_cast<void*>(
reinterpret_cast<uptr>(info->agentBaseAddress) + kPageSize_);
info->hostBaseAddress = reinterpret_cast<void*>(
reinterpret_cast<uptr>(info->hostBaseAddress) + kPageSize_);
info->sizeInBytes = m->UsedSize();
}
}
return status;
}

} // namespace __asan
#endif
5 changes: 5 additions & 0 deletions compiler-rt/lib/asan/asan_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,11 @@ hsa_status_t asan_hsa_amd_vmem_address_reserve_align(void** ptr, size_t size,
BufferedStackTrace* stack);
hsa_status_t asan_hsa_amd_vmem_address_free(void* ptr, size_t size,
BufferedStackTrace* stack);
hsa_status_t asan_hsa_amd_pointer_info(const void* ptr,
hsa_amd_pointer_info_t* info,
void* (*alloc)(size_t),
uint32_t* num_agents_accessible,
hsa_agent_t** accessible);
} // namespace __asan
#endif

Expand Down
10 changes: 10 additions & 0 deletions compiler-rt/lib/asan/asan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,15 @@ INTERCEPTOR(hsa_status_t, hsa_amd_vmem_address_free, void* ptr, size_t size) {
return asan_hsa_amd_vmem_address_free(ptr, size, &stack);
}

INTERCEPTOR(hsa_status_t, hsa_amd_pointer_info, const void* ptr,
hsa_amd_pointer_info_t* info, void* (*alloc)(size_t),
uint32_t* num_agents_accessible, hsa_agent_t** accessible) {
AsanInitFromRtl();
ENSURE_HSA_INITED();
return asan_hsa_amd_pointer_info(ptr, info, alloc, num_agents_accessible,
accessible);
}

void InitializeAmdgpuInterceptors() {
ASAN_INTERCEPT_FUNC(hsa_memory_copy);
ASAN_INTERCEPT_FUNC(hsa_amd_memory_pool_allocate);
Expand All @@ -962,6 +971,7 @@ void InitializeAmdgpuInterceptors() {
ASAN_INTERCEPT_FUNC(hsa_amd_ipc_memory_detach);
ASAN_INTERCEPT_FUNC(hsa_amd_vmem_address_reserve_align);
ASAN_INTERCEPT_FUNC(hsa_amd_vmem_address_free);
ASAN_INTERCEPT_FUNC(hsa_amd_pointer_info);
}

void ENSURE_HSA_INITED() {
Expand Down