Skip to content

Commit 5946a2c

Browse files
Fix printf issue with printing pointers from 32bit kernel on 64bit system.
Change-Id: I77771b4ebe6c4335d51dc1834f0b8f9df2a069a4
1 parent 2e4a64f commit 5946a2c

File tree

7 files changed

+89
-31
lines changed

7 files changed

+89
-31
lines changed

runtime/kernel/kernel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,10 @@ class Kernel : public BaseObject<_cl_kernel> {
358358
return isParentKernel && getProgram()->getBlockKernelManager()->getIfBlockUsesPrintf();
359359
}
360360

361+
bool is32Bit() const {
362+
return kernelInfo.gpuPointerSize == 4;
363+
}
364+
361365
int32_t getDebugSurfaceBti() const {
362366
if (kernelInfo.patchInfo.pAllocateSystemThreadSurface) {
363367
return kernelInfo.patchInfo.pAllocateSystemThreadSurface->BTI;

runtime/os_interface/linux/print.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, Intel Corporation
2+
* Copyright (c) 2017 - 2018, Intel Corporation
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -39,10 +39,6 @@ size_t simple_sprintf(char *output, size_t outputSize, const char *format, const
3939
return snprintf(output, outputSize, format, value);
4040
}
4141

42-
size_t simple_sprintf(char *output, size_t outputSize, const char *format, void *value) {
43-
return snprintf(output, outputSize, format, value);
44-
}
45-
4642
template size_t simple_sprintf<float>(char *output, size_t output_size, const char *format, float value);
4743
template size_t simple_sprintf<double>(char *output, size_t output_size, const char *format, double value);
4844
template size_t simple_sprintf<char>(char *output, size_t output_size, const char *format, char value);

runtime/os_interface/windows/print.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, Intel Corporation
2+
* Copyright (c) 2017 - 2018, Intel Corporation
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -80,10 +80,6 @@ size_t simple_sprintf(char *output, size_t outputSize, const char *format, const
8080
return sprintf_s(output, outputSize, format, value);
8181
}
8282

83-
size_t simple_sprintf(char *output, size_t outputSize, const char *format, void *value) {
84-
return sprintf_s(output, outputSize, format, value);
85-
}
86-
8783
template size_t simple_sprintf<float>(char *output, size_t output_size, const char *format, float value);
8884
template size_t simple_sprintf<double>(char *output, size_t output_size, const char *format, double value);
8985
template size_t simple_sprintf<char>(char *output, size_t output_size, const char *format, char value);

runtime/program/print_formatter.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ void PrintFormatter::stripVectorTypeConversion(char *format) {
119119

120120
size_t PrintFormatter::printToken(char *output, size_t size, const char *formatString) {
121121
PRINTF_DATA_TYPE type(PRINTF_DATA_TYPE::INVALID);
122-
size_t ret = 0;
123122
read(&type);
124123

125124
switch (type) {
@@ -134,10 +133,7 @@ size_t PrintFormatter::printToken(char *output, size_t size, const char *formatS
134133
case PRINTF_DATA_TYPE::LONG:
135134
return typedPrintToken<int64_t>(output, size, formatString);
136135
case PRINTF_DATA_TYPE::POINTER:
137-
ret = typedPrintToken<void *>(output, size, formatString);
138-
// always pad read data to 8 bytes when handling pointers
139-
offset += 8 - sizeof(void *);
140-
return ret;
136+
return printPointerToken(output, size, formatString);
141137
case PRINTF_DATA_TYPE::DOUBLE:
142138
return typedPrintToken<double>(output, size, formatString);
143139
case PRINTF_DATA_TYPE::VECTOR_BYTE:
@@ -157,6 +153,30 @@ size_t PrintFormatter::printToken(char *output, size_t size, const char *formatS
157153
}
158154
}
159155

156+
size_t PrintFormatter::printStringToken(char *output, size_t size, const char *formatString) {
157+
int index = 0;
158+
int type = 0;
159+
// additional read to discard the token
160+
read(&type);
161+
read(&index);
162+
if (type == static_cast<int>(PRINTF_DATA_TYPE::STRING)) {
163+
return simple_sprintf(output, size, formatString, kernel.getKernelInfo().queryPrintfString(index));
164+
} else {
165+
return simple_sprintf(output, size, formatString, 0);
166+
}
167+
}
168+
169+
size_t PrintFormatter::printPointerToken(char *output, size_t size, const char *formatString) {
170+
uint64_t value = {0};
171+
read(&value);
172+
173+
if (kernel.is32Bit()) {
174+
value &= 0x00000000FFFFFFFF;
175+
}
176+
177+
return simple_sprintf(output, size, formatString, value);
178+
}
179+
160180
char PrintFormatter::escapeChar(char escape) {
161181
switch (escape) {
162182
case 'n':

runtime/program/print_formatter.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, Intel Corporation
2+
* Copyright (c) 2017 - 2018, Intel Corporation
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -63,6 +63,8 @@ class PrintFormatter {
6363
protected:
6464
void printString(const char *formatString, const std::function<void(char *)> &print);
6565
size_t printToken(char *output, size_t size, const char *formatString);
66+
size_t printStringToken(char *output, size_t size, const char *formatString);
67+
size_t printPointerToken(char *output, size_t size, const char *formatString);
6668

6769
char escapeChar(char escape);
6870
bool isConversionSpecifier(char c);
@@ -108,8 +110,9 @@ class PrintFormatter {
108110
for (int i = 0; i < valueCount; i++) {
109111
read(&value);
110112
charactersPrinted += simple_sprintf(output + charactersPrinted, size - charactersPrinted, strippedFormat, value);
111-
if (i < valueCount - 1)
113+
if (i < valueCount - 1) {
112114
charactersPrinted += simple_sprintf(output + charactersPrinted, size - charactersPrinted, "%c", ',');
115+
}
113116
}
114117

115118
if (sizeof(T) < 4) {
@@ -119,23 +122,11 @@ class PrintFormatter {
119122
return charactersPrinted;
120123
}
121124

122-
size_t printStringToken(char *output, size_t size, const char *formatString) {
123-
int index = 0;
124-
int type = 0;
125-
// additional read to discard the data type
126-
read(&type);
127-
read(&index);
128-
if (type == static_cast<int>(PRINTF_DATA_TYPE::STRING))
129-
return simple_sprintf(output, size, formatString, kernel.getKernelInfo().queryPrintfString(index));
130-
else
131-
return simple_sprintf(output, size, formatString, 0);
132-
}
133-
134125
Kernel &kernel;
135126
GraphicsAllocation &data;
136127

137128
uint8_t *buffer; // buffer extracted from the kernel, contains values to be printed
138129
uint32_t bufferSize; // size of the data contained in the buffer
139130
uint32_t offset; // current position in currently parsed buffer
140131
};
141-
};
132+
}; // namespace OCLRT

unit_tests/kernel/kernel_tests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,3 +2128,27 @@ TEST(KernelTest, givenKernelWhenDebugFlagToUseMaxSimdForCalculationsIsUsedThenMa
21282128
kernel.mockKernel->getWorkGroupInfo(device.get(), CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &maxKernelWkgSize, nullptr);
21292129
EXPECT_EQ(256u, maxKernelWkgSize);
21302130
}
2131+
2132+
TEST(KernelTest, givenKernelWithKernelInfoWith32bitPointerSizeThenReport32bit) {
2133+
KernelInfo info;
2134+
info.gpuPointerSize = 4;
2135+
2136+
MockContext context;
2137+
MockProgram program(&context, false);
2138+
std::unique_ptr<MockDevice> device(Device::create<OCLRT::MockDevice>(nullptr));
2139+
std::unique_ptr<MockKernel> kernel(new MockKernel(&program, info, *device.get()));
2140+
2141+
EXPECT_TRUE(kernel->is32Bit());
2142+
}
2143+
2144+
TEST(KernelTest, givenKernelWithKernelInfoWith64bitPointerSizeThenReport64bit) {
2145+
KernelInfo info;
2146+
info.gpuPointerSize = 8;
2147+
2148+
MockContext context;
2149+
MockProgram program(&context, false);
2150+
std::unique_ptr<MockDevice> device(Device::create<OCLRT::MockDevice>(nullptr));
2151+
std::unique_ptr<MockKernel> kernel(new MockKernel(&program, info, *device.get()));
2152+
2153+
EXPECT_FALSE(kernel->is32Bit());
2154+
}

unit_tests/program/printf_helper_tests.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ TEST_F(PrintFormatterTest, GivenPrintfFormatWhenPointerThenInsertAddress) {
749749
storeData(reinterpret_cast<void *>(&temp));
750750

751751
// on 32bit configurations add extra 4 bytes when storing pointers, IGC always stores pointers on 8 bytes
752-
if (!is64bit) {
752+
if (is32bit) {
753753
uint32_t padding = 0;
754754
storeData(padding);
755755
}
@@ -764,6 +764,33 @@ TEST_F(PrintFormatterTest, GivenPrintfFormatWhenPointerThenInsertAddress) {
764764
EXPECT_STREQ(referenceOutput, actualOutput);
765765
}
766766

767+
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenPointerWith32BitKernelThenPrint32BitPointer) {
768+
auto stringIndex = injectFormatString("%p");
769+
storeData(stringIndex);
770+
kernelInfo->gpuPointerSize = 4;
771+
772+
storeData(PRINTF_DATA_TYPE::POINTER);
773+
774+
// store pointer
775+
uint32_t addressValue = 0;
776+
storeData(addressValue);
777+
778+
void *pointer = nullptr;
779+
780+
// store non zero padding
781+
uint32_t padding = 0xdeadbeef;
782+
storeData(padding);
783+
784+
char actualOutput[PrintFormatter::maxPrintfOutputLength];
785+
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
786+
787+
snprintf(referenceOutput, sizeof(referenceOutput), "%p", pointer);
788+
789+
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
790+
791+
EXPECT_STREQ(referenceOutput, actualOutput);
792+
}
793+
767794
TEST_F(PrintFormatterTest, GivenPrintfFormatWhen2ByteVectorsThenParseDataBufferProperly) {
768795
int channelCount = 4;
769796

0 commit comments

Comments
 (0)