Skip to content

Commit 485862e

Browse files
committed
[profile] Avoid duplicating or leaking VMO
Now that write data continously into the memory mapping, we don't need to keep the VMO handle around after it has been mapped. This change also ensures that the VMO is always closed on error. Differential Revision: https://reviews.llvm.org/D76963
1 parent f88000a commit 485862e

File tree

1 file changed

+47
-58
lines changed

1 file changed

+47
-58
lines changed

compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ COMPILER_RT_VISIBILITY unsigned lprofRuntimeCounterRelocation(void) {
4444
}
4545
COMPILER_RT_VISIBILITY void lprofSetRuntimeCounterRelocation(unsigned Value) {}
4646

47-
/* VMO that contains the profile data for this module. */
48-
static zx_handle_t __llvm_profile_vmo;
49-
/* Current offset within the VMO where data should be written next. */
50-
static uint64_t __llvm_profile_offset;
51-
5247
static const char ProfileSinkName[] = "llvm-profile";
5348

5449
static inline void lprofWrite(const char *fmt, ...) {
@@ -62,50 +57,65 @@ static inline void lprofWrite(const char *fmt, ...) {
6257
__sanitizer_log_write(s, ret + 1);
6358
}
6459

60+
struct lprofVMOWriterCtx {
61+
/* VMO that contains the profile data for this module. */
62+
zx_handle_t Vmo;
63+
/* Current offset within the VMO where data should be written next. */
64+
uint64_t Offset;
65+
};
66+
6567
static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
6668
uint32_t NumIOVecs) {
69+
struct lprofVMOWriterCtx *Ctx = (struct lprofVMOWriterCtx *)This->WriterCtx;
70+
6771
/* Compute the total length of data to be written. */
6872
size_t Length = 0;
6973
for (uint32_t I = 0; I < NumIOVecs; I++)
7074
Length += IOVecs[I].ElmSize * IOVecs[I].NumElm;
7175

7276
/* Resize the VMO to ensure there's sufficient space for the data. */
73-
zx_status_t Status =
74-
_zx_vmo_set_size(__llvm_profile_vmo, __llvm_profile_offset + Length);
77+
zx_status_t Status = _zx_vmo_set_size(Ctx->Vmo, Ctx->Offset + Length);
7578
if (Status != ZX_OK)
7679
return -1;
7780

7881
/* Copy the data into VMO. */
7982
for (uint32_t I = 0; I < NumIOVecs; I++) {
8083
size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
8184
if (IOVecs[I].Data) {
82-
Status = _zx_vmo_write(__llvm_profile_vmo, IOVecs[I].Data,
83-
__llvm_profile_offset, Length);
85+
Status = _zx_vmo_write(Ctx->Vmo, IOVecs[I].Data, Ctx->Offset, Length);
8486
if (Status != ZX_OK)
8587
return -1;
8688
} else if (IOVecs[I].UseZeroPadding) {
8789
/* Resizing the VMO should zero fill. */
8890
}
89-
__llvm_profile_offset += Length;
91+
Ctx->Offset += Length;
9092
}
9193

9294
/* Record the profile size as a property of the VMO. */
93-
_zx_object_set_property(__llvm_profile_vmo, ZX_PROP_VMO_CONTENT_SIZE,
94-
&__llvm_profile_offset,
95-
sizeof(__llvm_profile_offset));
95+
_zx_object_set_property(Ctx->Vmo, ZX_PROP_VMO_CONTENT_SIZE, &Ctx->Offset,
96+
sizeof(Ctx->Offset));
9697

9798
return 0;
9899
}
99100

100-
static void initVMOWriter(ProfDataWriter *This) {
101+
static void initVMOWriter(ProfDataWriter *This, struct lprofVMOWriterCtx *Ctx) {
101102
This->Write = lprofVMOWriter;
102-
This->WriterCtx = NULL;
103+
This->WriterCtx = Ctx;
103104
}
104105

105106
/* This method is invoked by the runtime initialization hook
106107
* InstrProfilingRuntime.o if it is linked in. */
107108
COMPILER_RT_VISIBILITY
108109
void __llvm_profile_initialize(void) {
110+
/* Check if there is llvm/runtime version mismatch. */
111+
if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
112+
lprofWrite("LLVM Profile: runtime and instrumentation version mismatch: "
113+
"expected %d, but got %d\n",
114+
INSTR_PROF_RAW_VERSION,
115+
(int)GET_VERSION(__llvm_profile_get_version()));
116+
return;
117+
}
118+
109119
/* This symbol is defined as weak and initialized to -1 by the runtimer, but
110120
* compiler will generate a strong definition initialized to 0 when runtime
111121
* counter relocation is used. */
@@ -114,22 +124,17 @@ void __llvm_profile_initialize(void) {
114124
return;
115125
}
116126

117-
/* Don't create VMO if it has been alread created. */
118-
if (__llvm_profile_vmo != ZX_HANDLE_INVALID) {
119-
lprofWrite("LLVM Profile: VMO has already been created\n");
120-
return;
121-
}
122-
123127
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
124128
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
125129
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
126-
const uint64_t CountersOffset = sizeof(__llvm_profile_header) +
127-
(DataSize * sizeof(__llvm_profile_data));
130+
const uint64_t CountersOffset =
131+
sizeof(__llvm_profile_header) + (DataSize * sizeof(__llvm_profile_data));
128132

129133
zx_status_t Status;
130134

131135
/* Create VMO to hold the profile data. */
132-
Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &__llvm_profile_vmo);
136+
zx_handle_t Vmo = ZX_HANDLE_INVALID;
137+
Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &Vmo);
133138
if (Status != ZX_OK) {
134139
lprofWrite("LLVM Profile: cannot create VMO: %s\n",
135140
_zx_status_get_string(Status));
@@ -140,65 +145,49 @@ void __llvm_profile_initialize(void) {
140145
char VmoName[ZX_MAX_NAME_LEN];
141146
snprintf(VmoName, sizeof(VmoName), "%" PRIu64 ".profraw",
142147
lprofGetLoadModuleSignature());
143-
_zx_object_set_property(__llvm_profile_vmo, ZX_PROP_NAME, VmoName,
144-
strlen(VmoName));
145-
146-
/* Duplicate the handle since __sanitizer_publish_data consumes it. */
147-
zx_handle_t Handle;
148-
Status =
149-
_zx_handle_duplicate(__llvm_profile_vmo, ZX_RIGHT_SAME_RIGHTS, &Handle);
150-
if (Status != ZX_OK) {
151-
lprofWrite("LLVM Profile: cannot duplicate VMO handle: %s\n",
152-
_zx_status_get_string(Status));
153-
_zx_handle_close(__llvm_profile_vmo);
154-
__llvm_profile_vmo = ZX_HANDLE_INVALID;
155-
return;
156-
}
157-
158-
/* Publish the VMO which contains profile data to the system. */
159-
__sanitizer_publish_data(ProfileSinkName, Handle);
160-
161-
/* Use the dumpfile symbolizer markup element to write the name of VMO. */
162-
lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName);
163-
164-
/* Check if there is llvm/runtime version mismatch. */
165-
if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
166-
lprofWrite("LLVM Profile: runtime and instrumentation version mismatch: "
167-
"expected %d, but got %d\n",
168-
INSTR_PROF_RAW_VERSION,
169-
(int)GET_VERSION(__llvm_profile_get_version()));
170-
return;
171-
}
148+
_zx_object_set_property(Vmo, ZX_PROP_NAME, VmoName, strlen(VmoName));
172149

173150
/* Write the profile data into the mapped region. */
174151
ProfDataWriter VMOWriter;
175-
initVMOWriter(&VMOWriter);
152+
struct lprofVMOWriterCtx Ctx = {.Vmo = Vmo, .Offset = 0};
153+
initVMOWriter(&VMOWriter, &Ctx);
176154
if (lprofWriteData(&VMOWriter, 0, 0) != 0) {
177155
lprofWrite("LLVM Profile: failed to write data\n");
156+
_zx_handle_close(Vmo);
178157
return;
179158
}
180159

181160
uint64_t Len = 0;
182-
Status = _zx_vmo_get_size(__llvm_profile_vmo, &Len);
161+
Status = _zx_vmo_get_size(Vmo, &Len);
183162
if (Status != ZX_OK) {
184163
lprofWrite("LLVM Profile: failed to get the VMO size: %s\n",
185164
_zx_status_get_string(Status));
165+
_zx_handle_close(Vmo);
186166
return;
187167
}
188168

189169
uintptr_t Mapping;
190170
Status =
191-
_zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
192-
0, __llvm_profile_vmo, 0, Len, &Mapping);
171+
_zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
172+
Vmo, 0, Len, &Mapping);
193173
if (Status != ZX_OK) {
194174
lprofWrite("LLVM Profile: failed to map the VMO: %s\n",
195175
_zx_status_get_string(Status));
176+
_zx_handle_close(Vmo);
196177
return;
197178
}
198179

180+
/* Publish the VMO which contains profile data to the system. Note that this
181+
* also consumes the VMO handle. */
182+
__sanitizer_publish_data(ProfileSinkName, Vmo);
183+
184+
/* Use the dumpfile symbolizer markup element to write the name of VMO. */
185+
lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName);
186+
199187
/* Update the profile fields based on the current mapping. */
200188
__llvm_profile_counter_bias = (intptr_t)Mapping -
201-
(uintptr_t)__llvm_profile_begin_counters() + CountersOffset;
189+
(uintptr_t)__llvm_profile_begin_counters() +
190+
CountersOffset;
202191
}
203192

204193
#endif

0 commit comments

Comments
 (0)