You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:47:01