how to insert unique ID into binary file that created after compilation?

P

pristo

hello All,
how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

thx
 
K

Kenny McCormack

hello All,
how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

Not portable. Can't discuss it here. Blah, blah, blah.
 
E

Eric Sosman

pristo wrote On 11/08/05 11:36,:
hello All,
how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

In portable C, the closest you can come is to create
a static variable initialized with the ID you desire. The
source file name, date, and time are often used for this:

static const char version_info[] =
"@@@ VERSION INFO @@@"
" Compiled from " __FILE__
" on " __DATE__
" at " __TIME__;

Many systems have utilities that can extract and display
the string constants from an executable or object file,
and ways to separate the "@@@ VERSION INFO @@@" strings
from the others (on Unix systems, you could use `strings'
and `grep'). Some source-management systems can be made
to provide part or all of the data, which could automate
the inclusion of a version identifier for each file. Of
course, all such utilities are not part of the C language,
and will vary from system to system.

A disadvantage of this technique is that some compilers
will issue diagnostic messages about variables that are
declared but not used; such compilers are likely to complain
about the `version_info' variable.
 
G

Gordon Burditt

how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

One common method of inserting an ID is:

static char rcsid[] = "$Id: foo.c,v 1.7 2005/11/08 12:01:32 root Exp $";

A compiler might give a warning about an unreferenced variable (and
might be smart enough to try to discard it): so reference it, for
example, make "foo -V" print out the version string.

The method of INSERTING the id is portable. The method of extracting
it isn't, but locating such a string is fairly easy and makes few
assumptions beyond the file being a raw binary file: scan until
you see a $, followed by a known keyword, followed by a colon, then
output the stuff from a $ to the next $. I think if non-text
characters (whatever that means) or newlines are encountered between
the two $, it's not output. I've never seen the program that
extracts the headers have a false match, although constructing a
failure case is easy.

RCS and CVS (source code control systems) will even maintain the
strings for you with a current version, time stamp, and user who
last checked it in. You actually put in:
static char rcsid[] = "$Id$";
and RCS or CVS will expand it for you.

Gordon L. Burditt
 
C

CarlosB

If you want to mark the binary file that is generated by more than one
source code: e.g (main.c, other.c, etc.) which will cause more than one
rcsid, and you want one unique mark for the whole binary, a good way to
do this is creating your own marker, something like the piece of code
below: (notice that I'm not testing for i/o, string or any other errors
in this example).

typedef struct tagFooter {
BYTE area1[10];
BYTE area2[10];
} _FOOTER;
#define size_footer sizeof(_FOOTER)

int main(int argc,char **argv)
{
FILE *f;
int size;
_FOOTER myInfo;

if(argc < 3) {
/* we expect to receive at least 2 parameters from command line */
return(1);
}
strcpy(myinfo.area1,argv[1]);
strcpy(myinfo.area2,argv[2]);

f=fopen("myfile.bin","wb");
fseek(f,0,SEEK_END);
fwrite(&myinfo,size_footer ,1,f);
fclose(f);
return(0);
}

Instead of getting the values from command line, you could put a CRC
check or anything you desire to use. Also It's pretty easy to create a
program to show the footer information for a marked file.

Hope this can help you.
 
P

pristo

first thx to all for helping,
i try use your suggestion but its seem that the compiler is optmize the
variable.
i write the code for embdded system and i dont have interface to print
the version out
so how can i cause the compiler think that i use the variable and not
to optmize it?

Pristo
 
G

Gordon Burditt

If you want to mark the binary file that is generated by more than one
source code: e.g (main.c, other.c, etc.) which will cause more than one
rcsid,

Nothing wrong with more than one ID, if you make them static.
Often that's the whole point: you get the version number of
everything that was used to create the executable.
and you want one unique mark for the whole binary, a good way to

A common way to deal with this is to use the RCS ID in the version.c
file or the one in the main program as the primary ID, and that's
the one that the -V flag prints.
do this is creating your own marker, something like the piece of code
below: (notice that I'm not testing for i/o, string or any other errors
in this example).

Appending random crap to an executable may destroy it. Particularly
if the executable has a checksum, digital signature, or other
integrity check. Also, the program doing it *SHOULD* be flagged
as a virus.

There's no guarantee that SEEK_END on a binary file will work.
(Some OS such as CP/M only keep file sizes in sectors, so
there may be unwritten stuff at the end of the last sector in
a binary file, with no way to tell how much of it is unwritten.)

Gordon L. Burditt
typedef struct tagFooter {
BYTE area1[10];
BYTE area2[10];
} _FOOTER;
#define size_footer sizeof(_FOOTER)

int main(int argc,char **argv)
{
FILE *f;
int size;
_FOOTER myInfo;

if(argc < 3) {
/* we expect to receive at least 2 parameters from command line */
return(1);
}
strcpy(myinfo.area1,argv[1]);
strcpy(myinfo.area2,argv[2]);

f=fopen("myfile.bin","wb");
fseek(f,0,SEEK_END);
fwrite(&myinfo,size_footer ,1,f);
fclose(f);
return(0);
}

Instead of getting the values from command line, you could put a CRC
check or anything you desire to use. Also It's pretty easy to create a
program to show the footer information for a marked file.

Hope this can help you.
 
P

pristo

thx for helping.
i try use your solution
and its seen that the copiler optimize the variable,
i write for embedded system and i dont have interface for print the
version out
how can i cause the compiler not to optmize this constant?

thx
 
W

Walter Roberson

i try use your suggestion but its seem that the compiler is optmize the
variable.
i write the code for embdded system and i dont have interface to print
the version out
so how can i cause the compiler think that i use the variable and not
to optmize it?

Sometimes declaring the variable as volatile is enough to get the
compiler to leave it alone even if it isn't used. Sometimes
simple tricks like taking its strlen() are enough. It depends on
how smart the compiler is about finding "dead code" and "dead variables".
 
S

Skarmander

pristo said:
thx for helping.
i try use your solution
and its seen that the copiler optimize the variable,
i write for embedded system and i dont have interface for print the
version out
how can i cause the compiler not to optmize this constant?
Please quote the relevant parts of posts your reply to.

Your compiler or linker may have an option that tells it to emit statics
even if they're not used. For gcc, it is notable that
-fkeep-static-consts does *not* do the trick in general; this only works
if you're not optimizing. Consult your documentation.

Otherwise, you'll have to try and outsmart your compiler (this is
generally a bad idea, but it may be the only option). That is, involve
the constant in expressions that are too complicated for the compiler to
detect as going unused or evaluating to a constant.

If you find such an expression, it may be a good idea to encapsulate it
in a function, otherwise it'll look very mysterious.

S.
 
E

Eric Sosman

Skarmander wrote On 11/08/05 16:01,:
Please quote the relevant parts of posts your reply to.

Your compiler or linker may have an option that tells it to emit statics
even if they're not used. For gcc, it is notable that
-fkeep-static-consts does *not* do the trick in general; this only works
if you're not optimizing. Consult your documentation.

Also check your documentation to see whether your compiler
already "fingerprints" its outputs, and whether tools to display
the fingerprints exist. Such things aren't part of the C language,
but since you seem to be concerned with just one particular C
implementation you might as well use whatever it offers.
 
M

Mark McIntyre

so how can i cause the compiler think that i use the variable and not
to optmize it?

Use it in your code.

Or search the documentation for compiler flags to disable optimisation
for that specific object. There may be pragmas.
 
A

Alan Balmer

how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

One common method of inserting an ID is:

static char rcsid[] = "$Id: foo.c,v 1.7 2005/11/08 12:01:32 root Exp $";

It's not a bad idea to use a format recognized by the Unix "what"
command. Excerpt from man page:

The what command searches the given files for all occurrences of the
pattern that get(1) substitutes for %Z% (currently @(#) at this
printing) and prints out what follows until the first ", >, new-line,
\, or null character. For example, if the C program in file f.c
contains

char ident[] = "@(#)identification information";

Then you can write a portable version of "what" to go along with it
:)
A compiler might give a warning about an unreferenced variable (and
might be smart enough to try to discard it): so reference it, for
example, make "foo -V" print out the version string.

The method of INSERTING the id is portable. The method of extracting
it isn't, but locating such a string is fairly easy and makes few
assumptions beyond the file being a raw binary file: scan until
you see a $, followed by a known keyword, followed by a colon, then
output the stuff from a $ to the next $. I think if non-text
characters (whatever that means) or newlines are encountered between
the two $, it's not output. I've never seen the program that
extracts the headers have a false match, although constructing a
failure case is easy.

RCS and CVS (source code control systems) will even maintain the
strings for you with a current version, time stamp, and user who
last checked it in. You actually put in:
static char rcsid[] = "$Id$";
and RCS or CVS will expand it for you.

Gordon L. Burditt
 
K

Keith Thompson

Alan Balmer said:
how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

One common method of inserting an ID is:

static char rcsid[] = "$Id: foo.c,v 1.7 2005/11/08 12:01:32 root Exp $";

It's not a bad idea to use a format recognized by the Unix "what"
command.

<OT>
The "what" command is part of SCCS, a mostly obsolete source control
system that isn't even installed on a lot of Unix-like systems.
See also RCS, CVS, and "ident".
</OT>
 
C

CarlosB

Appending random crap to an executable may destroy it.

The random "crap" you mention is just an example on how to implement a
digital signature, as this binary file belongs to him. Besides this,
the "rcsid" example requires a control version system, which cannot be
the case.
There's no guarantee that SEEK_END on a binary file will work.

Sorry my friend, but the issue with SEEK_END is with text files, not
binary.
 
A

Alan Balmer

Alan Balmer said:
how can i insert unique ID into binary file (that created by compiler)?
(so after compiling i can to identify the src that i use)

One common method of inserting an ID is:

static char rcsid[] = "$Id: foo.c,v 1.7 2005/11/08 12:01:32 root Exp $";

It's not a bad idea to use a format recognized by the Unix "what"
command.

<OT>
The "what" command is part of SCCS, a mostly obsolete source control
system that isn't even installed on a lot of Unix-like systems.
See also RCS, CVS, and "ident".
</OT>
<Still OT>
It's a standalone command, not dependent on SCCS. Our HP-UX systems
always have it, but never have SCCS (or RCV or CVS, for that matter.)
It's probably available for most Unix systems (all of which have stuff
available which may or may not be installed.)

What's more, it's a very useful command, and as I suggested, not hard
to implement yourself. Better, imo, than inventing a new format with
no meaning to anyone else.
 
W

Walter Roberson

There's no guarantee that SEEK_END on a binary file will work.
[/QUOTE]
Sorry my friend, but the issue with SEEK_END is with text files, not
binary.

C89 4.9.9.2 The fseek Function

A binary stream need not meaningfully support
fseek calls with a whence value of SEEK_END.

For a text stream, either offset ahall be zero, or offset shall be
a value returned by an earlier call to the ftell function on the same
stream and whence shall be SEEK_SET.
 
J

Jordan Abel

There's no guarantee that SEEK_END on a binary file will work.
(Some OS such as CP/M only keep file sizes in sectors, so
there may be unwritten stuff at the end of the last sector in
a binary file, with no way to tell how much of it is unwritten.)

But those will be null bytes. You could always decide "that is part of
the file for purposes of what i'm doing" - just keep in mind that there
also may be extra null bytes after whatever _you_ wrote.
 
A

Alan Balmer

But those will be null bytes. You could always decide "that is part of
the file for purposes of what i'm doing" - just keep in mind that there
also may be extra null bytes after whatever _you_ wrote.

They won't necessarily be null. Even if they are, how do you know they
weren't written on purpose, and part of the data?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top