Vitis HLS 2022.2源码综合报错求助:MD5暴力破解器实现问题
Vitis HLS 2022.2综合错误排查:MD5暴力破解器实现问题
我是Vitis HLS初学者,正在实现一款可在PYNQ-Z2开发板运行的MD5暴力破解器,功能为输入MD5哈希字符串、字符集和最大长度进行破解。C++代码在x86平台可正常编译运行,已解决部分不可综合问题,但在Vitis HLS 2022.2综合时触发错误:ERROR: [HLS 200-1715] Encountered problem during source synthesis,现寻求问题排查帮助。
代码如下:
#include <iostream> #include <vector> char* pad_data(const char *data, size_t len, size_t& padded_size); void md5(const unsigned int *in, unsigned int *out, const size_t size); void generateCombinations(char* charset, int charset_size); //void print_md5(unsigned char* md5); void generateCombinations(char* charset, int charset_size) { #pragma HLS INTERFACE m_axi port=charset #pragma HLS INTERFACE m_axi port=charset_size int length = 3; char current[length+1]; for (size_t i = 0; i < length; i++) { current[i] = charset[0]; } while (true) { //std::cout<<current<<std::endl; char c[length+1]; for (size_t i = 0; i < length; i++) { c[i] = current[i]; } unsigned char out[16]; size_t data_size; char *pdata = pad_data(c, length, data_size); md5((unsigned int*)pdata, (unsigned int*)out, data_size); //print_md5(out); // check if out is equal to requested MD5 hash // if yes break and return to AXI port // Generate next combination bool carry = true; for (int i = length - 1; i >= 0; --i) { if (carry) { char* ptr; for (int j = 0; j < charset_size; j++) { if (charset[j] == current[i]) { ptr = charset + j; break; } } int idx = (ptr-charset)+1; if (idx >= charset_size) { idx = 0; carry = true; } else { carry = false; } current[i] = charset[idx]; } } if (carry) { break; } } } char* pad_data(const char *data, size_t len, size_t& padded_size) { // Do padding in software for simplicity size_t mod = (len+1)%64; size_t pad_size = (64+56-mod)%64; padded_size = len+1+pad_size+8; char padded[padded_size]; for (size_t i = 0; i < len; i++) { padded[i] = data[i]; } padded[len] = (char)0x80; for (size_t i = len+1; i < len+1+pad_size; i++) { padded[i] = 0x0; } // Convert bytes to bits and append length len <<= 3; for(char* p = padded+(padded_size-8); p < padded+padded_size; ++p){ *p = len & 0xff; len >>= 8; } return padded; } const unsigned int K[] = { 0XD76AA478, 0XE8C7B756, 0X242070DB, 0XC1BDCEEE, 0XF57C0FAF, 0X4787C62A, 0XA8304613, 0XFD469501, 0X698098D8, 0X8B44F7AF, 0XFFFF5BB1, 0X895CD7BE, 0X6B901122, 0XFD987193, 0XA679438E, 0X49B40821, 0XF61E2562, 0XC040B340, 0X265E5A51, 0XE9B6C7AA, 0XD62F105D, 0X02441453, 0XD8A1E681, 0XE7D3FBC8, 0X21E1CDE6, 0XC33707D6, 0XF4D50D87, 0X455A14ED, 0XA9E3E905, 0XFCEFA3F8, 0X676F02D9, 0X8D2A4C8A, 0XFFFA3942, 0X8771F681, 0X6D9D6122, 0XFDE5380C, 0XA4BEEA44, 0X4BDECFA9, 0XF6BB4B60, 0XBEBFBC70, 0X289B7EC6, 0XEAA127FA, 0XD4EF3085, 0X04881D05, 0XD9D4D039, 0XE6DB99E5, 0X1FA27CF8, 0XC4AC5665, 0XF4292244, 0X432AFF97, 0XAB9423A7, 0XFC93A039, 0X655B59C3, 0X8F0CCC92, 0XFFEFF47D, 0X85845DD1, 0X6FA87E4F, 0XFE2CE6E0, 0XA3014314, 0X4E0811A1, 0XF7537E82, 0XBD3AF235, 0X2AD7D2BB, 0XEB86D391 }; const unsigned char S[][16] = { {7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22}, {5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20}, {4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23}, {6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21} }; void md5_round1(const unsigned int *M, const unsigned int *in, unsigned int *out) { unsigned int A = in[0]; unsigned int B = in[1]; unsigned int C = in[2]; unsigned int D = in[3]; for(int i=0; i<16; ++i){ unsigned int tmp0 = (B&C)|(~B&D); unsigned int tmp1 = A + tmp0; unsigned int tmp2 = M[i] + K[i] + tmp1; unsigned int tmp3 = (tmp2 << S[0][i]) | (tmp2 >> (32-S[0][i])); A = D; D = C; C = B; B = tmp3 + B; } out[0] = A; out[1] = B; out[2] = C; out[3] = D; } void md5_round2(const unsigned int *M, const unsigned int *in, unsigned int *out) { unsigned int A = in[0]; unsigned int B = in[1]; unsigned int C = in[2]; unsigned int D = in[3]; for(int i=0; i<16; ++i){ unsigned int tmp0 = (B&D)|(C&~D); unsigned int tmp1 = A + tmp0; // unsigned int tmp2 = M[16+i] + K[16+i] + tmp1; unsigned int tmp2 = M[(((i+16) * 5) + 1) % 16] + K[16+i] + A + tmp0; unsigned int tmp3 = (tmp2 << S[1][i]) | (tmp2 >> (32-S[1][i])); A = D; D = C; C = B; B = tmp3 + B; } out[0] = A; out[1] = B; out[2] = C; out[3] = D; } void md5_round3(const unsigned int *M, const unsigned int *in, unsigned int *out) { unsigned int A = in[0]; unsigned int B = in[1]; unsigned int C = in[2]; unsigned int D = in[3]; for(int i=0; i<16; ++i){ unsigned int tmp0 = B^C^D; unsigned int tmp1 = A + tmp0; unsigned int tmp2 = M[(((i+32) * 3) + 5) % 16] + K[32+i] + tmp1; unsigned int tmp3 = (tmp2 << S[2][i]) | (tmp2 >> (32-S[2][i])); A = D; D = C; C = B; B = tmp3 + B; } out[0] = A; out[1] = B; out[2] = C; out[3] = D; } void md5_round4(const unsigned int *M, const unsigned int *in, unsigned int *out) { unsigned int A = in[0]; unsigned int B = in[1]; unsigned int C = in[2]; unsigned int D = in[3]; for(int i=0; i<16; ++i){ unsigned int tmp0 = C^(B|~D); unsigned int tmp1 = A + tmp0; unsigned int tmp2 = M[((i+48) * 7) % 16] + K[48+i] + tmp1; unsigned int tmp3 = (tmp2 << S[3][i]) | (tmp2 >> (32-S[3][i])); A = D; D = C; C = B; B = tmp3 + B; } out[0] = A; out[1] = B; out[2] = C; out[3] = D; } void md5(const unsigned int *in, unsigned int *out, const size_t size) { const unsigned int *M = in; unsigned int v0[] = {0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476}; unsigned int v1[4]; unsigned int v2[4]; unsigned int v3[4]; unsigned int v4[4]; for(size_t i=0; i<size; i+=64) { md5_round1(M, v0, v1); md5_round2(M, v1, v2); md5_round3(M, v2, v3); md5_round4(M, v3, v4); M += 16; v0[0] += v4[0]; v0[1] += v4[1]; v0[2] += v4[2]; v0[3] += v4[3]; } out[0] = v0[0]; out[1] = v0[1]; out[2] = v0[2]; out[3] = v0[3]; }
核心问题排查与修复建议
1. 栈内存指针返回(致命不可综合问题)
pad_data函数中声明了栈数组char padded[padded_size];,随后返回该数组的指针。栈内存是临时分配的,综合工具无法处理这种动态栈内存的返回逻辑,会直接导致综合失败。
修复方案:改为通过参数传入预先分配好的输出缓冲区,函数不再返回指针:
void pad_data(const char *data, size_t len, char *padded, size_t& padded_size) { size_t mod = (len+1)%64; size_t pad_size = (64+56-mod)%64; padded_size = len+1+pad_size+8; for (size_t i = 0; i < len; i++) { padded[i] = data[i]; } padded[len] = (char)0x80; for (size_t i = len+1; i < len+1+pad_size; i++) { padded[i] = 0x0; } len <<= 3; for(char* p = padded+(padded_size-8); p < padded+padded_size; ++p){ *p = len & 0xff; len >>= 8; } }
调用时需提前分配足够大的缓冲区(比如按最大支持长度计算64字节对齐后的大小)。
2. 变长栈数组不可综合
char current[length+1];和char c[length+1];中的length是运行时变量,Vitis HLS不支持变长栈数组。
修复方案:将length改为编译时常量,例如用#define MAX_LENGTH 3定义,然后声明数组为char current[MAX_LENGTH+1];。
3. AXI接口配置错误
charset_size是int类型控制参数,使用m_axi接口不合适,应改为s_axilite接口作为控制信号。charset的m_axi接口需明确数据宽度和突发长度,否则综合工具无法正确生成总线逻辑。
修复方案:调整接口配置,补充必要的控制和结果输出接口:
#define MAX_LENGTH 3 void generateCombinations(char* charset, int charset_size, unsigned char target_hash[16], char result[MAX_LENGTH+1], bool* done) { #pragma HLS INTERFACE m_axi port=charset bundle=MAXI depth=256 #pragma HLS INTERFACE s_axilite port=charset_size bundle=CTRL #pragma HLS INTERFACE s_axilite port=target_hash bundle=CTRL #pragma HLS INTERFACE m_axi port=result bundle=MAXI depth=16 #pragma HLS INTERFACE s_axilite port=done bundle=CTRL #pragma HLS INTERFACE s_axilite port=return bundle=CTRL // ... 原有函数逻辑 }
4. 其他优化与综合兼容调整
- 线性查找字符索引的逻辑可预先固化为查表结构,提升综合后性能。
while(true)循环建议添加明确的最大迭代次数限制,帮助综合工具识别循环的有限性。
内容的提问来源于stack exchange,提问作者devdc
相关产品推荐
相关产品推荐

