Discussion:
C Funktion wird nicht aufgerufen
Add Reply
Thomas Orgelmacher
2018-10-03 14:44:40 UTC
Antworten
Permalink
Hallo Zusammen!

Ich stehe auf dem Schlauch. Und zwar richtig.

Ich will mit libexif EXIF-Daten parsen (ok, das ist jetzt nicht wirklich
überraschend).

Folgender Code (Ausschnitt und um den Inhalt von "switch(entry->tag)" gekürzt):

-------------------- schnipp --------------------
void cb_entry(ExifEntry *entry, void *data)
{
exifdata_t *ed = data;

if(! is_suppressed_tag(entry->tag) /* tags we (at least I) don't need */
&& entry->size < BUFFSIZE)
{
exif_entry_get_value(entry, buf, sizeof(buf));

if(!buf[0])
ed = NULL;
else
{
switch(entry->tag)
{
/* lauter cases eben... */
};
}
}
}

void cb_content(ExifContent *content, void *data)
{
exif_content_foreach_entry(content, cb_entry, data);
}
-------------------- schnapp --------------------

Das Problem ist: cb_entry wird nicht aus cb_content von
exif_content_foreach_entry per Callback aufgerufen.
Ich habe mir das im Assembler angeschaut und da steht ganz
klar ein "callq", welches einfach übergangen wird.

Und jetzt wird richtig schräg: gdb meint dazu:
"Line 1 of "exif.c" is at address 0x401fb4 <cb_entry> but contains no code."

Compiler Flags (gcc 5.5) sind "-g -Wall", also wirklich nicht wirklich spannend.

Der Ursprung des Codes ist eine Python3 Extension, die eigentlich auch
weitgehend funktioniert. Ich hatte nur gelegentliche segfaults, die ich
jetzt ohne den Python Kontext isolieren wollte.
Aus dem Grund habe ich die Python Abhängigkeiten wieder ausgebaut und es
tut gar nichts mehr.

Der Code ist kein Geheimnis, wenn jemand mehr sehen will: sachts eben was.

Ich stoße mich vor allem an "<cb_entry> but contains no code." und der
Tatsache, daß das "callq" nicht ausgeführt wird.

Klingelt das bei irgendwem?


Gruß, Thomas


PS.: Entschuldigt bitte den Post an dclc. Ich weiß, daß hier kein C-Problem
vorliegt aber da sitzt Potential, daß ich gern dabei hätte...
--
I have seen things you lusers would not believe. I've seen Sun
monitors on fire off the side of the multimedia lab. I've seen
NTU lights glitter in the dark near the Mail Gate. All these
things will be lost in time, like the root partition last week.
Stefan Ram
2018-10-03 15:14:48 UTC
Antworten
Permalink
Supersedes: <debuggen-***@ram.dialup.fu-berlin.de>
[Newsgroups: de.comp.lang.c]
Post by Thomas Orgelmacher
Das Problem ist: cb_entry wird nicht aus cb_content von
exif_content_foreach_entry per Callback aufgerufen.
Ich habe mir das im Assembler angeschaut und da steht ganz
klar ein "callq", welches einfach übergangen wird.
Falls Du Assembler-Programmierer bist, dann ersetzt die
callq-Zeile durch folgende fünf Zeilen:

<Ausgabe eines Textes auf die Konsole>
<callq-Aufruf einer prominenten Funktion, der auf jeden Fall
erfolgreich ausgeführt werden können sollte>
<callq einer Funktion mit ähnlichen Eigenschaften wie cb_entry>
<der ursprüngliche callq-Aufruf von cb_entry>
<Ausgabe eines Textes auf die Konsole>

und starte dann das Programm, um zu sehen, was dann dort
passiert.

Ok, das ist jetzt ein sehr primitiver Hinweis, aber ich weiß
ja nicht, was Du schon alles probiert hast:

Ersetze cb_entry einmal durch:

void cb_entry(ExifEntry *entry, void *data){ abort(); }

und lasse das so, solange es nicht aufgerufen wird.

An dem »abort()« kannst Du es dann erkennen, falls es
doch einmal aufgerufen werden sollte.

Dann rufe es auch einmal von »main()« aus auf.

main(){ cb_entry( 0, 0 ); }

. Jetzt müßte das Programm abbrechen.
Post by Thomas Orgelmacher
"Line 1 of "exif.c" is at address 0x401fb4 <cb_entry> but contains no code."
Zeile 1 von exif.c enthält keinen Code? Verstehe ich auch nicht!
Thomas Orgelmacher
2018-10-03 16:28:57 UTC
Antworten
Permalink
Post by Stefan Ram
Falls Du Assembler-Programmierer bist, dann ersetzt die
Nein, sorry. War ich zuletzt bei 68K.

Da steht:

0x000000000040220b <+23>: mov %rax,%rcx
0x000000000040220e <+26>: mov $0x12,%edx
0x0000000000402213 <+31>: mov $0x1,%esi
0x0000000000402218 <+36>: mov $0x402a0a,%edi
0x000000000040221d <+41>: callq 0x400f80 <***@plt>
=> 0x0000000000402222 <+46>: mov -0x10(%rbp),%rdx
0x0000000000402226 <+50>: mov -0x8(%rbp),%rax
0x000000000040222a <+54>: mov $0x401fb4,%esi
0x000000000040222f <+59>: mov %rax,%rdi
0x0000000000402232 <+62>: callq 0x400e00 <***@plt>
0x0000000000402237 <+67>: nop
0x0000000000402238 <+68>: leaveq
0x0000000000402239 <+69>: retq

Ich sehe nicht warum der Call nach exif_content_foreach_entry einfach
übergangen wird. Und ich habe so etwas auch noch nie gesehen.
Post by Stefan Ram
void cb_entry(ExifEntry *entry, void *data){ abort(); }
Nix. Kein Effekt.
Post by Stefan Ram
Dann rufe es auch einmal von »main()« aus auf.
main(){ cb_entry( 0, 0 ); }
Sorry, aber dafür muss ich den gesamten Code umgraben. Mache ich,
aber nicht jetzt mal eben.
Post by Stefan Ram
Post by Thomas Orgelmacher
"Line 1 of "exif.c" is at address 0x401fb4 <cb_entry> but contains no code."
Zeile 1 von exif.c enthält keinen Code? Verstehe ich auch nicht!
Das wäre spannend... :-)


Gruß, Thomas
--
I have seen things you lusers would not believe. I've seen Sun
monitors on fire off the side of the multimedia lab. I've seen
NTU lights glitter in the dark near the Mail Gate. All these
things will be lost in time, like the root partition last week.
Stefan Ram
2018-10-03 16:59:29 UTC
Antworten
Permalink
Post by Thomas Orgelmacher
Ich sehe nicht warum der Call nach exif_content_foreach_entry einfach
übergangen wird. Und ich habe so etwas auch noch nie gesehen.
Da würde ich dann im C-Quellcode direkt vor und direkt
hinter den Aufruf eine Debug-Ausgabe schreiben, die mir
anzeigt, ob die Kontrolle wirklich an diese Stelle kommt,
und genauso in die aufgerufene Funktion (wie schon gesagt).
Post by Thomas Orgelmacher
Post by Stefan Ram
void cb_entry(ExifEntry *entry, void *data){ abort(); }
Nix. Kein Effekt.
Das sind Stefan Reuthers Überlegungen über den Inhalt von
»cb_entry« vielleicht hinfällig, denn Deine Beobachtung zeigt
anscheinend, daß die Kontrolle nie an den Anfang von »cb_entry«
kommt, egal /was/ nun im Einzelnen in »cb_entry« steht.
Thomas Orgelmacher
2018-10-03 17:12:33 UTC
Antworten
Permalink
Post by Stefan Ram
Post by Thomas Orgelmacher
Ich sehe nicht warum der Call nach exif_content_foreach_entry einfach
übergangen wird. Und ich habe so etwas auch noch nie gesehen.
Da würde ich dann im C-Quellcode direkt vor und direkt
hinter den Aufruf eine Debug-Ausgabe schreiben, die mir
anzeigt, ob die Kontrolle wirklich an diese Stelle kommt,
und genauso in die aufgerufene Funktion (wie schon gesagt).
Das war natürlich das erste was ich gemacht habe, weil naheliegend.

Da kommt nichts an.
Post by Stefan Ram
Post by Thomas Orgelmacher
Post by Stefan Ram
void cb_entry(ExifEntry *entry, void *data){ abort(); }
Nix. Kein Effekt.
Das sind Stefan Reuthers Überlegungen über den Inhalt von
»cb_entry« vielleicht hinfällig, denn Deine Beobachtung zeigt
anscheinend, daß die Kontrolle nie an den Anfang von »cb_entry«
kommt, egal /was/ nun im Einzelnen in »cb_entry« steht.
So ist es.

Hey, ich ich hatte extra ein Flupto nach de.comp.os.unix.programming
gesetzt, weil das eigentlich kein dclc Thema ist.
Ich find's toll, das Du mitgrübeln willst, aber vielleicht sollte das eher
da passieren.


Thomas
--
I have seen things you lusers would not believe. I've seen Sun
monitors on fire off the side of the multimedia lab. I've seen
NTU lights glitter in the dark near the Mail Gate. All these
things will be lost in time, like the root partition last week.
Rainer Weikusat
2018-10-03 17:33:30 UTC
Antworten
Permalink
Post by Thomas Orgelmacher
Post by Stefan Ram
Falls Du Assembler-Programmierer bist, dann ersetzt die
Nein, sorry. War ich zuletzt bei 68K.
0x000000000040220b <+23>: mov %rax,%rcx
0x000000000040220e <+26>: mov $0x12,%edx
0x0000000000402213 <+31>: mov $0x1,%esi
0x0000000000402218 <+36>: mov $0x402a0a,%edi
=> 0x0000000000402222 <+46>: mov -0x10(%rbp),%rdx
0x0000000000402226 <+50>: mov -0x8(%rbp),%rax
0x000000000040222a <+54>: mov $0x401fb4,%esi
0x000000000040222f <+59>: mov %rax,%rdi
0x0000000000402237 <+67>: nop
0x0000000000402238 <+68>: leaveq
0x0000000000402239 <+69>: retq
Ich sehe nicht warum der Call nach exif_content_foreach_entry einfach
übergangen wird. Und ich habe so etwas auch noch nie gesehen.
Oa sieht nach gdb-Ausgabe aus. => makiert die momentane
Instruktion. Entweder dein Computer ist verflucht (oder sowas) oder
dieser callq wird nicht ueberspringen. Die Ladeinstruktionen davor
bewirken das mal nicht. Mit 'stepi' kann man Instruktionen
einzelschrittweise ausfuehren, dass koennte hier nuetzlich sein.

Dumme Frage: Laut
https://libexif.github.io/internals/exif-content_8c-source.html ist
exif_content_foreach_entry

exif_content_foreach_entry (ExifContent *content,
ExifContentForeachEntryFunc func, void *data)
{
unsigned int i;

if (!content || !func)
return;

for (i = 0; i < content->count; i++)
func (content->entries[i], data);
}

bist Du sicher, das content->count > 0 ist?
Thomas Orgelmacher
2018-10-04 20:34:24 UTC
Antworten
Permalink
Post by Rainer Weikusat
bist Du sicher, das content->count > 0 ist?
Ganz dämlicher Fehler. Vor allem wenn man Tage danach gesucht hat.

Ich hatte da massiv umstrukturiert und dabei auch diverse Variablen
entsorgt. Ich habe dann die Größe des mmappeded Files direkt aus der
Rückgabe von "stat" verwendet. Blöderweise habe ich dann exif_data_new_from_data
mit einer auf 0 initialisierten Variable verwendet die im ursprünglichen
Code eben auch die Größe enthielt. Da konnte nichts gefunden werden.

Manchmal sieht man den Wald vor lauter Bäumen nicht mehr.

Danke fürs mitdenken.


Thomas
--
I have seen things you lusers would not believe. I've seen Sun
monitors on fire off the side of the multimedia lab. I've seen
NTU lights glitter in the dark near the Mail Gate. All these
things will be lost in time, like the root partition last week.
Stefan Ram
2018-10-03 17:37:41 UTC
Antworten
Permalink
int is_suppressed_tag(int tag)
{
static int suppressed_tags[] =
{
EXIF_TAG_PRINT_IMAGE_MATCHING,
...
Ich sehe nicht, was da mal eben wegoptimiert werden könnte...
main.c

#include <stdio.h>

#define EXIF_A 0
#define EXIF_B 1
#define EXIF_C 2

static void escape( volatile void * p )
{ asm volatile( "" : : "g"(p) : "memory" ); }

int is_suppressed_tag( int tag )
{ static int suppressed_tags[] =
{ EXIF_A,
EXIF_B,
-1 };

for( int i = 0; suppressed_tags[ i ]!= -1; ++i )
if( suppressed_tags[ i ]== tag )return 1;
return 0; }

__attribute__ ((noinline)) int f340()
{ return is_suppressed_tag( EXIF_A ); }

__attribute__ ((noinline)) int f341()
{ return is_suppressed_tag( EXIF_C ); }

int main()
{ { int result = f340(); escape( &result ); }
{ int result = f341(); escape( &result ); }}

Assembler-Ausgabe (mit gcc ... -O3 ...)

f340:
...
movl $1, %eax
ret
...
f341:
...
xorl %eax, %eax
ret
...
Loading...