Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined symbols for architecture x86_64 (clang)

I'm trying to use OpenSSL to compute sha1 hash from a c program. I am compiling with clang on Mac OS X Yosemite with an Intel i7 (so 64 bit).

The relevant piece of code is roughly like so:

#include <openssl/evp.h>
...
unsigned char outHash[20]; 
hash("SHA1","abcd", 20, outHash);

The thing is, when using the "hash" function from openssl/evp.h, compiling with clang yields the following error:

Undefined symbols for architecture x86_64:
  "_hash", referenced from:
      _getRandomSHA1 in main-68ccd6.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So it looks like OpenSSL is not found by the linker (the "hash" function is unidentified). Any ideas on how to fix this?

EDIT:

It turns out that I was trying to use a function that does not exist ("hash") - sorry for misleading you about that.

However I'm still having quite the same problem: including openssl/evp.h does not seem to work.

This is the hash function that I am using, it uses evp to perform sha1 encoding:

unsigned int hash(const char *mode, const char* dataToHash, size_t dataSize, unsigned char* outHashed) {
    unsigned int md_len = -1;
    const EVP_MD *md = EVP_get_digestbyname(mode);
    if(NULL != md) {
        EVP_MD_CTX mdctx;
        EVP_MD_CTX_init(&mdctx);
        EVP_DigestInit_ex(&mdctx, md, NULL);
        EVP_DigestUpdate(&mdctx, dataToHash, dataSize);
        EVP_DigestFinal_ex(&mdctx, outHashed, &md_len);
        EVP_MD_CTX_cleanup(&mdctx);
    }
    return md_len;
}

And then I call:

hash("SHA1","abcd", 20, outHash);

I am compiling same as before, this is my compile command (pretty simple):

 clang main.c

And I'm getting the following error from the linker:

Undefined symbols for architecture x86_64:
  "_EVP_DigestFinal_ex", referenced from:
      _hash in main-935849.o
  "_EVP_DigestInit_ex", referenced from:
      _hash in main-935849.o
  "_EVP_DigestUpdate", referenced from:
      _hash in main-935849.o
  "_EVP_MD_CTX_cleanup", referenced from:
      _hash in main-935849.o
  "_EVP_MD_CTX_init", referenced from:
      _hash in main-935849.o
  "_EVP_get_digestbyname", referenced from:
      _hash in main-935849.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
like image 871
orcaman Avatar asked Jun 19 '15 13:06

orcaman


1 Answers

#include <openssl/evp.h>
...
unsigned char outHash[20]; 
hash("SHA1","abcd", 20, outHash);

OpenSSL does not have a int hash(...) or char* hash(...) function.

$ cat /usr/include/openssl/evp.h | grep hash returns 0 hits. man 3 hash returns BSD's "hash database access method".


Undefined symbols for architecture x86_64:
  "_hash", referenced from:
      _getRandomSHA1 in main-68ccd6.o

Latching on to _getRandomSHA1, there is a SHA function, but it's available from sha.h, and not evp.h (I filtered out the DEPRECATED_IN... macro):

$ cat /usr/include/openssl/sha.h | grep SHA | grep char
...
unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md);
...

I believe it uses a static buffer, and its use is discouraged.

The project recommends using EVP Message Digests interface now.


(EDIT): I am compiling same as before, this is my compile command (pretty simple):
clang main.c

See Linking OpenSSL libraries to a program. You need to add -lcrypto to the end of the compile command.


(EDIT, from comment): I have openssl at /opt/local/include/openssl....

You are going to have more problems because you are probably runtime linking against the wrong version of the OpenSSL library. For that problem, see Statically link OpenSSL in XCode. The same problem exists from the command line and Xcode.

Here's the easiest solution. Notice that it does not use -lcrypto (-lfoo is usually the solution, except when runtime linking to the wrong shared object becomes a problem):

 clang main.c -I /opt/local/include /opt/local/lib/libcrypto.a -o my_hash.exe 

An archive is just a collection of object files, so an archive can be used in place where an object file is required.

OS X does not honor RPATHs. Another solution is to build OpenSSL and your program with an RPATH so the correct version of the library is loaded at runtime. For that, see Compilation and Installation | Using RPATHs on the OpenSSL wiki and Build OpenSSL with RPATH? on Stack Overflow.

like image 167
jww Avatar answered Sep 29 '22 17:09

jww