Forum: Mikrocontroller und Digitale Elektronik STM32: gcc 5.4.1 vs. 6.3.1 und memset


von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

wenn ich den angehängten code mit gcc 5.4.1 kompiliere, läuft der code 
bis in die Endlosschleife und läßt die LED im Sekundentakt blinken.

Wenn ich denselben Code mit gcc 6.3.1 kompiliere, sorgt memset dafür, 
daß der HardFault_Handler aufgerufen wird.

Das ganze unter Linux (Ubuntu 17.10 vs. Ubuntu 18.04).

Anbei noch das Linker-Skript und das Makefile.

Ist jemandem sowas schonmal begegnet?

Bin für jegliche Hinweise dankbar.

von Nop (Gast)


Lesenswert?

Versuch mal, das Array "data" mit "__attribute__ ((aligned (4)))" zu 
versehen. Sollte eigentlich nicht nötig sein, aber man kann damit 
zumindest probieren, ob es was mit alignment zu tun hat.

von Unwissender (Gast)


Lesenswert?

Das mit dem aligned war auch mein erster Verdacht, aber das ändert 
leider nichts.

von Nop (Gast)


Lesenswert?

Dann nimm als nächstes mal die Delays über den Systick raus und ersetz 
das durch eine ganz dumme Runterzähl-Schleife.

von Unwissender (Gast)


Lesenswert?

Hab ich getestet, leider keine Änderung :-(

von Nop (Gast)


Lesenswert?

Guck mal hier:

https://stackoverflow.com/questions/20587208/cortex-m3-cant-handle-memset

Kann also sein, daß er die Libraries durcheinanderkriegt. Wie sieht 
eigentlich das Disassembly an der Stelle aus, wo memset aufgerufen wird? 
Ist das niederwertigste Bit der Zieladresse wirklich auf 1 (thumb)?

von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Anbei der Dump, hier der Auszug, an dem memset aufgerufen wird:

memset(data, 0x00, 64);
 80014ee:  2240        movs  r2, #64  ; 0x40
 80014f0:  2100        movs  r1, #0
 80014f2:  4808        ldr  r0, [pc, #32]  ; (8001514 <main+0x68>)
 80014f4:  f000 f89c   bl  8001630 <memset>

von Nop (Gast)


Lesenswert?

Unwissender schrieb:
 80014ee:  2240        movs  r2, #64  ; 0x40
 80014f0:  2100        movs  r1, #0
 80014f2:  4808        ldr  r0, [pc, #32]  ; (8001514 <main+0x68>)
 80014f4:  f000 f89c   bl  8001630 <memset>

Also r0 als erster Parameter sollte die Adresse von data haben. Aber an 
0x08000000 liegt doch das ROM?

Was sagt Dein mapfile denn, wo liegt data dort?

Außerdem ist es merkwürdig, daß der bl an eine gerade Adresse geht, das 
sollte an eine ungerade gehen (für thumb-Mode). Das kann aber auch der 
Disassembler sein, der das von sich aus schon lesbarer darstellen will 
und deswegen automatisch das Bit 0 der Zieladresse auf 0 zurückdreht.

von Johannes S. (Gast)


Lesenswert?

Unwissender schrieb:
> 80014f2:  4808        ldr  r0, [pc, #32]  ; (8001514 <main+0x68>)

da wird für &data[0] doch eine Adresse aus dem Flash geladen? Ist da 
nicht eher ein Fehler im Linkerfile?

von Unwissender (Gast)


Lesenswert?

Johannes, das klingt erstmal plausibel. Aber warum funktioniert das 
unter gcc 5.4.1 problemlos. Im Disasembler sieht der Aufruf von memset 
genauso aus:

Mit gcc 5.4.1 kompiliert:

memset(data, 0x00, 64);
 80014ee:  2240        movs  r2, #64  ; 0x40
 80014f0:  2100        movs  r1, #0
 80014f2:  4808        ldr  r0, [pc, #32]  ; (8001514 <main+0x68>)
 80014f4:  f000 f89c   bl  8001630 <memset>

von Johannes S. (Gast)


Lesenswert?

an der memset Funktion hat sich nichts geändert,
https://github.com/gcc-mirror/gcc/blob/gcc-6_3_0-release/libiberty/memset.c
das dürften irgendwelche anderen Effekte sein. Leg das data Feld doch 
mal auf den Stack.

von Nop (Gast)


Lesenswert?

Ach ja, das Mapfile bekommst Du, indem Du dem GCC beim Linken auch 
"-Wl,-Map=mymapfile.map" mit auf den Weg gibst.

von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist das map file ...

von Unwissender (Gast)


Lesenswert?

Johannes S. schrieb:
> Leg das data Feld doch
> mal auf den Stack.

Wie mache ich das?

von Johannes S. (Gast)


Lesenswert?

die data Deklaration einfach in das main reinschieben.

Im Mapfile liegt das array aber richtig im Ram, komisch. Der Name für 
das Array ist auch blöde weil das mapfile voll ist mit 'data', benenne 
das besser anders.

von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Ist mir auch schon aufgefallen :-) Hab den Namen in data_xxx geändert.
Das Verschieben in den den heap hat auch nicts gebracht :-(

Anbei die aktuellen Dateien.

von Nop (Gast)


Lesenswert?

Oha.. also das Mapfile ist etwas schwer lesbar, weil die Variable "data" 
ehißt, während zig andere Sachen da auch "data" heißen. Kannste das 
Array mal in irgendwas Nettes umbennennen, wie "mystuff" oder so, und 
dann nochmal ein Mapfile erstellen?

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> Kannste das
> Array mal in irgendwas Nettes umbennennen, wie "mystuff" oder so, und
> dann nochmal ein Mapfile erstellen?

Schon geschehen :-) -> data_xxx

von Nop (Gast)


Lesenswert?

Unwissender schrieb:

> Schon geschehen :-) -> data_xxx

Ah ja ok, aber da es jetzt auf dem Stack liegt, taucht es im Mapfile 
natürlich nicht mehr auf. Geht das Programm denn jetzt wenigstens?

von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal mit data_xxx als globale Variable.

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> Geht das Programm denn jetzt wenigstens?

nein, es ist egal ob die Variable auf dem heap liegt oder im RAM ...

von Nop (Gast)


Lesenswert?

Hmm also das Mapfile sieht gut aus:
1
Allocating common symbols
2
Common symbol       size              file
3
4
data_xxx            0x40              /tmp/ccwpjrt4.o
5
6
...
7
8
 COMMON         0x0000000020000480       0x40 /tmp/ccwpjrt4.o
9
                0x0000000020000480                data_xxx
10
                0x00000000200004c0                . = ALIGN (0x4)

Das Array liegt im RAM und hat auch die richtige Länge. Wieso das im 
Disassembly so aussieht, verstehe ich nicht, zumal das mit dem alten GCC 
auch so aussah und funktioniert hat. Wie sehen denn die Zeilen davor 
aus? Nicht immer wird das sauber sequentiell angezeigt. Möglicherweise 
wird R0 als Adresse für den Rücksprung benutzt?!

von Johannes S. (Gast)


Lesenswert?

diese Zeile ist noch gefährlich:
1
 for (int i=0; i<sizeof(data_xxx); i++) {
2
  data_xxx[i] = 0;

weil du mit sizeof(data_xxx) nicht die Anzahl der Elemente bekommst. In 
diesem Fall müsste es richtig sein, aber etwas besser ist dafür ein 
Makro in der Art
1
#define countof(arr) (sizeof(arr) / sizeof(arr[0]))
zu benutzen.

von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Hier sind die map und disassembler Dateien der 5.4.1.

von Nop (Gast)


Lesenswert?

Also, das Mapfile für den 5er GCC sieht genauso aus für data_xxx:
1
Allocating common symbols
2
Common symbol       size              file
3
4
data_xxx            0x40              /tmp/ccks9HZh.o
5
6
...
7
8
 COMMON         0x0000000020000480       0x40 /tmp/ccks9HZh.o
9
                0x0000000020000480                data_xxx
10
                0x00000000200004c0                . = ALIGN (0x4)

Zumindest würde ich das Linkerscript, was data_xxx angeht, als 
Verursacher damit ausschließen.

von Nop (Gast)


Lesenswert?

Johannes S. schrieb:
> an der memset Funktion hat sich nichts geändert,
> https://github.com/gcc-mirror/gcc/blob/gcc-6_3_0-r...

Da sieht memset so aus:
1
PTR
2
memset (PTR dest, register int val, register size_t len)
3
{
4
  register unsigned char *ptr = (unsigned char*)dest;
5
  while (len-- > 0)
6
    *ptr++ = val;
7
  return dest;
8
}

Das ist aber nicht das, was da im Code steht. Hier mal aus dem 5er Dump 
das Disassembly von memset:
1
0800152c <memset>:
2
 800152c:  b470        push  {r4, r5, r6}
3
 800152e:  0784        lsls  r4, r0, #30
4
 8001530:  d046        beq.n  80015c0 <memset+0x94>
5
 8001532:  1e54        subs  r4, r2, #1
6
 8001534:  2a00        cmp  r2, #0
7
 8001536:  d041        beq.n  80015bc <memset+0x90>
8
 8001538:  b2cd        uxtb  r5, r1
9
 800153a:  4603        mov  r3, r0
10
 800153c:  e002        b.n  8001544 <memset+0x18>
11
 800153e:  1e62        subs  r2, r4, #1
12
 8001540:  b3e4        cbz  r4, 80015bc <memset+0x90>
13
 8001542:  4614        mov  r4, r2
14
 8001544:  f803 5b01   strb.w  r5, [r3], #1
15
 8001548:  079a        lsls  r2, r3, #30
16
 800154a:  d1f8        bne.n  800153e <memset+0x12>
17
 800154c:  2c03        cmp  r4, #3
18
 800154e:  d92e        bls.n  80015ae <memset+0x82>
19
 8001550:  b2cd        uxtb  r5, r1
20
 8001552:  ea45 2505   orr.w  r5, r5, r5, lsl #8
21
 8001556:  2c0f        cmp  r4, #15
22
 8001558:  ea45 4505   orr.w  r5, r5, r5, lsl #16
23
 800155c:  d919        bls.n  8001592 <memset+0x66>
24
 800155e:  4626        mov  r6, r4
25
 8001560:  f103 0210   add.w  r2, r3, #16
26
 8001564:  3e10        subs  r6, #16
27
 8001566:  2e0f        cmp  r6, #15
28
 8001568:  f842 5c10   str.w  r5, [r2, #-16]
29
 800156c:  f842 5c0c   str.w  r5, [r2, #-12]
30
 8001570:  f842 5c08   str.w  r5, [r2, #-8]
31
 8001574:  f842 5c04   str.w  r5, [r2, #-4]
32
 8001578:  f102 0210   add.w  r2, r2, #16
33
 800157c:  d8f2        bhi.n  8001564 <memset+0x38>
34
 800157e:  f1a4 0210   sub.w  r2, r4, #16
35
 8001582:  f022 020f   bic.w  r2, r2, #15
36
 8001586:  f004 040f   and.w  r4, r4, #15
37
 800158a:  3210        adds  r2, #16
38
 800158c:  2c03        cmp  r4, #3
39
 800158e:  4413        add  r3, r2
40
 8001590:  d90d        bls.n  80015ae <memset+0x82>
41
 8001592:  461e        mov  r6, r3
42
 8001594:  4622        mov  r2, r4
43
 8001596:  3a04        subs  r2, #4
44
 8001598:  2a03        cmp  r2, #3
45
 800159a:  f846 5b04   str.w  r5, [r6], #4
46
 800159e:  d8fa        bhi.n  8001596 <memset+0x6a>
47
 80015a0:  1f22        subs  r2, r4, #4
48
 80015a2:  f022 0203   bic.w  r2, r2, #3
49
 80015a6:  3204        adds  r2, #4
50
 80015a8:  4413        add  r3, r2
51
 80015aa:  f004 0403   and.w  r4, r4, #3
52
 80015ae:  b12c        cbz  r4, 80015bc <memset+0x90>
53
 80015b0:  b2c9        uxtb  r1, r1
54
 80015b2:  441c        add  r4, r3
55
 80015b4:  f803 1b01   strb.w  r1, [r3], #1
56
 80015b8:  42a3        cmp  r3, r4
57
 80015ba:  d1fb        bne.n  80015b4 <memset+0x88>
58
 80015bc:  bc70        pop  {r4, r5, r6}
59
 80015be:  4770        bx  lr
60
 80015c0:  4614        mov  r4, r2
61
 80015c2:  4603        mov  r3, r0
62
 80015c4:  e7c2        b.n  800154c <memset+0x20>
63
 80015c6:  bf00        nop

Das ab Adresse 8001568 sieht doch stark nach Loop unrolling aus, was in 
der C-Version nicht drin ist. Zumal das Makefile hier auf O0 steht und 
daher kein automagisches Loop unrolling zu erwarten ist, zumal ich auch 
erstaunt wäre, wenn GCC das tatsächlich bei unbekannter Loop-Menge so 
optimieren könnte.

von Nop (Gast)


Lesenswert?

Ahhh ich habs, wie das mit dem r0 da geht:
1
 8001462:  4808        ldr  r0, [pc, #32]  ; (8001484 <main+0x68>)
2
...
3
 8001484:  20000480   .word  0x20000480

Also der speichert nach der Main im Flash die Adresse von data_xxx ab. 
In der oberen Zeile addiert er auf den program counter 32 drauf, das 
ergibt 8001484. Das, was an dieser Adresse steht, also 20000480, lädt er 
in r0 - und das ist genau die Startadresse des Buffers, die memset sehen 
will. Das paßt.

von Nop (Gast)


Lesenswert?

Jetzt die Preisfrage: wie sieht der vollständige Dump mit dem 6er GCC 
aus? Was steht da an 8001484?

von Unwissender (Gast)


Lesenswert?


von Nop (Gast)


Lesenswert?

Unwissender schrieb:
> Den findest Du hier:
>
> https://www.mikrocontroller.net/attachment/365304/...

Nicht das Mapfile, den Disassembly-Dump meine ich. Also das, was 
gcc-5.4.1-test.dump für den 5er ist, nur für den 6er.

von Unwissender (Gast)


Lesenswert?


von Nop (Gast)


Lesenswert?

Der Dump ist jetzt aber mit lokalem data_xxx. Laß mal lieber den 
6er-Dump mit globalem data_xxx angucken, denn dann verändern wir nur 
eine Sache zur Zeit - den Compiler.

von Nop (Gast)


Lesenswert?


von Unwissender (Gast)


Angehängte Dateien:

Lesenswert?

Biddeschön :-)

Danke schonmal für Deine Unterstützung. Auch an Johannes ...

von Nop (Gast)


Lesenswert?

Gut, also hier für den 6er:
1
  memset(data, 0x00, 64);
2
 80014f2:  4808        ldr  r0, [pc, #32]  ; (8001514 <main+0x68>)
3
...
4
 8001514:  20000480   .word  0x20000480

Auch das stimmt also. memset bekommt auch hier die richtige Adresse in 
r0.

von Johannes S. (Gast)


Lesenswert?

Mit der Adresse sehe ich das genauso, ist also doch richtig.

Bei der STM HAL/SPL Technik mit den Strukturen die gefüllt und an eine 
Funktion übergeben werden hatte ich aber auch mal einen blöden Fehler 
gesucht. Wenn die Struktur auf dem Stack liegt (wie die GPIO_InitTypeDef 
hier auch) hat die zufällige Inhalte. Die Struktur muss also erst mit 
einer passenden Init Funktion auf Defaultwerte gesetzt werden, für diese 
Struktur wäre das
1
GPIO_StructInit(&g);
In deinem Testcode werden alle Felder gesetzt und es sollte ok sein, 
aber das ist eine böse Falle wenn falsch initialisierte Felder irgendwas 
auslösen können. Auch wenn ST die Struktur erweitert kann das passieren 
und funktionierender Code Blödsinn machen.

von Unwissender (Gast)


Lesenswert?

Das ist ein guter Hinweis. Danke dafür.

von Johannes S. (Gast)


Lesenswert?


von Nop (Gast)


Lesenswert?

Also wenn man sich mal im Dump für den 5er an Adresse 0800152c <memset>: 
umguckt und das mit dem vergleicht, was beim 6er an 08001630 <memset>: 
zu finden ist, dann sind das doch einige Veränderungen. Der Quelltext 
mag sich nicht geändert haben, das Compilat aber schon.

Allerdings wird memset ja auch schon im CRT-Startupcode aufgerufen, in 
080001b0 <_mainCRTStartup>:, ohne daß es schiefgeht.

1) Hast Du wirklich alle Objektdateien bereinigt und auch nachgeprüft, 
daß wirklich alle weg sind?
2) Hast Du mal versucht, den Pfad des 5ers umzubenennen und dann mit dem 
6er zu compilieren? Nicht daß da was mit den Suchpfaden aus Versehen 
immer noch aus dem 5er genommen und dann mit dem 6er gemischt wird.
3) Kannst Du mit dem Debugger per Singlestep vorgehen und so genauer 
checken, an welcher Adresse es abstürzt?
4) Du könntest den gesamten SPL-Anteil auskommentieren und Deine 
toggle-Schleifen auf globalen volatile-Integern machen. Das würde den 
Scope noch mehr reduzieren.

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> 1) Hast Du wirklich alle Objektdateien bereinigt und auch nachgeprüft,
> daß wirklich alle weg sind?

Das Build-Verzeichnis habe ich immer wieder gelöscht. Ich kompiliere und 
linke in einem Schritt, so daß keine Objektdateien übrigbleiben. Ich 
habe auch in sämtlichen tmp-Verzeichnissen geschuat, ob sich da noch was 
altes versteckt. Nix ...

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> 2) Hast Du mal versucht, den Pfad des 5ers umzubenennen und dann mit dem
> 6er zu compilieren? Nicht daß da was mit den Suchpfaden aus Versehen
> immer noch aus dem 5er genommen und dann mit dem 6er gemischt wird.

Auf meinem Entwicklungsrechner gibt es nach dem Updaten von Ubuntu auf 
18.04 keinen arm-gcc 5 mehr. Ich habe auch nir eine einzige newlib 
gefunden.

Den Enwicklungsrechner habe ich vorher gebackupt und kann so mit chroot 
in diesem Backup mit arm-gcc 5 kompilieren.

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> 3) Kannst Du mit dem Debugger per Singlestep vorgehen und so genauer
> checken, an welcher Adresse es abstürzt?

Hab mit dem Debugger bisher kaum Erfahrung, mal sehen ob ich da was 
beisteuern kann ...

von Unwissender (Gast)


Lesenswert?

Nop schrieb:
> 4) Du könntest den gesamten SPL-Anteil auskommentieren und Deine
> toggle-Schleifen auf globalen volatile-Integern machen. Das würde den
> Scope noch mehr reduzieren.

Jepp, die SPL könnte ich noch rausschmeissen. Allerdings hat sich die 
auch gar nicht verändert. Aber das ganze wird wieder etwas 
überschaubarer.

von Unwissender (Gast)


Lesenswert?

Ich habe testweise mal einen aktuelleren gcc (7.2.1, 
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm) installiert. 
Siehe da, damit läuft mein Programm tadellos.

Schein so, als ob der 6.3.1 Dummheiten macht? Kann ich mir aber auch 
nicht so richtig vorstellen.

von Johannes S. (Gast)


Lesenswert?

ist schon mysteriös, memset ist ja keine soooo seltene Funktion.
Um dem Compiler weiter auf den Zahn zu fühlen könntest du auch mal 
andere Optimierungsstufen ausprobieren, als das -O0 im makefile durch 
-Os oder -O1...3 ersetzen.

von Bernd K. (prof7bit)


Lesenswert?

Unwissender schrieb:
> Schein so, als ob der 6.3.1 Dummheiten macht? Kann ich mir aber auch
> nicht so richtig vorstellen.

Versuch rauszufinden wie Du in Deiner IDE auf "Instruction Stepping" 
umstellst, bei solchen Sachen ist das ein unverzichtbares Werkzeug (In 
Eclipse ist das zum Beispiel der Button mit blauem i und gelbem Pfeil 
rechts neben den anderen Debug-Buttons in der Toolbar).

Dann steppst Du das gaaaanz langsam und konzentriert Instruktion für 
Instruktion durch und merkst Dir die letzte Adresse bevor er in den 
Hardfault springt.

Dann machst Du es nochmal aber diesmal bleibst Du genau dort stehen (an 
der Stelle an der es im nächsten Takt gekracht hätte) und schaust Dir 
alle Register an und den Befehl der jetzt als nächstes ausgeführt werden 
soll. Das wird Licht ins Dunkel bringen. Poste das Ergebnis hier.

: Bearbeitet durch User
von Unwissender (Gast)


Lesenswert?

Bernd K. schrieb:
> Versuch rauszufinden wie Du in Deiner IDE

Isch habe gar keine IDE :-)

von Bernd K. (prof7bit)


Lesenswert?

Unwissender schrieb:
> Bernd K. schrieb:
>> Versuch rauszufinden wie Du in Deiner IDE
>
> Isch habe gar keine IDE :-)

Dann nimm ddd oder kdbg. Es gibt keinen Grund auf Werkzeuge zu 
verzichten die einem das Leben einfacher machen.

IDE könntest Du Dir im Laufe der nächsten Zeit auch mal zulegen, Eclipse 
zum Beispiel kann problemlos mit Makefile Projekten arbeiten und hat 
auch ein gutes Debugger-Frontend und ein schönes Plugin für ARM und noch 
mehr nützliche Sachen.

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Wenn man's richtig hart will, kann man auch GDB auf der Kommandozeile 
nehmen, funktioniert auch. Hab ich bisher aber nur ein, zweimal 
gebraucht, und dann mit nem Linux dahinter statt bare metal.

von Johannes S. (Gast)


Lesenswert?

habe das mal ausprobiert, bei mir läufts auch mit der 6er Version,
1
 
2
D:\Projects\Sn\LocalGit\mbed-os-example-blinky>arm-none-eabi-gcc --version
3
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors 6-2017-q2-update) 6.3.1 20170620 (release) [ARM/embedded-6-branch revisio
4
n 249437]
Allerdings unter Windows und ich habe die SPL nicht, habe das in ein 
mbed Projekt reingepackt. Die memset Zeile und die for Schleife wie in 
deinem Test.
Läuft mit 6er und 7er Compiler, linker und compiler options sind 
natürlich auch unterschiedlich, auber auch für das Bluepill Board mit 
dem F103C8.
1
#include "mbed.h"
2
3
DigitalOut led1(LED1);
4
char data_xxx[64];
5
6
// main() runs in its own thread in the OS
7
int main() {
8
9
  for (int i=0; i<sizeof(data_xxx); i++) {
10
    data_xxx[i] = 0;
11
  }
12
13
  memset(data_xxx, 0x00, 64);    
14
    
15
  while (true) {
16
    
17
    led1 = 0;
18
    
19
        wait_ms(100);
20
21
        led1 = 1;
22
    
23
        wait_ms(100);
24
    }
25
}

von Unwissender (Gast)


Lesenswert?

Wenn ich die Toolchain von 
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm verwende, 
funktionierts bei mir auch mit der 6.3.1. Scheints ein Problem im Ubuntu 
zu sein ...

von Nop (Gast)


Lesenswert?

Wär nicht das erste Mal, daß Maintainer korrekten Code vom Upstream 
verbasteln. Vielleicht ist beim Paketieren auch was schiefgeaufen. Oder 
die Version ist von einem anderen Stand.

von Unwissender (Gast)


Lesenswert?

Herlichen Dank an alle, die hier was dazubeigetragen haben. Mein Problem 
ist gelöst.

Und das mit dem Debugging und der IDE werde ich mir mal vornehmen :-)

von Johannes S. (Gast)


Lesenswert?

Das scheint das gleiche Problem zu sein:
https://bugs.launchpad.net/ubuntu/+source/newlib/+bug/1768125

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.